| 1 | 
           efrain | 
           1 | 
           <?php
  | 
        
        
            | 
            | 
           2 | 
           // This file is part of Moodle - http://moodle.org/
  | 
        
        
            | 
            | 
           3 | 
           //
  | 
        
        
            | 
            | 
           4 | 
           // Moodle is free software: you can redistribute it and/or modify
  | 
        
        
            | 
            | 
           5 | 
           // it under the terms of the GNU General Public License as published by
  | 
        
        
            | 
            | 
           6 | 
           // the Free Software Foundation, either version 3 of the License, or
  | 
        
        
            | 
            | 
           7 | 
           // (at your option) any later version.
  | 
        
        
            | 
            | 
           8 | 
           //
  | 
        
        
            | 
            | 
           9 | 
           // Moodle is distributed in the hope that it will be useful,
  | 
        
        
            | 
            | 
           10 | 
           // but WITHOUT ANY WARRANTY; without even the implied warranty of
  | 
        
        
            | 
            | 
           11 | 
           // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  | 
        
        
            | 
            | 
           12 | 
           // GNU General Public License for more details.
  | 
        
        
            | 
            | 
           13 | 
           //
  | 
        
        
            | 
            | 
           14 | 
           // You should have received a copy of the GNU General Public License
  | 
        
        
            | 
            | 
           15 | 
           // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  | 
        
        
            | 
            | 
           16 | 
              | 
        
        
            | 
            | 
           17 | 
           /**
  | 
        
        
            | 
            | 
           18 | 
            * External course functions unit tests
  | 
        
        
            | 
            | 
           19 | 
            *
  | 
        
        
            | 
            | 
           20 | 
            * @package    core_course
  | 
        
        
            | 
            | 
           21 | 
            * @category   external
  | 
        
        
            | 
            | 
           22 | 
            * @copyright  2012 Jerome Mouneyrac
  | 
        
        
            | 
            | 
           23 | 
            * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  | 
        
        
            | 
            | 
           24 | 
            */
  | 
        
        
            | 
            | 
           25 | 
              | 
        
        
            | 
            | 
           26 | 
           use \core_external\external_api;
  | 
        
        
            | 
            | 
           27 | 
              | 
        
        
            | 
            | 
           28 | 
           defined('MOODLE_INTERNAL') || die();
  | 
        
        
            | 
            | 
           29 | 
              | 
        
        
            | 
            | 
           30 | 
           global $CFG;
  | 
        
        
            | 
            | 
           31 | 
              | 
        
        
            | 
            | 
           32 | 
           require_once($CFG->dirroot . '/webservice/tests/helpers.php');
  | 
        
        
            | 
            | 
           33 | 
              | 
        
        
            | 
            | 
           34 | 
           /**
  | 
        
        
            | 
            | 
           35 | 
            * External course functions unit tests
  | 
        
        
            | 
            | 
           36 | 
            *
  | 
        
        
            | 
            | 
           37 | 
            * @package    core_course
  | 
        
        
            | 
            | 
           38 | 
            * @category   external
  | 
        
        
            | 
            | 
           39 | 
            * @copyright  2012 Jerome Mouneyrac
  | 
        
        
            | 
            | 
           40 | 
            * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  | 
        
        
            | 
            | 
           41 | 
            */
  | 
        
        
           | 11 | 
           efrain | 
           42 | 
           final class externallib_test extends externallib_advanced_testcase {
  | 
        
        
           | 1 | 
           efrain | 
           43 | 
              | 
        
        
            | 
            | 
           44 | 
               /**
  | 
        
        
            | 
            | 
           45 | 
                * Tests set up
  | 
        
        
            | 
            | 
           46 | 
                */
  | 
        
        
            | 
            | 
           47 | 
               protected function setUp(): void {
  | 
        
        
            | 
            | 
           48 | 
                   global $CFG;
  | 
        
        
            | 
            | 
           49 | 
                   require_once($CFG->dirroot . '/course/externallib.php');
  | 
        
        
            | 
            | 
           50 | 
               }
  | 
        
        
            | 
            | 
           51 | 
              | 
        
        
            | 
            | 
           52 | 
               /**
  | 
        
        
            | 
            | 
           53 | 
                * Test create_categories
  | 
        
        
            | 
            | 
           54 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           55 | 
               public function test_create_categories(): void {
  | 
        
        
           | 1 | 
           efrain | 
           56 | 
              | 
        
        
            | 
            | 
           57 | 
                   global $DB;
  | 
        
        
            | 
            | 
           58 | 
              | 
        
        
            | 
            | 
           59 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           60 | 
              | 
        
        
            | 
            | 
           61 | 
                   // Set the required capabilities by the external function
  | 
        
        
            | 
            | 
           62 | 
                   $contextid = context_system::instance()->id;
  | 
        
        
            | 
            | 
           63 | 
                   $roleid = $this->assignUserCapability('moodle/category:manage', $contextid);
  | 
        
        
            | 
            | 
           64 | 
              | 
        
        
            | 
            | 
           65 | 
                   // Create base categories.
  | 
        
        
            | 
            | 
           66 | 
                   $category1 = new stdClass();
  | 
        
        
            | 
            | 
           67 | 
                   $category1->name = 'Root Test Category 1';
  | 
        
        
            | 
            | 
           68 | 
                   $category2 = new stdClass();
  | 
        
        
            | 
            | 
           69 | 
                   $category2->name = 'Root Test Category 2';
  | 
        
        
            | 
            | 
           70 | 
                   $category2->idnumber = 'rootcattest2';
  | 
        
        
            | 
            | 
           71 | 
                   $category2->desc = 'Description for root test category 1';
  | 
        
        
            | 
            | 
           72 | 
                   $category2->theme = 'classic';
  | 
        
        
            | 
            | 
           73 | 
                   $categories = array(
  | 
        
        
            | 
            | 
           74 | 
                       array('name' => $category1->name, 'parent' => 0),
  | 
        
        
            | 
            | 
           75 | 
                       array('name' => $category2->name, 'parent' => 0, 'idnumber' => $category2->idnumber,
  | 
        
        
            | 
            | 
           76 | 
                           'description' => $category2->desc, 'theme' => $category2->theme)
  | 
        
        
            | 
            | 
           77 | 
                   );
  | 
        
        
            | 
            | 
           78 | 
              | 
        
        
            | 
            | 
           79 | 
                   $createdcats = core_course_external::create_categories($categories);
  | 
        
        
            | 
            | 
           80 | 
              | 
        
        
            | 
            | 
           81 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           82 | 
                   $createdcats = external_api::clean_returnvalue(core_course_external::create_categories_returns(), $createdcats);
  | 
        
        
            | 
            | 
           83 | 
              | 
        
        
            | 
            | 
           84 | 
                   // Initially confirm that base data was inserted correctly.
  | 
        
        
            | 
            | 
           85 | 
                   $this->assertEquals($category1->name, $createdcats[0]['name']);
  | 
        
        
            | 
            | 
           86 | 
                   $this->assertEquals($category2->name, $createdcats[1]['name']);
  | 
        
        
            | 
            | 
           87 | 
              | 
        
        
            | 
            | 
           88 | 
                   // Save the ids.
  | 
        
        
            | 
            | 
           89 | 
                   $category1->id = $createdcats[0]['id'];
  | 
        
        
            | 
            | 
           90 | 
                   $category2->id = $createdcats[1]['id'];
  | 
        
        
            | 
            | 
           91 | 
              | 
        
        
            | 
            | 
           92 | 
                   // Create on sub category.
  | 
        
        
            | 
            | 
           93 | 
                   $category3 = new stdClass();
  | 
        
        
            | 
            | 
           94 | 
                   $category3->name = 'Sub Root Test Category 3';
  | 
        
        
            | 
            | 
           95 | 
                   $subcategories = array(
  | 
        
        
            | 
            | 
           96 | 
                       array('name' => $category3->name, 'parent' => $category1->id)
  | 
        
        
            | 
            | 
           97 | 
                   );
  | 
        
        
            | 
            | 
           98 | 
              | 
        
        
            | 
            | 
           99 | 
                   $createdsubcats = core_course_external::create_categories($subcategories);
  | 
        
        
            | 
            | 
           100 | 
              | 
        
        
            | 
            | 
           101 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           102 | 
                   $createdsubcats = external_api::clean_returnvalue(core_course_external::create_categories_returns(), $createdsubcats);
  | 
        
        
            | 
            | 
           103 | 
              | 
        
        
            | 
            | 
           104 | 
                   // Confirm that sub categories were inserted correctly.
  | 
        
        
            | 
            | 
           105 | 
                   $this->assertEquals($category3->name, $createdsubcats[0]['name']);
  | 
        
        
            | 
            | 
           106 | 
              | 
        
        
            | 
            | 
           107 | 
                   // Save the ids.
  | 
        
        
            | 
            | 
           108 | 
                   $category3->id = $createdsubcats[0]['id'];
  | 
        
        
            | 
            | 
           109 | 
              | 
        
        
            | 
            | 
           110 | 
                   // Calling the ws function should provide a new sortorder to give category1,
  | 
        
        
            | 
            | 
           111 | 
                   // category2, category3. New course categories are ordered by id not name.
  | 
        
        
            | 
            | 
           112 | 
                   $category1 = $DB->get_record('course_categories', array('id' => $category1->id));
  | 
        
        
            | 
            | 
           113 | 
                   $category2 = $DB->get_record('course_categories', array('id' => $category2->id));
  | 
        
        
            | 
            | 
           114 | 
                   $category3 = $DB->get_record('course_categories', array('id' => $category3->id));
  | 
        
        
            | 
            | 
           115 | 
              | 
        
        
            | 
            | 
           116 | 
                   // sortorder sequence (and sortorder) must be:
  | 
        
        
            | 
            | 
           117 | 
                   // category 1
  | 
        
        
            | 
            | 
           118 | 
                   //   category 3
  | 
        
        
            | 
            | 
           119 | 
                   // category 2
  | 
        
        
            | 
            | 
           120 | 
                   $this->assertGreaterThan($category1->sortorder, $category3->sortorder);
  | 
        
        
            | 
            | 
           121 | 
                   $this->assertGreaterThan($category3->sortorder, $category2->sortorder);
  | 
        
        
            | 
            | 
           122 | 
              | 
        
        
            | 
            | 
           123 | 
                   // Call without required capability
  | 
        
        
            | 
            | 
           124 | 
                   $this->unassignUserCapability('moodle/category:manage', $contextid, $roleid);
  | 
        
        
            | 
            | 
           125 | 
                   $this->expectException('required_capability_exception');
  | 
        
        
            | 
            | 
           126 | 
                   $createdsubcats = core_course_external::create_categories($subcategories);
  | 
        
        
            | 
            | 
           127 | 
              | 
        
        
            | 
            | 
           128 | 
               }
  | 
        
        
            | 
            | 
           129 | 
              | 
        
        
            | 
            | 
           130 | 
               /**
  | 
        
        
            | 
            | 
           131 | 
                * Test delete categories
  | 
        
        
            | 
            | 
           132 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           133 | 
               public function test_delete_categories(): void {
  | 
        
        
           | 1 | 
           efrain | 
           134 | 
                   global $DB;
  | 
        
        
            | 
            | 
           135 | 
              | 
        
        
            | 
            | 
           136 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           137 | 
              | 
        
        
            | 
            | 
           138 | 
                   // Set the required capabilities by the external function
  | 
        
        
            | 
            | 
           139 | 
                   $contextid = context_system::instance()->id;
  | 
        
        
            | 
            | 
           140 | 
                   $roleid = $this->assignUserCapability('moodle/category:manage', $contextid);
  | 
        
        
            | 
            | 
           141 | 
              | 
        
        
            | 
            | 
           142 | 
                   $category1  = self::getDataGenerator()->create_category();
  | 
        
        
            | 
            | 
           143 | 
                   $category2  = self::getDataGenerator()->create_category(
  | 
        
        
            | 
            | 
           144 | 
                           array('parent' => $category1->id));
  | 
        
        
            | 
            | 
           145 | 
                   $category3  = self::getDataGenerator()->create_category();
  | 
        
        
            | 
            | 
           146 | 
                   $category4  = self::getDataGenerator()->create_category(
  | 
        
        
            | 
            | 
           147 | 
                           array('parent' => $category3->id));
  | 
        
        
            | 
            | 
           148 | 
                   $category5  = self::getDataGenerator()->create_category(
  | 
        
        
            | 
            | 
           149 | 
                           array('parent' => $category4->id));
  | 
        
        
            | 
            | 
           150 | 
              | 
        
        
            | 
            | 
           151 | 
                   //delete category 1 and 2 + delete category 4, category 5 moved under category 3
  | 
        
        
            | 
            | 
           152 | 
                   core_course_external::delete_categories(array(
  | 
        
        
            | 
            | 
           153 | 
                       array('id' => $category1->id, 'recursive' => 1),
  | 
        
        
            | 
            | 
           154 | 
                       array('id' => $category4->id)
  | 
        
        
            | 
            | 
           155 | 
                   ));
  | 
        
        
            | 
            | 
           156 | 
              | 
        
        
            | 
            | 
           157 | 
                   //check $category 1 and 2 are deleted
  | 
        
        
            | 
            | 
           158 | 
                   $notdeletedcount = $DB->count_records_select('course_categories',
  | 
        
        
            | 
            | 
           159 | 
                       'id IN ( ' . $category1->id . ',' . $category2->id . ',' . $category4->id . ')');
  | 
        
        
            | 
            | 
           160 | 
                   $this->assertEquals(0, $notdeletedcount);
  | 
        
        
            | 
            | 
           161 | 
              | 
        
        
            | 
            | 
           162 | 
                   //check that $category5 as $category3 for parent
  | 
        
        
            | 
            | 
           163 | 
                   $dbcategory5 = $DB->get_record('course_categories', array('id' => $category5->id));
  | 
        
        
            | 
            | 
           164 | 
                   $this->assertEquals($dbcategory5->path, $category3->path . '/' . $category5->id);
  | 
        
        
            | 
            | 
           165 | 
              | 
        
        
            | 
            | 
           166 | 
                    // Call without required capability
  | 
        
        
            | 
            | 
           167 | 
                   $this->unassignUserCapability('moodle/category:manage', $contextid, $roleid);
  | 
        
        
            | 
            | 
           168 | 
                   $this->expectException('required_capability_exception');
  | 
        
        
            | 
            | 
           169 | 
                   $createdsubcats = core_course_external::delete_categories(
  | 
        
        
            | 
            | 
           170 | 
                           array(array('id' => $category3->id)));
  | 
        
        
            | 
            | 
           171 | 
               }
  | 
        
        
            | 
            | 
           172 | 
              | 
        
        
            | 
            | 
           173 | 
               /**
  | 
        
        
            | 
            | 
           174 | 
                * Test get categories
  | 
        
        
            | 
            | 
           175 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           176 | 
               public function test_get_categories(): void {
  | 
        
        
           | 1 | 
           efrain | 
           177 | 
                   global $DB;
  | 
        
        
            | 
            | 
           178 | 
              | 
        
        
            | 
            | 
           179 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           180 | 
              | 
        
        
            | 
            | 
           181 | 
                   $generatedcats = array();
  | 
        
        
            | 
            | 
           182 | 
                   $category1data['idnumber'] = 'idnumbercat1';
  | 
        
        
            | 
            | 
           183 | 
                   $category1data['name'] = 'Category 1 for PHPunit test';
  | 
        
        
            | 
            | 
           184 | 
                   $category1data['description'] = 'Category 1 description';
  | 
        
        
            | 
            | 
           185 | 
                   $category1data['descriptionformat'] = FORMAT_MOODLE;
  | 
        
        
            | 
            | 
           186 | 
                   $category1  = self::getDataGenerator()->create_category($category1data);
  | 
        
        
            | 
            | 
           187 | 
                   $generatedcats[$category1->id] = $category1;
  | 
        
        
            | 
            | 
           188 | 
                   $category2  = self::getDataGenerator()->create_category(
  | 
        
        
            | 
            | 
           189 | 
                           array('parent' => $category1->id));
  | 
        
        
            | 
            | 
           190 | 
                   $generatedcats[$category2->id] = $category2;
  | 
        
        
            | 
            | 
           191 | 
                   $category6  = self::getDataGenerator()->create_category(
  | 
        
        
            | 
            | 
           192 | 
                           array('parent' => $category1->id, 'visible' => 0));
  | 
        
        
            | 
            | 
           193 | 
                   $generatedcats[$category6->id] = $category6;
  | 
        
        
            | 
            | 
           194 | 
                   $category3  = self::getDataGenerator()->create_category();
  | 
        
        
            | 
            | 
           195 | 
                   $generatedcats[$category3->id] = $category3;
  | 
        
        
            | 
            | 
           196 | 
                   $category4  = self::getDataGenerator()->create_category(
  | 
        
        
            | 
            | 
           197 | 
                           array('parent' => $category3->id));
  | 
        
        
            | 
            | 
           198 | 
                   $generatedcats[$category4->id] = $category4;
  | 
        
        
            | 
            | 
           199 | 
                   $category5  = self::getDataGenerator()->create_category(
  | 
        
        
            | 
            | 
           200 | 
                           array('parent' => $category4->id));
  | 
        
        
            | 
            | 
           201 | 
                   $generatedcats[$category5->id] = $category5;
  | 
        
        
            | 
            | 
           202 | 
              | 
        
        
            | 
            | 
           203 | 
                   // Set the required capabilities by the external function.
  | 
        
        
            | 
            | 
           204 | 
                   $context = context_system::instance();
  | 
        
        
            | 
            | 
           205 | 
                   $roleid = $this->assignUserCapability('moodle/category:manage', $context->id);
  | 
        
        
            | 
            | 
           206 | 
                   $this->assignUserCapability('moodle/category:viewhiddencategories', $context->id, $roleid);
  | 
        
        
            | 
            | 
           207 | 
              | 
        
        
            | 
            | 
           208 | 
                   // Retrieve category1 + sub-categories except not visible ones
  | 
        
        
            | 
            | 
           209 | 
                   $categories = core_course_external::get_categories(array(
  | 
        
        
            | 
            | 
           210 | 
                       array('key' => 'id', 'value' => $category1->id),
  | 
        
        
            | 
            | 
           211 | 
                       array('key' => 'visible', 'value' => 1)), 1);
  | 
        
        
            | 
            | 
           212 | 
              | 
        
        
            | 
            | 
           213 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           214 | 
                   $categories = external_api::clean_returnvalue(core_course_external::get_categories_returns(), $categories);
  | 
        
        
            | 
            | 
           215 | 
              | 
        
        
            | 
            | 
           216 | 
                   // Check we retrieve the good total number of categories.
  | 
        
        
            | 
            | 
           217 | 
                   $this->assertEquals(2, count($categories));
  | 
        
        
            | 
            | 
           218 | 
              | 
        
        
            | 
            | 
           219 | 
                   // Check the return values
  | 
        
        
            | 
            | 
           220 | 
                   foreach ($categories as $category) {
  | 
        
        
            | 
            | 
           221 | 
                       $generatedcat = $generatedcats[$category['id']];
  | 
        
        
            | 
            | 
           222 | 
                       $this->assertEquals($category['idnumber'], $generatedcat->idnumber);
  | 
        
        
            | 
            | 
           223 | 
                       $this->assertEquals($category['name'], $generatedcat->name);
  | 
        
        
            | 
            | 
           224 | 
                       // Description was converted to the HTML format.
  | 
        
        
            | 
            | 
           225 | 
                       $this->assertEquals($category['description'], format_text($generatedcat->description, FORMAT_MOODLE, array('para' => false)));
  | 
        
        
            | 
            | 
           226 | 
                       $this->assertEquals($category['descriptionformat'], FORMAT_HTML);
  | 
        
        
            | 
            | 
           227 | 
                   }
  | 
        
        
            | 
            | 
           228 | 
              | 
        
        
            | 
            | 
           229 | 
                   // Check categories by ids.
  | 
        
        
            | 
            | 
           230 | 
                   $ids = implode(',', array_keys($generatedcats));
  | 
        
        
            | 
            | 
           231 | 
                   $categories = core_course_external::get_categories(array(
  | 
        
        
            | 
            | 
           232 | 
                       array('key' => 'ids', 'value' => $ids)), 0);
  | 
        
        
            | 
            | 
           233 | 
              | 
        
        
            | 
            | 
           234 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           235 | 
                   $categories = external_api::clean_returnvalue(core_course_external::get_categories_returns(), $categories);
  | 
        
        
            | 
            | 
           236 | 
              | 
        
        
            | 
            | 
           237 | 
                   // Check we retrieve the good total number of categories.
  | 
        
        
            | 
            | 
           238 | 
                   $this->assertEquals(6, count($categories));
  | 
        
        
            | 
            | 
           239 | 
                   // Check ids.
  | 
        
        
            | 
            | 
           240 | 
                   $returnedids = [];
  | 
        
        
            | 
            | 
           241 | 
                   foreach ($categories as $category) {
  | 
        
        
            | 
            | 
           242 | 
                       $returnedids[] = $category['id'];
  | 
        
        
            | 
            | 
           243 | 
                   }
  | 
        
        
            | 
            | 
           244 | 
                   // Sort the arrays upon comparision.
  | 
        
        
            | 
            | 
           245 | 
                   $this->assertEqualsCanonicalizing(array_keys($generatedcats), $returnedids);
  | 
        
        
            | 
            | 
           246 | 
              | 
        
        
            | 
            | 
           247 | 
                   // Check different params.
  | 
        
        
            | 
            | 
           248 | 
                   $categories = core_course_external::get_categories(array(
  | 
        
        
            | 
            | 
           249 | 
                       array('key' => 'id', 'value' => $category1->id),
  | 
        
        
            | 
            | 
           250 | 
                       array('key' => 'ids', 'value' => $category1->id),
  | 
        
        
            | 
            | 
           251 | 
                       array('key' => 'idnumber', 'value' => $category1->idnumber),
  | 
        
        
            | 
            | 
           252 | 
                       array('key' => 'visible', 'value' => 1)), 0);
  | 
        
        
            | 
            | 
           253 | 
              | 
        
        
            | 
            | 
           254 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           255 | 
                   $categories = external_api::clean_returnvalue(core_course_external::get_categories_returns(), $categories);
  | 
        
        
            | 
            | 
           256 | 
              | 
        
        
            | 
            | 
           257 | 
                   $this->assertEquals(1, count($categories));
  | 
        
        
            | 
            | 
           258 | 
              | 
        
        
            | 
            | 
           259 | 
                   // Same query, but forcing a parameters clean.
  | 
        
        
            | 
            | 
           260 | 
                   $categories = core_course_external::get_categories(array(
  | 
        
        
            | 
            | 
           261 | 
                       array('key' => 'id', 'value' => "$category1->id"),
  | 
        
        
            | 
            | 
           262 | 
                       array('key' => 'idnumber', 'value' => $category1->idnumber),
  | 
        
        
            | 
            | 
           263 | 
                       array('key' => 'name', 'value' => $category1->name . "<br/>"),
  | 
        
        
            | 
            | 
           264 | 
                       array('key' => 'visible', 'value' => '1')), 0);
  | 
        
        
            | 
            | 
           265 | 
                   $categories = external_api::clean_returnvalue(core_course_external::get_categories_returns(), $categories);
  | 
        
        
            | 
            | 
           266 | 
              | 
        
        
            | 
            | 
           267 | 
                   $this->assertEquals(1, count($categories));
  | 
        
        
            | 
            | 
           268 | 
              | 
        
        
            | 
            | 
           269 | 
                   // Retrieve categories from parent.
  | 
        
        
            | 
            | 
           270 | 
                   $categories = core_course_external::get_categories(array(
  | 
        
        
            | 
            | 
           271 | 
                       array('key' => 'parent', 'value' => $category3->id)), 1);
  | 
        
        
            | 
            | 
           272 | 
                   $categories = external_api::clean_returnvalue(core_course_external::get_categories_returns(), $categories);
  | 
        
        
            | 
            | 
           273 | 
              | 
        
        
            | 
            | 
           274 | 
                   $this->assertEquals(2, count($categories));
  | 
        
        
            | 
            | 
           275 | 
              | 
        
        
            | 
            | 
           276 | 
                   // Retrieve all categories.
  | 
        
        
            | 
            | 
           277 | 
                   $categories = core_course_external::get_categories();
  | 
        
        
            | 
            | 
           278 | 
              | 
        
        
            | 
            | 
           279 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           280 | 
                   $categories = external_api::clean_returnvalue(core_course_external::get_categories_returns(), $categories);
  | 
        
        
            | 
            | 
           281 | 
              | 
        
        
            | 
            | 
           282 | 
                   $this->assertEquals($DB->count_records('course_categories'), count($categories));
  | 
        
        
            | 
            | 
           283 | 
              | 
        
        
            | 
            | 
           284 | 
                   $this->unassignUserCapability('moodle/category:viewhiddencategories', $context->id, $roleid);
  | 
        
        
            | 
            | 
           285 | 
              | 
        
        
            | 
            | 
           286 | 
                   // Ensure maxdepthcategory is 2 and retrieve all categories without category:viewhiddencategories capability.
  | 
        
        
            | 
            | 
           287 | 
                   // It should retrieve all visible categories as well.
  | 
        
        
            | 
            | 
           288 | 
                   set_config('maxcategorydepth', 2);
  | 
        
        
            | 
            | 
           289 | 
                   $categories = core_course_external::get_categories();
  | 
        
        
            | 
            | 
           290 | 
              | 
        
        
            | 
            | 
           291 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           292 | 
                   $categories = external_api::clean_returnvalue(core_course_external::get_categories_returns(), $categories);
  | 
        
        
            | 
            | 
           293 | 
              | 
        
        
            | 
            | 
           294 | 
                   $this->assertEquals($DB->count_records('course_categories', array('visible' => 1)), count($categories));
  | 
        
        
            | 
            | 
           295 | 
              | 
        
        
            | 
            | 
           296 | 
                   // Call without required capability (it will fail cause of the search on idnumber).
  | 
        
        
            | 
            | 
           297 | 
                   $this->expectException('moodle_exception');
  | 
        
        
            | 
            | 
           298 | 
                   $categories = core_course_external::get_categories(array(
  | 
        
        
            | 
            | 
           299 | 
                       array('key' => 'id', 'value' => $category1->id),
  | 
        
        
            | 
            | 
           300 | 
                       array('key' => 'idnumber', 'value' => $category1->idnumber),
  | 
        
        
            | 
            | 
           301 | 
                       array('key' => 'visible', 'value' => 1)), 0);
  | 
        
        
            | 
            | 
           302 | 
               }
  | 
        
        
            | 
            | 
           303 | 
              | 
        
        
            | 
            | 
           304 | 
               /**
  | 
        
        
            | 
            | 
           305 | 
                * Test update_categories
  | 
        
        
            | 
            | 
           306 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           307 | 
               public function test_update_categories(): void {
  | 
        
        
           | 1 | 
           efrain | 
           308 | 
                   global $DB;
  | 
        
        
            | 
            | 
           309 | 
              | 
        
        
            | 
            | 
           310 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           311 | 
              | 
        
        
            | 
            | 
           312 | 
                   // Set the required capabilities by the external function
  | 
        
        
            | 
            | 
           313 | 
                   $contextid = context_system::instance()->id;
  | 
        
        
            | 
            | 
           314 | 
                   $roleid = $this->assignUserCapability('moodle/category:manage', $contextid);
  | 
        
        
            | 
            | 
           315 | 
              | 
        
        
            | 
            | 
           316 | 
                   // Create base categories.
  | 
        
        
            | 
            | 
           317 | 
                   $category1data['idnumber'] = 'idnumbercat1';
  | 
        
        
            | 
            | 
           318 | 
                   $category1data['name'] = 'Category 1 for PHPunit test';
  | 
        
        
            | 
            | 
           319 | 
                   $category1data['description'] = 'Category 1 description';
  | 
        
        
            | 
            | 
           320 | 
                   $category1data['descriptionformat'] = FORMAT_MOODLE;
  | 
        
        
            | 
            | 
           321 | 
                   $category1  = self::getDataGenerator()->create_category($category1data);
  | 
        
        
            | 
            | 
           322 | 
                   $category2  = self::getDataGenerator()->create_category(
  | 
        
        
            | 
            | 
           323 | 
                           array('parent' => $category1->id));
  | 
        
        
            | 
            | 
           324 | 
                   $category3  = self::getDataGenerator()->create_category();
  | 
        
        
            | 
            | 
           325 | 
                   $category4  = self::getDataGenerator()->create_category(
  | 
        
        
            | 
            | 
           326 | 
                           array('parent' => $category3->id));
  | 
        
        
            | 
            | 
           327 | 
                   $category5  = self::getDataGenerator()->create_category(
  | 
        
        
            | 
            | 
           328 | 
                           array('parent' => $category4->id));
  | 
        
        
            | 
            | 
           329 | 
              | 
        
        
            | 
            | 
           330 | 
                   // We update all category1 attribut.
  | 
        
        
            | 
            | 
           331 | 
                   // Then we move cat4 and cat5 parent: cat3 => cat1
  | 
        
        
            | 
            | 
           332 | 
                   $categories = array(
  | 
        
        
            | 
            | 
           333 | 
                       array('id' => $category1->id,
  | 
        
        
            | 
            | 
           334 | 
                           'name' => $category1->name . '_updated',
  | 
        
        
            | 
            | 
           335 | 
                           'idnumber' => $category1->idnumber . '_updated',
  | 
        
        
            | 
            | 
           336 | 
                           'description' => $category1->description . '_updated',
  | 
        
        
            | 
            | 
           337 | 
                           'descriptionformat' => FORMAT_HTML,
  | 
        
        
            | 
            | 
           338 | 
                           'theme' => $category1->theme),
  | 
        
        
            | 
            | 
           339 | 
                       array('id' => $category4->id, 'parent' => $category1->id));
  | 
        
        
            | 
            | 
           340 | 
              | 
        
        
            | 
            | 
           341 | 
                   core_course_external::update_categories($categories);
  | 
        
        
            | 
            | 
           342 | 
              | 
        
        
            | 
            | 
           343 | 
                   // Check the values were updated.
  | 
        
        
            | 
            | 
           344 | 
                   $dbcategories = $DB->get_records_select('course_categories',
  | 
        
        
            | 
            | 
           345 | 
                           'id IN (' . $category1->id . ',' . $category2->id . ',' . $category2->id
  | 
        
        
            | 
            | 
           346 | 
                           . ',' . $category3->id . ',' . $category4->id . ',' . $category5->id .')');
  | 
        
        
            | 
            | 
           347 | 
                   $this->assertEquals($category1->name . '_updated',
  | 
        
        
            | 
            | 
           348 | 
                           $dbcategories[$category1->id]->name);
  | 
        
        
            | 
            | 
           349 | 
                   $this->assertEquals($category1->idnumber . '_updated',
  | 
        
        
            | 
            | 
           350 | 
                           $dbcategories[$category1->id]->idnumber);
  | 
        
        
            | 
            | 
           351 | 
                   $this->assertEquals($category1->description . '_updated',
  | 
        
        
            | 
            | 
           352 | 
                           $dbcategories[$category1->id]->description);
  | 
        
        
            | 
            | 
           353 | 
                   $this->assertEquals(FORMAT_HTML, $dbcategories[$category1->id]->descriptionformat);
  | 
        
        
            | 
            | 
           354 | 
              | 
        
        
            | 
            | 
           355 | 
                   // Check that category4 and category5 have been properly moved.
  | 
        
        
            | 
            | 
           356 | 
                   $this->assertEquals('/' . $category1->id . '/' . $category4->id,
  | 
        
        
            | 
            | 
           357 | 
                           $dbcategories[$category4->id]->path);
  | 
        
        
            | 
            | 
           358 | 
                   $this->assertEquals('/' . $category1->id . '/' . $category4->id . '/' . $category5->id,
  | 
        
        
            | 
            | 
           359 | 
                           $dbcategories[$category5->id]->path);
  | 
        
        
            | 
            | 
           360 | 
              | 
        
        
            | 
            | 
           361 | 
                   // Call without required capability.
  | 
        
        
            | 
            | 
           362 | 
                   $this->unassignUserCapability('moodle/category:manage', $contextid, $roleid);
  | 
        
        
            | 
            | 
           363 | 
                   $this->expectException('required_capability_exception');
  | 
        
        
            | 
            | 
           364 | 
                   core_course_external::update_categories($categories);
  | 
        
        
            | 
            | 
           365 | 
               }
  | 
        
        
            | 
            | 
           366 | 
              | 
        
        
            | 
            | 
           367 | 
               /**
  | 
        
        
            | 
            | 
           368 | 
                * Test update_categories method for moving categories
  | 
        
        
            | 
            | 
           369 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           370 | 
               public function test_update_categories_moving(): void {
  | 
        
        
           | 1 | 
           efrain | 
           371 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           372 | 
              | 
        
        
            | 
            | 
           373 | 
                   // Create data.
  | 
        
        
            | 
            | 
           374 | 
                   $categorya  = self::getDataGenerator()->create_category([
  | 
        
        
            | 
            | 
           375 | 
                       'name' => 'CAT_A',
  | 
        
        
            | 
            | 
           376 | 
                   ]);
  | 
        
        
            | 
            | 
           377 | 
                   $categoryasub = self::getDataGenerator()->create_category([
  | 
        
        
            | 
            | 
           378 | 
                       'name' => 'SUBCAT_A',
  | 
        
        
            | 
            | 
           379 | 
                       'parent' => $categorya->id
  | 
        
        
            | 
            | 
           380 | 
                   ]);
  | 
        
        
            | 
            | 
           381 | 
                   $categoryb  = self::getDataGenerator()->create_category([
  | 
        
        
            | 
            | 
           382 | 
                       'name' => 'CAT_B',
  | 
        
        
            | 
            | 
           383 | 
                   ]);
  | 
        
        
            | 
            | 
           384 | 
              | 
        
        
            | 
            | 
           385 | 
                   // Create a new test user.
  | 
        
        
            | 
            | 
           386 | 
                   $testuser = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           387 | 
                   $this->setUser($testuser);
  | 
        
        
            | 
            | 
           388 | 
              | 
        
        
            | 
            | 
           389 | 
                   // Set the capability for CAT_A only.
  | 
        
        
            | 
            | 
           390 | 
                   $contextcata = context_coursecat::instance($categorya->id);
  | 
        
        
            | 
            | 
           391 | 
                   $roleid = $this->assignUserCapability('moodle/category:manage', $contextcata->id);
  | 
        
        
            | 
            | 
           392 | 
              | 
        
        
            | 
            | 
           393 | 
                   // Then we move SUBCAT_A parent: CAT_A => CAT_B.
  | 
        
        
            | 
            | 
           394 | 
                   $categories = [
  | 
        
        
            | 
            | 
           395 | 
                       [
  | 
        
        
            | 
            | 
           396 | 
                           'id' => $categoryasub->id,
  | 
        
        
            | 
            | 
           397 | 
                           'parent' => $categoryb->id
  | 
        
        
            | 
            | 
           398 | 
                       ]
  | 
        
        
            | 
            | 
           399 | 
                   ];
  | 
        
        
            | 
            | 
           400 | 
              | 
        
        
            | 
            | 
           401 | 
                   $this->expectException('required_capability_exception');
  | 
        
        
            | 
            | 
           402 | 
                   core_course_external::update_categories($categories);
  | 
        
        
            | 
            | 
           403 | 
               }
  | 
        
        
            | 
            | 
           404 | 
              | 
        
        
            | 
            | 
           405 | 
               /**
  | 
        
        
            | 
            | 
           406 | 
                * Test create_courses numsections
  | 
        
        
            | 
            | 
           407 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           408 | 
               public function test_create_course_numsections(): void {
  | 
        
        
           | 1 | 
           efrain | 
           409 | 
                   global $DB;
  | 
        
        
            | 
            | 
           410 | 
              | 
        
        
            | 
            | 
           411 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           412 | 
              | 
        
        
            | 
            | 
           413 | 
                   // Set the required capabilities by the external function.
  | 
        
        
            | 
            | 
           414 | 
                   $contextid = context_system::instance()->id;
  | 
        
        
            | 
            | 
           415 | 
                   $roleid = $this->assignUserCapability('moodle/course:create', $contextid);
  | 
        
        
            | 
            | 
           416 | 
                   $this->assignUserCapability('moodle/course:visibility', $contextid, $roleid);
  | 
        
        
            | 
            | 
           417 | 
              | 
        
        
            | 
            | 
           418 | 
                   $numsections = 10;
  | 
        
        
            | 
            | 
           419 | 
                   $category  = self::getDataGenerator()->create_category();
  | 
        
        
            | 
            | 
           420 | 
              | 
        
        
            | 
            | 
           421 | 
                   // Create base categories.
  | 
        
        
            | 
            | 
           422 | 
                   $course1['fullname'] = 'Test course 1';
  | 
        
        
            | 
            | 
           423 | 
                   $course1['shortname'] = 'Testcourse1';
  | 
        
        
            | 
            | 
           424 | 
                   $course1['categoryid'] = $category->id;
  | 
        
        
            | 
            | 
           425 | 
                   $course1['courseformatoptions'][] = array('name' => 'numsections', 'value' => $numsections);
  | 
        
        
            | 
            | 
           426 | 
              | 
        
        
            | 
            | 
           427 | 
                   $courses = array($course1);
  | 
        
        
            | 
            | 
           428 | 
              | 
        
        
            | 
            | 
           429 | 
                   $createdcourses = core_course_external::create_courses($courses);
  | 
        
        
            | 
            | 
           430 | 
                   foreach ($createdcourses as $createdcourse) {
  | 
        
        
            | 
            | 
           431 | 
                       $existingsections = $DB->get_records('course_sections', array('course' => $createdcourse['id']));
  | 
        
        
            | 
            | 
           432 | 
                       $modinfo = get_fast_modinfo($createdcourse['id']);
  | 
        
        
            | 
            | 
           433 | 
                       $sections = $modinfo->get_section_info_all();
  | 
        
        
            | 
            | 
           434 | 
                       $this->assertEquals(count($sections), $numsections + 1); // Includes generic section.
  | 
        
        
            | 
            | 
           435 | 
                       $this->assertEquals(count($existingsections), $numsections + 1); // Includes generic section.
  | 
        
        
            | 
            | 
           436 | 
                   }
  | 
        
        
            | 
            | 
           437 | 
               }
  | 
        
        
            | 
            | 
           438 | 
              | 
        
        
            | 
            | 
           439 | 
               /**
  | 
        
        
            | 
            | 
           440 | 
                * Test create_courses
  | 
        
        
            | 
            | 
           441 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           442 | 
               public function test_create_courses(): void {
  | 
        
        
           | 1 | 
           efrain | 
           443 | 
                   global $DB;
  | 
        
        
            | 
            | 
           444 | 
              | 
        
        
            | 
            | 
           445 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           446 | 
              | 
        
        
            | 
            | 
           447 | 
                   // Enable course completion.
  | 
        
        
            | 
            | 
           448 | 
                   set_config('enablecompletion', 1);
  | 
        
        
            | 
            | 
           449 | 
                   // Enable course themes.
  | 
        
        
            | 
            | 
           450 | 
                   set_config('allowcoursethemes', 1);
  | 
        
        
            | 
            | 
           451 | 
              | 
        
        
            | 
            | 
           452 | 
                   // Custom fields.
  | 
        
        
            | 
            | 
           453 | 
                   $fieldcategory = self::getDataGenerator()->create_custom_field_category(['name' => 'Other fields']);
  | 
        
        
            | 
            | 
           454 | 
              | 
        
        
            | 
            | 
           455 | 
                   $fieldtext = self::getDataGenerator()->create_custom_field([
  | 
        
        
            | 
            | 
           456 | 
                       'categoryid' => $fieldcategory->get('id'), 'name' => 'Text', 'shortname' => 'text', 'type' => 'text',
  | 
        
        
            | 
            | 
           457 | 
                   ]);
  | 
        
        
            | 
            | 
           458 | 
                   $fieldtextarea = self::getDataGenerator()->create_custom_field([
  | 
        
        
            | 
            | 
           459 | 
                       'categoryid' => $fieldcategory->get('id'), 'name' => 'Textarea', 'shortname' => 'textarea', 'type' => 'textarea',
  | 
        
        
            | 
            | 
           460 | 
                   ]);
  | 
        
        
            | 
            | 
           461 | 
              | 
        
        
            | 
            | 
           462 | 
                   // Set the required capabilities by the external function
  | 
        
        
            | 
            | 
           463 | 
                   $contextid = context_system::instance()->id;
  | 
        
        
            | 
            | 
           464 | 
                   $roleid = $this->assignUserCapability('moodle/course:create', $contextid);
  | 
        
        
            | 
            | 
           465 | 
                   $this->assignUserCapability('moodle/course:visibility', $contextid, $roleid);
  | 
        
        
            | 
            | 
           466 | 
                   $this->assignUserCapability('moodle/course:setforcedlanguage', $contextid, $roleid);
  | 
        
        
            | 
            | 
           467 | 
              | 
        
        
            | 
            | 
           468 | 
                   $category  = self::getDataGenerator()->create_category();
  | 
        
        
            | 
            | 
           469 | 
              | 
        
        
            | 
            | 
           470 | 
                   // Create base categories.
  | 
        
        
            | 
            | 
           471 | 
                   $course1['fullname'] = 'Test course 1';
  | 
        
        
            | 
            | 
           472 | 
                   $course1['shortname'] = 'Testcourse1';
  | 
        
        
            | 
            | 
           473 | 
                   $course1['categoryid'] = $category->id;
  | 
        
        
            | 
            | 
           474 | 
                   $course2['fullname'] = 'Test course 2';
  | 
        
        
            | 
            | 
           475 | 
                   $course2['shortname'] = 'Testcourse2';
  | 
        
        
            | 
            | 
           476 | 
                   $course2['categoryid'] = $category->id;
  | 
        
        
            | 
            | 
           477 | 
                   $course2['idnumber'] = 'testcourse2idnumber';
  | 
        
        
            | 
            | 
           478 | 
                   $course2['summary'] = 'Description for course 2';
  | 
        
        
            | 
            | 
           479 | 
                   $course2['summaryformat'] = FORMAT_MOODLE;
  | 
        
        
            | 
            | 
           480 | 
                   $course2['format'] = 'weeks';
  | 
        
        
            | 
            | 
           481 | 
                   $course2['showgrades'] = 1;
  | 
        
        
            | 
            | 
           482 | 
                   $course2['newsitems'] = 3;
  | 
        
        
            | 
            | 
           483 | 
                   $course2['startdate'] = 1420092000; // 01/01/2015.
  | 
        
        
            | 
            | 
           484 | 
                   $course2['enddate'] = 1422669600; // 01/31/2015.
  | 
        
        
            | 
            | 
           485 | 
                   $course2['numsections'] = 4;
  | 
        
        
            | 
            | 
           486 | 
                   $course2['maxbytes'] = 100000;
  | 
        
        
            | 
            | 
           487 | 
                   $course2['showreports'] = 1;
  | 
        
        
            | 
            | 
           488 | 
                   $course2['visible'] = 0;
  | 
        
        
            | 
            | 
           489 | 
                   $course2['hiddensections'] = 0;
  | 
        
        
            | 
            | 
           490 | 
                   $course2['groupmode'] = 0;
  | 
        
        
            | 
            | 
           491 | 
                   $course2['groupmodeforce'] = 0;
  | 
        
        
            | 
            | 
           492 | 
                   $course2['defaultgroupingid'] = 0;
  | 
        
        
            | 
            | 
           493 | 
                   $course2['enablecompletion'] = 1;
  | 
        
        
            | 
            | 
           494 | 
                   $course2['completionnotify'] = 1;
  | 
        
        
            | 
            | 
           495 | 
                   $course2['lang'] = 'en';
  | 
        
        
            | 
            | 
           496 | 
                   $course2['forcetheme'] = 'classic';
  | 
        
        
            | 
            | 
           497 | 
                   $course2['courseformatoptions'][] = array('name' => 'automaticenddate', 'value' => 0);
  | 
        
        
            | 
            | 
           498 | 
                   $course3['fullname'] = 'Test course 3';
  | 
        
        
            | 
            | 
           499 | 
                   $course3['shortname'] = 'Testcourse3';
  | 
        
        
            | 
            | 
           500 | 
                   $course3['categoryid'] = $category->id;
  | 
        
        
            | 
            | 
           501 | 
                   $course3['format'] = 'topics';
  | 
        
        
            | 
            | 
           502 | 
                   $course3options = array('numsections' => 8,
  | 
        
        
            | 
            | 
           503 | 
                       'hiddensections' => 1,
  | 
        
        
            | 
            | 
           504 | 
                       'coursedisplay' => 1);
  | 
        
        
            | 
            | 
           505 | 
                   $course3['courseformatoptions'] = array();
  | 
        
        
            | 
            | 
           506 | 
                   foreach ($course3options as $key => $value) {
  | 
        
        
            | 
            | 
           507 | 
                       $course3['courseformatoptions'][] = array('name' => $key, 'value' => $value);
  | 
        
        
            | 
            | 
           508 | 
                   }
  | 
        
        
            | 
            | 
           509 | 
                   $course4['fullname'] = 'Test course with custom fields';
  | 
        
        
            | 
            | 
           510 | 
                   $course4['shortname'] = 'Testcoursecustomfields';
  | 
        
        
            | 
            | 
           511 | 
                   $course4['categoryid'] = $category->id;
  | 
        
        
            | 
            | 
           512 | 
                   $course4['customfields'] = [
  | 
        
        
            | 
            | 
           513 | 
                       ['shortname' => $fieldtext->get('shortname'), 'value' => 'And I want to tell you so much'],
  | 
        
        
            | 
            | 
           514 | 
                       ['shortname' => $fieldtextarea->get('shortname'), 'value' => 'I love you'],
  | 
        
        
            | 
            | 
           515 | 
                   ];
  | 
        
        
            | 
            | 
           516 | 
                   $courses = array($course4, $course1, $course2, $course3);
  | 
        
        
            | 
            | 
           517 | 
              | 
        
        
            | 
            | 
           518 | 
                   $createdcourses = core_course_external::create_courses($courses);
  | 
        
        
            | 
            | 
           519 | 
              | 
        
        
            | 
            | 
           520 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           521 | 
                   $createdcourses = external_api::clean_returnvalue(core_course_external::create_courses_returns(), $createdcourses);
  | 
        
        
            | 
            | 
           522 | 
              | 
        
        
            | 
            | 
           523 | 
                   // Check that right number of courses were created.
  | 
        
        
            | 
            | 
           524 | 
                   $this->assertEquals(4, count($createdcourses));
  | 
        
        
            | 
            | 
           525 | 
              | 
        
        
            | 
            | 
           526 | 
                   // Check that the courses were correctly created.
  | 
        
        
            | 
            | 
           527 | 
                   foreach ($createdcourses as $createdcourse) {
  | 
        
        
            | 
            | 
           528 | 
                       $courseinfo = course_get_format($createdcourse['id'])->get_course();
  | 
        
        
            | 
            | 
           529 | 
              | 
        
        
            | 
            | 
           530 | 
                       if ($createdcourse['shortname'] == $course2['shortname']) {
  | 
        
        
            | 
            | 
           531 | 
                           $this->assertEquals($courseinfo->fullname, $course2['fullname']);
  | 
        
        
            | 
            | 
           532 | 
                           $this->assertEquals($courseinfo->shortname, $course2['shortname']);
  | 
        
        
            | 
            | 
           533 | 
                           $this->assertEquals($courseinfo->category, $course2['categoryid']);
  | 
        
        
            | 
            | 
           534 | 
                           $this->assertEquals($courseinfo->idnumber, $course2['idnumber']);
  | 
        
        
            | 
            | 
           535 | 
                           $this->assertEquals($courseinfo->summary, $course2['summary']);
  | 
        
        
            | 
            | 
           536 | 
                           $this->assertEquals($courseinfo->summaryformat, $course2['summaryformat']);
  | 
        
        
            | 
            | 
           537 | 
                           $this->assertEquals($courseinfo->format, $course2['format']);
  | 
        
        
            | 
            | 
           538 | 
                           $this->assertEquals($courseinfo->showgrades, $course2['showgrades']);
  | 
        
        
            | 
            | 
           539 | 
                           $this->assertEquals($courseinfo->newsitems, $course2['newsitems']);
  | 
        
        
            | 
            | 
           540 | 
                           $this->assertEquals($courseinfo->startdate, $course2['startdate']);
  | 
        
        
            | 
            | 
           541 | 
                           $this->assertEquals($courseinfo->enddate, $course2['enddate']);
  | 
        
        
            | 
            | 
           542 | 
                           $this->assertEquals(course_get_format($createdcourse['id'])->get_last_section_number(), $course2['numsections']);
  | 
        
        
            | 
            | 
           543 | 
                           $this->assertEquals($courseinfo->maxbytes, $course2['maxbytes']);
  | 
        
        
            | 
            | 
           544 | 
                           $this->assertEquals($courseinfo->showreports, $course2['showreports']);
  | 
        
        
            | 
            | 
           545 | 
                           $this->assertEquals($courseinfo->visible, $course2['visible']);
  | 
        
        
            | 
            | 
           546 | 
                           $this->assertEquals($courseinfo->hiddensections, $course2['hiddensections']);
  | 
        
        
            | 
            | 
           547 | 
                           $this->assertEquals($courseinfo->groupmode, $course2['groupmode']);
  | 
        
        
            | 
            | 
           548 | 
                           $this->assertEquals($courseinfo->groupmodeforce, $course2['groupmodeforce']);
  | 
        
        
            | 
            | 
           549 | 
                           $this->assertEquals($courseinfo->defaultgroupingid, $course2['defaultgroupingid']);
  | 
        
        
            | 
            | 
           550 | 
                           $this->assertEquals($courseinfo->completionnotify, $course2['completionnotify']);
  | 
        
        
            | 
            | 
           551 | 
                           $this->assertEquals($courseinfo->lang, $course2['lang']);
  | 
        
        
            | 
            | 
           552 | 
                           $this->assertEquals($courseinfo->theme, $course2['forcetheme']);
  | 
        
        
            | 
            | 
           553 | 
              | 
        
        
            | 
            | 
           554 | 
                           // We enabled completion at the beginning of the test.
  | 
        
        
            | 
            | 
           555 | 
                           $this->assertEquals($courseinfo->enablecompletion, $course2['enablecompletion']);
  | 
        
        
            | 
            | 
           556 | 
              | 
        
        
            | 
            | 
           557 | 
                       } else if ($createdcourse['shortname'] == $course1['shortname']) {
  | 
        
        
            | 
            | 
           558 | 
                           $courseconfig = get_config('moodlecourse');
  | 
        
        
            | 
            | 
           559 | 
                           $this->assertEquals($courseinfo->fullname, $course1['fullname']);
  | 
        
        
            | 
            | 
           560 | 
                           $this->assertEquals($courseinfo->shortname, $course1['shortname']);
  | 
        
        
            | 
            | 
           561 | 
                           $this->assertEquals($courseinfo->category, $course1['categoryid']);
  | 
        
        
            | 
            | 
           562 | 
                           $this->assertEquals($courseinfo->summaryformat, FORMAT_HTML);
  | 
        
        
            | 
            | 
           563 | 
                           $this->assertEquals($courseinfo->format, $courseconfig->format);
  | 
        
        
            | 
            | 
           564 | 
                           $this->assertEquals($courseinfo->showgrades, $courseconfig->showgrades);
  | 
        
        
            | 
            | 
           565 | 
                           $this->assertEquals($courseinfo->newsitems, $courseconfig->newsitems);
  | 
        
        
            | 
            | 
           566 | 
                           $this->assertEquals($courseinfo->maxbytes, $courseconfig->maxbytes);
  | 
        
        
            | 
            | 
           567 | 
                           $this->assertEquals($courseinfo->showreports, $courseconfig->showreports);
  | 
        
        
            | 
            | 
           568 | 
                           $this->assertEquals($courseinfo->groupmode, $courseconfig->groupmode);
  | 
        
        
            | 
            | 
           569 | 
                           $this->assertEquals($courseinfo->groupmodeforce, $courseconfig->groupmodeforce);
  | 
        
        
            | 
            | 
           570 | 
                           $this->assertEquals($courseinfo->defaultgroupingid, 0);
  | 
        
        
            | 
            | 
           571 | 
                       } else if ($createdcourse['shortname'] == $course3['shortname']) {
  | 
        
        
            | 
            | 
           572 | 
                           $this->assertEquals($courseinfo->fullname, $course3['fullname']);
  | 
        
        
            | 
            | 
           573 | 
                           $this->assertEquals($courseinfo->shortname, $course3['shortname']);
  | 
        
        
            | 
            | 
           574 | 
                           $this->assertEquals($courseinfo->category, $course3['categoryid']);
  | 
        
        
            | 
            | 
           575 | 
                           $this->assertEquals($courseinfo->format, $course3['format']);
  | 
        
        
            | 
            | 
           576 | 
                           $this->assertEquals($courseinfo->hiddensections, $course3options['hiddensections']);
  | 
        
        
            | 
            | 
           577 | 
                           $this->assertEquals(course_get_format($createdcourse['id'])->get_last_section_number(),
  | 
        
        
            | 
            | 
           578 | 
                               $course3options['numsections']);
  | 
        
        
            | 
            | 
           579 | 
                           $this->assertEquals($courseinfo->coursedisplay, $course3options['coursedisplay']);
  | 
        
        
            | 
            | 
           580 | 
                       } else if ($createdcourse['shortname'] == $course4['shortname']) {
  | 
        
        
            | 
            | 
           581 | 
                           $this->assertEquals($courseinfo->fullname, $course4['fullname']);
  | 
        
        
            | 
            | 
           582 | 
                           $this->assertEquals($courseinfo->shortname, $course4['shortname']);
  | 
        
        
            | 
            | 
           583 | 
                           $this->assertEquals($courseinfo->category, $course4['categoryid']);
  | 
        
        
            | 
            | 
           584 | 
              | 
        
        
            | 
            | 
           585 | 
                           $handler = core_course\customfield\course_handler::create();
  | 
        
        
            | 
            | 
           586 | 
                           $customfields = $handler->export_instance_data_object($createdcourse['id']);
  | 
        
        
            | 
            | 
           587 | 
                           $this->assertEquals((object) [
  | 
        
        
            | 
            | 
           588 | 
                               'text' => 'And I want to tell you so much',
  | 
        
        
            | 
            | 
           589 | 
                               'textarea' => '<div class="text_to_html">I love you</div>',
  | 
        
        
            | 
            | 
           590 | 
                           ], $customfields);
  | 
        
        
            | 
            | 
           591 | 
                       } else {
  | 
        
        
            | 
            | 
           592 | 
                           throw new moodle_exception('Unexpected shortname');
  | 
        
        
            | 
            | 
           593 | 
                       }
  | 
        
        
            | 
            | 
           594 | 
                   }
  | 
        
        
            | 
            | 
           595 | 
              | 
        
        
            | 
            | 
           596 | 
                   // Call without required capability
  | 
        
        
            | 
            | 
           597 | 
                   $this->unassignUserCapability('moodle/course:create', $contextid, $roleid);
  | 
        
        
            | 
            | 
           598 | 
                   $this->expectException('required_capability_exception');
  | 
        
        
            | 
            | 
           599 | 
                   $createdsubcats = core_course_external::create_courses($courses);
  | 
        
        
            | 
            | 
           600 | 
               }
  | 
        
        
            | 
            | 
           601 | 
              | 
        
        
            | 
            | 
           602 | 
               /**
  | 
        
        
            | 
            | 
           603 | 
                * Data provider for testing empty fields produce expected exceptions
  | 
        
        
            | 
            | 
           604 | 
                *
  | 
        
        
            | 
            | 
           605 | 
                * @see test_create_courses_empty_field
  | 
        
        
            | 
            | 
           606 | 
                * @see test_update_courses_empty_field
  | 
        
        
            | 
            | 
           607 | 
                *
  | 
        
        
            | 
            | 
           608 | 
                * @return array
  | 
        
        
            | 
            | 
           609 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           610 | 
               public static function course_empty_field_provider(): array {
  | 
        
        
           | 1 | 
           efrain | 
           611 | 
                   return [
  | 
        
        
            | 
            | 
           612 | 
                       [[
  | 
        
        
            | 
            | 
           613 | 
                           'fullname' => '',
  | 
        
        
            | 
            | 
           614 | 
                           'shortname' => 'ws101',
  | 
        
        
            | 
            | 
           615 | 
                       ], 'fullname'],
  | 
        
        
            | 
            | 
           616 | 
                       [[
  | 
        
        
            | 
            | 
           617 | 
                           'fullname' => ' ',
  | 
        
        
            | 
            | 
           618 | 
                           'shortname' => 'ws101',
  | 
        
        
            | 
            | 
           619 | 
                       ], 'fullname'],
  | 
        
        
            | 
            | 
           620 | 
                       [[
  | 
        
        
            | 
            | 
           621 | 
                           'fullname' => 'Web Services',
  | 
        
        
            | 
            | 
           622 | 
                           'shortname' => '',
  | 
        
        
            | 
            | 
           623 | 
                       ], 'shortname'],
  | 
        
        
            | 
            | 
           624 | 
                       [[
  | 
        
        
            | 
            | 
           625 | 
                           'fullname' => 'Web Services',
  | 
        
        
            | 
            | 
           626 | 
                           'shortname' => ' ',
  | 
        
        
            | 
            | 
           627 | 
                       ], 'shortname'],
  | 
        
        
            | 
            | 
           628 | 
                   ];
  | 
        
        
            | 
            | 
           629 | 
               }
  | 
        
        
            | 
            | 
           630 | 
              | 
        
        
            | 
            | 
           631 | 
               /**
  | 
        
        
            | 
            | 
           632 | 
                * Test creating courses with empty fields throws an exception
  | 
        
        
            | 
            | 
           633 | 
                *
  | 
        
        
            | 
            | 
           634 | 
                * @param array $course
  | 
        
        
            | 
            | 
           635 | 
                * @param string $expectedemptyfield
  | 
        
        
            | 
            | 
           636 | 
                *
  | 
        
        
            | 
            | 
           637 | 
                * @dataProvider course_empty_field_provider
  | 
        
        
            | 
            | 
           638 | 
                */
  | 
        
        
            | 
            | 
           639 | 
               public function test_create_courses_empty_field(array $course, string $expectedemptyfield): void {
  | 
        
        
            | 
            | 
           640 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           641 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           642 | 
              | 
        
        
            | 
            | 
           643 | 
                   // Create a category for the new course.
  | 
        
        
            | 
            | 
           644 | 
                   $course['categoryid'] = $this->getDataGenerator()->create_category()->id;
  | 
        
        
            | 
            | 
           645 | 
              | 
        
        
            | 
            | 
           646 | 
                   $this->expectException(moodle_exception::class);
  | 
        
        
            | 
            | 
           647 | 
                   $this->expectExceptionMessageMatches("/{$expectedemptyfield}/");
  | 
        
        
            | 
            | 
           648 | 
                   core_course_external::create_courses([$course]);
  | 
        
        
            | 
            | 
           649 | 
               }
  | 
        
        
            | 
            | 
           650 | 
              | 
        
        
            | 
            | 
           651 | 
               /**
  | 
        
        
            | 
            | 
           652 | 
                * Test updating courses with empty fields returns warnings
  | 
        
        
            | 
            | 
           653 | 
                *
  | 
        
        
            | 
            | 
           654 | 
                * @param array $course
  | 
        
        
            | 
            | 
           655 | 
                * @param string $expectedemptyfield
  | 
        
        
            | 
            | 
           656 | 
                *
  | 
        
        
            | 
            | 
           657 | 
                * @dataProvider course_empty_field_provider
  | 
        
        
            | 
            | 
           658 | 
                */
  | 
        
        
            | 
            | 
           659 | 
               public function test_update_courses_empty_field(array $course, string $expectedemptyfield): void {
  | 
        
        
            | 
            | 
           660 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           661 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           662 | 
              | 
        
        
            | 
            | 
           663 | 
                   // Create a course to update.
  | 
        
        
            | 
            | 
           664 | 
                   $course['id'] = $this->getDataGenerator()->create_course()->id;
  | 
        
        
            | 
            | 
           665 | 
              | 
        
        
            | 
            | 
           666 | 
                   $result = core_course_external::update_courses([$course]);
  | 
        
        
            | 
            | 
           667 | 
                   $result = core_course_external::clean_returnvalue(core_course_external::update_courses_returns(), $result);
  | 
        
        
            | 
            | 
           668 | 
              | 
        
        
            | 
            | 
           669 | 
                   $this->assertCount(1, $result['warnings']);
  | 
        
        
            | 
            | 
           670 | 
              | 
        
        
            | 
            | 
           671 | 
                   $warning = reset($result['warnings']);
  | 
        
        
            | 
            | 
           672 | 
                   $this->assertEquals('errorinvalidparam', $warning['warningcode']);
  | 
        
        
            | 
            | 
           673 | 
                   $this->assertStringContainsString($expectedemptyfield, $warning['message']);
  | 
        
        
            | 
            | 
           674 | 
               }
  | 
        
        
            | 
            | 
           675 | 
              | 
        
        
            | 
            | 
           676 | 
               /**
  | 
        
        
            | 
            | 
           677 | 
                * Test delete_courses
  | 
        
        
            | 
            | 
           678 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           679 | 
               public function test_delete_courses(): void {
  | 
        
        
           | 1 | 
           efrain | 
           680 | 
                   global $DB, $USER;
  | 
        
        
            | 
            | 
           681 | 
              | 
        
        
            | 
            | 
           682 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           683 | 
              | 
        
        
            | 
            | 
           684 | 
                   // Admin can delete a course.
  | 
        
        
            | 
            | 
           685 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           686 | 
                   // Validate_context() will fail as the email is not set by $this->setAdminUser().
  | 
        
        
            | 
            | 
           687 | 
                   $USER->email = 'emailtopass@example.com';
  | 
        
        
            | 
            | 
           688 | 
              | 
        
        
            | 
            | 
           689 | 
                   $course1  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           690 | 
                   $course2  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           691 | 
                   $course3  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           692 | 
              | 
        
        
            | 
            | 
           693 | 
                   // Delete courses.
  | 
        
        
            | 
            | 
           694 | 
                   $result = core_course_external::delete_courses(array($course1->id, $course2->id));
  | 
        
        
            | 
            | 
           695 | 
                   $result = external_api::clean_returnvalue(core_course_external::delete_courses_returns(), $result);
  | 
        
        
            | 
            | 
           696 | 
                   // Check for 0 warnings.
  | 
        
        
            | 
            | 
           697 | 
                   $this->assertEquals(0, count($result['warnings']));
  | 
        
        
            | 
            | 
           698 | 
              | 
        
        
            | 
            | 
           699 | 
                   // Check $course 1 and 2 are deleted.
  | 
        
        
            | 
            | 
           700 | 
                   $notdeletedcount = $DB->count_records_select('course',
  | 
        
        
            | 
            | 
           701 | 
                       'id IN ( ' . $course1->id . ',' . $course2->id . ')');
  | 
        
        
            | 
            | 
           702 | 
                   $this->assertEquals(0, $notdeletedcount);
  | 
        
        
            | 
            | 
           703 | 
              | 
        
        
            | 
            | 
           704 | 
                   // Try to delete non-existent course.
  | 
        
        
            | 
            | 
           705 | 
                   $result = core_course_external::delete_courses(array($course1->id));
  | 
        
        
            | 
            | 
           706 | 
                   $result = external_api::clean_returnvalue(core_course_external::delete_courses_returns(), $result);
  | 
        
        
            | 
            | 
           707 | 
                   // Check for 1 warnings.
  | 
        
        
            | 
            | 
           708 | 
                   $this->assertEquals(1, count($result['warnings']));
  | 
        
        
            | 
            | 
           709 | 
              | 
        
        
            | 
            | 
           710 | 
                   // Try to delete Frontpage course.
  | 
        
        
            | 
            | 
           711 | 
                   $result = core_course_external::delete_courses(array(0));
  | 
        
        
            | 
            | 
           712 | 
                   $result = external_api::clean_returnvalue(core_course_external::delete_courses_returns(), $result);
  | 
        
        
            | 
            | 
           713 | 
                   // Check for 1 warnings.
  | 
        
        
            | 
            | 
           714 | 
                   $this->assertEquals(1, count($result['warnings']));
  | 
        
        
            | 
            | 
           715 | 
              | 
        
        
            | 
            | 
           716 | 
                    // Fail when the user has access to course (enrolled) but does not have permission or is not admin.
  | 
        
        
            | 
            | 
           717 | 
                   $student1 = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           718 | 
                   $studentrole = $DB->get_record('role', array('shortname' => 'student'));
  | 
        
        
            | 
            | 
           719 | 
                   $this->getDataGenerator()->enrol_user($student1->id,
  | 
        
        
            | 
            | 
           720 | 
                                                         $course3->id,
  | 
        
        
            | 
            | 
           721 | 
                                                         $studentrole->id);
  | 
        
        
            | 
            | 
           722 | 
                   $this->setUser($student1);
  | 
        
        
            | 
            | 
           723 | 
                   $result = core_course_external::delete_courses(array($course3->id));
  | 
        
        
            | 
            | 
           724 | 
                   $result = external_api::clean_returnvalue(core_course_external::delete_courses_returns(), $result);
  | 
        
        
            | 
            | 
           725 | 
                   // Check for 1 warnings.
  | 
        
        
            | 
            | 
           726 | 
                   $this->assertEquals(1, count($result['warnings']));
  | 
        
        
            | 
            | 
           727 | 
              | 
        
        
            | 
            | 
           728 | 
                    // Fail when the user is not allow to access the course (enrolled) or is not admin.
  | 
        
        
            | 
            | 
           729 | 
                   $this->setGuestUser();
  | 
        
        
            | 
            | 
           730 | 
                   $this->expectException('require_login_exception');
  | 
        
        
            | 
            | 
           731 | 
              | 
        
        
            | 
            | 
           732 | 
                   $result = core_course_external::delete_courses(array($course3->id));
  | 
        
        
            | 
            | 
           733 | 
                   $result = external_api::clean_returnvalue(core_course_external::delete_courses_returns(), $result);
  | 
        
        
            | 
            | 
           734 | 
               }
  | 
        
        
            | 
            | 
           735 | 
              | 
        
        
            | 
            | 
           736 | 
               /**
  | 
        
        
            | 
            | 
           737 | 
                * Test get_courses
  | 
        
        
            | 
            | 
           738 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           739 | 
               public function test_get_courses(): void {
  | 
        
        
           | 1 | 
           efrain | 
           740 | 
                   global $DB;
  | 
        
        
            | 
            | 
           741 | 
              | 
        
        
            | 
            | 
           742 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           743 | 
              | 
        
        
            | 
            | 
           744 | 
                   $generatedcourses = array();
  | 
        
        
            | 
            | 
           745 | 
                   $coursedata['idnumber'] = 'idnumbercourse1';
  | 
        
        
            | 
            | 
           746 | 
                   // Adding tags here to check that format_string is applied.
  | 
        
        
            | 
            | 
           747 | 
                   $coursedata['fullname'] = '<b>Course 1 for PHPunit test</b>';
  | 
        
        
            | 
            | 
           748 | 
                   $coursedata['shortname'] = '<b>Course 1 for PHPunit test</b>';
  | 
        
        
            | 
            | 
           749 | 
                   $coursedata['summary'] = 'Course 1 description';
  | 
        
        
            | 
            | 
           750 | 
                   $coursedata['summaryformat'] = FORMAT_MOODLE;
  | 
        
        
            | 
            | 
           751 | 
                   $course1  = self::getDataGenerator()->create_course($coursedata);
  | 
        
        
            | 
            | 
           752 | 
              | 
        
        
            | 
            | 
           753 | 
                   $fieldcategory = self::getDataGenerator()->create_custom_field_category(
  | 
        
        
            | 
            | 
           754 | 
                       ['name' => 'Other fields']);
  | 
        
        
            | 
            | 
           755 | 
              | 
        
        
            | 
            | 
           756 | 
                   $customfield = ['shortname' => 'test', 'name' => 'Custom field', 'type' => 'text',
  | 
        
        
            | 
            | 
           757 | 
                       'categoryid' => $fieldcategory->get('id')];
  | 
        
        
            | 
            | 
           758 | 
                   $field = self::getDataGenerator()->create_custom_field($customfield);
  | 
        
        
            | 
            | 
           759 | 
              | 
        
        
            | 
            | 
           760 | 
                   $customfieldvalue = ['shortname' => 'test', 'value' => 'Test value'];
  | 
        
        
            | 
            | 
           761 | 
              | 
        
        
            | 
            | 
           762 | 
                   $generatedcourses[$course1->id] = $course1;
  | 
        
        
            | 
            | 
           763 | 
                   $course2  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           764 | 
                   $generatedcourses[$course2->id] = $course2;
  | 
        
        
            | 
            | 
           765 | 
                   $course3  = self::getDataGenerator()->create_course(array('format' => 'topics'));
  | 
        
        
            | 
            | 
           766 | 
                   $generatedcourses[$course3->id] = $course3;
  | 
        
        
            | 
            | 
           767 | 
                   $course4  = self::getDataGenerator()->create_course(['customfields' => [$customfieldvalue]]);
  | 
        
        
            | 
            | 
           768 | 
                   $generatedcourses[$course4->id] = $course4;
  | 
        
        
            | 
            | 
           769 | 
              | 
        
        
            | 
            | 
           770 | 
                   // Set the required capabilities by the external function.
  | 
        
        
            | 
            | 
           771 | 
                   $context = context_system::instance();
  | 
        
        
            | 
            | 
           772 | 
                   $roleid = $this->assignUserCapability('moodle/course:view', $context->id);
  | 
        
        
            | 
            | 
           773 | 
                   $this->assignUserCapability('moodle/course:update',
  | 
        
        
            | 
            | 
           774 | 
                           context_course::instance($course1->id)->id, $roleid);
  | 
        
        
            | 
            | 
           775 | 
                   $this->assignUserCapability('moodle/course:update',
  | 
        
        
            | 
            | 
           776 | 
                           context_course::instance($course2->id)->id, $roleid);
  | 
        
        
            | 
            | 
           777 | 
                   $this->assignUserCapability('moodle/course:update',
  | 
        
        
            | 
            | 
           778 | 
                           context_course::instance($course3->id)->id, $roleid);
  | 
        
        
            | 
            | 
           779 | 
                   $this->assignUserCapability('moodle/course:update',
  | 
        
        
            | 
            | 
           780 | 
                           context_course::instance($course4->id)->id, $roleid);
  | 
        
        
            | 
            | 
           781 | 
              | 
        
        
            | 
            | 
           782 | 
                   $courses = core_course_external::get_courses(array('ids' =>
  | 
        
        
            | 
            | 
           783 | 
                       array($course1->id, $course2->id, $course4->id)));
  | 
        
        
            | 
            | 
           784 | 
              | 
        
        
            | 
            | 
           785 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           786 | 
                   $courses = external_api::clean_returnvalue(core_course_external::get_courses_returns(), $courses);
  | 
        
        
            | 
            | 
           787 | 
              | 
        
        
            | 
            | 
           788 | 
                   // Check we retrieve the good total number of courses.
  | 
        
        
            | 
            | 
           789 | 
                   $this->assertEquals(3, count($courses));
  | 
        
        
            | 
            | 
           790 | 
              | 
        
        
            | 
            | 
           791 | 
                   foreach ($courses as $course) {
  | 
        
        
            | 
            | 
           792 | 
                       $coursecontext = context_course::instance($course['id']);
  | 
        
        
            | 
            | 
           793 | 
                       $dbcourse = $generatedcourses[$course['id']];
  | 
        
        
            | 
            | 
           794 | 
                       $this->assertEquals($course['idnumber'], $dbcourse->idnumber);
  | 
        
        
            | 
            | 
           795 | 
                       $this->assertEquals(
  | 
        
        
            | 
            | 
           796 | 
                           $course['fullname'],
  | 
        
        
            | 
            | 
           797 | 
                           \core_external\util::format_string($dbcourse->fullname, $coursecontext->id)
  | 
        
        
            | 
            | 
           798 | 
                       );
  | 
        
        
            | 
            | 
           799 | 
                       $this->assertEquals(
  | 
        
        
            | 
            | 
           800 | 
                           $course['displayname'],
  | 
        
        
            | 
            | 
           801 | 
                           \core_external\util::format_string(get_course_display_name_for_list($dbcourse), $coursecontext->id)
  | 
        
        
            | 
            | 
           802 | 
                       );
  | 
        
        
            | 
            | 
           803 | 
                       // Summary was converted to the HTML format.
  | 
        
        
            | 
            | 
           804 | 
                       $this->assertEquals($course['summary'], format_text($dbcourse->summary, FORMAT_MOODLE, array('para' => false)));
  | 
        
        
            | 
            | 
           805 | 
                       $this->assertEquals($course['summaryformat'], FORMAT_HTML);
  | 
        
        
            | 
            | 
           806 | 
                       $this->assertEquals($course['shortname'], \core_external\util::format_string($dbcourse->shortname, $coursecontext->id));
  | 
        
        
            | 
            | 
           807 | 
                       $this->assertEquals($course['categoryid'], $dbcourse->category);
  | 
        
        
            | 
            | 
           808 | 
                       $this->assertEquals($course['format'], $dbcourse->format);
  | 
        
        
            | 
            | 
           809 | 
                       $this->assertEquals($course['showgrades'], $dbcourse->showgrades);
  | 
        
        
            | 
            | 
           810 | 
                       $this->assertEquals($course['newsitems'], $dbcourse->newsitems);
  | 
        
        
            | 
            | 
           811 | 
                       $this->assertEquals($course['startdate'], $dbcourse->startdate);
  | 
        
        
            | 
            | 
           812 | 
                       $this->assertEquals($course['enddate'], $dbcourse->enddate);
  | 
        
        
            | 
            | 
           813 | 
                       $this->assertEquals($course['numsections'], course_get_format($dbcourse)->get_last_section_number());
  | 
        
        
            | 
            | 
           814 | 
                       $this->assertEquals($course['maxbytes'], $dbcourse->maxbytes);
  | 
        
        
            | 
            | 
           815 | 
                       $this->assertEquals($course['showreports'], $dbcourse->showreports);
  | 
        
        
            | 
            | 
           816 | 
                       $this->assertEquals($course['visible'], $dbcourse->visible);
  | 
        
        
            | 
            | 
           817 | 
                       $this->assertEquals($course['hiddensections'], $dbcourse->hiddensections);
  | 
        
        
            | 
            | 
           818 | 
                       $this->assertEquals($course['groupmode'], $dbcourse->groupmode);
  | 
        
        
            | 
            | 
           819 | 
                       $this->assertEquals($course['groupmodeforce'], $dbcourse->groupmodeforce);
  | 
        
        
            | 
            | 
           820 | 
                       $this->assertEquals($course['defaultgroupingid'], $dbcourse->defaultgroupingid);
  | 
        
        
            | 
            | 
           821 | 
                       $this->assertEquals($course['completionnotify'], $dbcourse->completionnotify);
  | 
        
        
            | 
            | 
           822 | 
                       $this->assertEquals($course['lang'], $dbcourse->lang);
  | 
        
        
            | 
            | 
           823 | 
                       $this->assertEquals($course['forcetheme'], $dbcourse->theme);
  | 
        
        
            | 
            | 
           824 | 
                       $this->assertEquals($course['enablecompletion'], $dbcourse->enablecompletion);
  | 
        
        
            | 
            | 
           825 | 
                       if ($dbcourse->format === 'topics') {
  | 
        
        
            | 
            | 
           826 | 
                           $this->assertEquals($course['courseformatoptions'], array(
  | 
        
        
            | 
            | 
           827 | 
                               array('name' => 'hiddensections', 'value' => $dbcourse->hiddensections),
  | 
        
        
            | 
            | 
           828 | 
                               array('name' => 'coursedisplay', 'value' => $dbcourse->coursedisplay),
  | 
        
        
            | 
            | 
           829 | 
                           ));
  | 
        
        
            | 
            | 
           830 | 
                       }
  | 
        
        
            | 
            | 
           831 | 
              | 
        
        
            | 
            | 
           832 | 
                       // Assert custom field that we previously added to test course 4.
  | 
        
        
            | 
            | 
           833 | 
                       if ($dbcourse->id == $course4->id) {
  | 
        
        
            | 
            | 
           834 | 
                           $this->assertEquals([
  | 
        
        
            | 
            | 
           835 | 
                               'shortname' => $customfield['shortname'],
  | 
        
        
            | 
            | 
           836 | 
                               'name' => $customfield['name'],
  | 
        
        
            | 
            | 
           837 | 
                               'type' => $customfield['type'],
  | 
        
        
            | 
            | 
           838 | 
                               'value' => $customfieldvalue['value'],
  | 
        
        
            | 
            | 
           839 | 
                               'valueraw' => $customfieldvalue['value'],
  | 
        
        
            | 
            | 
           840 | 
                           ], $course['customfields'][0]);
  | 
        
        
            | 
            | 
           841 | 
                       }
  | 
        
        
            | 
            | 
           842 | 
                   }
  | 
        
        
            | 
            | 
           843 | 
              | 
        
        
            | 
            | 
           844 | 
                   // Get all courses in the DB
  | 
        
        
            | 
            | 
           845 | 
                   $courses = core_course_external::get_courses(array());
  | 
        
        
            | 
            | 
           846 | 
              | 
        
        
            | 
            | 
           847 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           848 | 
                   $courses = external_api::clean_returnvalue(core_course_external::get_courses_returns(), $courses);
  | 
        
        
            | 
            | 
           849 | 
              | 
        
        
            | 
            | 
           850 | 
                   $this->assertEquals($DB->count_records('course'), count($courses));
  | 
        
        
            | 
            | 
           851 | 
               }
  | 
        
        
            | 
            | 
           852 | 
              | 
        
        
            | 
            | 
           853 | 
               /**
  | 
        
        
            | 
            | 
           854 | 
                * Test retrieving courses returns custom field data
  | 
        
        
            | 
            | 
           855 | 
                */
  | 
        
        
            | 
            | 
           856 | 
               public function test_get_courses_customfields(): void {
  | 
        
        
            | 
            | 
           857 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           858 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           859 | 
              | 
        
        
            | 
            | 
           860 | 
                   $fieldcategory = $this->getDataGenerator()->create_custom_field_category([]);
  | 
        
        
            | 
            | 
           861 | 
                   $datefield = $this->getDataGenerator()->create_custom_field([
  | 
        
        
            | 
            | 
           862 | 
                       'categoryid' => $fieldcategory->get('id'),
  | 
        
        
            | 
            | 
           863 | 
                       'shortname' => 'mydate',
  | 
        
        
            | 
            | 
           864 | 
                       'name' => 'My date',
  | 
        
        
            | 
            | 
           865 | 
                       'type' => 'date',
  | 
        
        
            | 
            | 
           866 | 
                   ]);
  | 
        
        
            | 
            | 
           867 | 
              | 
        
        
            | 
            | 
           868 | 
                   $newcourse = $this->getDataGenerator()->create_course(['customfields' => [
  | 
        
        
            | 
            | 
           869 | 
                       [
  | 
        
        
            | 
            | 
           870 | 
                           'shortname' => $datefield->get('shortname'),
  | 
        
        
            | 
            | 
           871 | 
                           'value' => 1580389200, // 30/01/2020 13:00 GMT.
  | 
        
        
            | 
            | 
           872 | 
                       ],
  | 
        
        
            | 
            | 
           873 | 
                   ]]);
  | 
        
        
            | 
            | 
           874 | 
              | 
        
        
            | 
            | 
           875 | 
                   $courses = external_api::clean_returnvalue(
  | 
        
        
            | 
            | 
           876 | 
                       core_course_external::get_courses_returns(),
  | 
        
        
            | 
            | 
           877 | 
                       core_course_external::get_courses(['ids' => [$newcourse->id]])
  | 
        
        
            | 
            | 
           878 | 
                   );
  | 
        
        
            | 
            | 
           879 | 
              | 
        
        
            | 
            | 
           880 | 
                   $this->assertCount(1, $courses);
  | 
        
        
            | 
            | 
           881 | 
                   $course = reset($courses);
  | 
        
        
            | 
            | 
           882 | 
              | 
        
        
            | 
            | 
           883 | 
                   $this->assertArrayHasKey('customfields', $course);
  | 
        
        
            | 
            | 
           884 | 
                   $this->assertCount(1, $course['customfields']);
  | 
        
        
            | 
            | 
           885 | 
              | 
        
        
            | 
            | 
           886 | 
                   // Assert the received custom field, "value" containing a human-readable version and "valueraw" the unmodified version.
  | 
        
        
            | 
            | 
           887 | 
                   $this->assertEquals([
  | 
        
        
            | 
            | 
           888 | 
                       'name' => $datefield->get('name'),
  | 
        
        
            | 
            | 
           889 | 
                       'shortname' => $datefield->get('shortname'),
  | 
        
        
            | 
            | 
           890 | 
                       'type' => $datefield->get('type'),
  | 
        
        
            | 
            | 
           891 | 
                       'value' => userdate(1580389200),
  | 
        
        
            | 
            | 
           892 | 
                       'valueraw' => 1580389200,
  | 
        
        
            | 
            | 
           893 | 
                   ], reset($course['customfields']));
  | 
        
        
            | 
            | 
           894 | 
               }
  | 
        
        
            | 
            | 
           895 | 
              | 
        
        
            | 
            | 
           896 | 
               /**
  | 
        
        
            | 
            | 
           897 | 
                * Test get_courses without capability
  | 
        
        
            | 
            | 
           898 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           899 | 
               public function test_get_courses_without_capability(): void {
  | 
        
        
           | 1 | 
           efrain | 
           900 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           901 | 
              | 
        
        
            | 
            | 
           902 | 
                   $course1 = $this->getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           903 | 
                   $this->setUser($this->getDataGenerator()->create_user());
  | 
        
        
            | 
            | 
           904 | 
              | 
        
        
            | 
            | 
           905 | 
                   // No permissions are required to get the site course.
  | 
        
        
            | 
            | 
           906 | 
                   $courses = core_course_external::get_courses(array('ids' => [SITEID]));
  | 
        
        
            | 
            | 
           907 | 
                   $courses = external_api::clean_returnvalue(core_course_external::get_courses_returns(), $courses);
  | 
        
        
            | 
            | 
           908 | 
              | 
        
        
            | 
            | 
           909 | 
                   $this->assertEquals(1, count($courses));
  | 
        
        
            | 
            | 
           910 | 
                   $this->assertEquals('PHPUnit test site', $courses[0]['fullname']);
  | 
        
        
            | 
            | 
           911 | 
                   $this->assertEquals('site', $courses[0]['format']);
  | 
        
        
            | 
            | 
           912 | 
              | 
        
        
            | 
            | 
           913 | 
                   // Requesting course without being enrolled or capability to view it will throw an exception.
  | 
        
        
            | 
            | 
           914 | 
                   try {
  | 
        
        
            | 
            | 
           915 | 
                       core_course_external::get_courses(array('ids' => [$course1->id]));
  | 
        
        
            | 
            | 
           916 | 
                       $this->fail('Exception expected');
  | 
        
        
            | 
            | 
           917 | 
                   } catch (moodle_exception $e) {
  | 
        
        
            | 
            | 
           918 | 
                       $this->assertEquals(1, preg_match('/Course or activity not accessible. \(Not enrolled\)/', $e->getMessage()));
  | 
        
        
            | 
            | 
           919 | 
                   }
  | 
        
        
            | 
            | 
           920 | 
               }
  | 
        
        
            | 
            | 
           921 | 
              | 
        
        
            | 
            | 
           922 | 
               /**
  | 
        
        
            | 
            | 
           923 | 
                * Test search_courses
  | 
        
        
            | 
            | 
           924 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           925 | 
               public function test_search_courses(): void {
  | 
        
        
           | 1 | 
           efrain | 
           926 | 
              | 
        
        
            | 
            | 
           927 | 
                   global $DB;
  | 
        
        
            | 
            | 
           928 | 
              | 
        
        
            | 
            | 
           929 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           930 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           931 | 
                   $generatedcourses = array();
  | 
        
        
            | 
            | 
           932 | 
                   $coursedata1['fullname'] = 'FIRST COURSE';
  | 
        
        
            | 
            | 
           933 | 
                   $course1  = self::getDataGenerator()->create_course($coursedata1);
  | 
        
        
            | 
            | 
           934 | 
              | 
        
        
            | 
            | 
           935 | 
                   $page = new moodle_page();
  | 
        
        
            | 
            | 
           936 | 
                   $page->set_course($course1);
  | 
        
        
            | 
            | 
           937 | 
                   $page->blocks->add_blocks([BLOCK_POS_LEFT => ['news_items'], BLOCK_POS_RIGHT => []], 'course-view-*');
  | 
        
        
            | 
            | 
           938 | 
              | 
        
        
            | 
            | 
           939 | 
                   $coursedata2['fullname'] = 'SECOND COURSE';
  | 
        
        
            | 
            | 
           940 | 
                   $course2  = self::getDataGenerator()->create_course($coursedata2);
  | 
        
        
            | 
            | 
           941 | 
              | 
        
        
            | 
            | 
           942 | 
                   $page = new moodle_page();
  | 
        
        
            | 
            | 
           943 | 
                   $page->set_course($course2);
  | 
        
        
            | 
            | 
           944 | 
                   $page->blocks->add_blocks([BLOCK_POS_LEFT => ['news_items'], BLOCK_POS_RIGHT => []], 'course-view-*');
  | 
        
        
            | 
            | 
           945 | 
              | 
        
        
            | 
            | 
           946 | 
                   // Search by name.
  | 
        
        
            | 
            | 
           947 | 
                   $results = core_course_external::search_courses('search', 'FIRST');
  | 
        
        
            | 
            | 
           948 | 
                   $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
  | 
        
        
            | 
            | 
           949 | 
                   $this->assertEquals($coursedata1['fullname'], $results['courses'][0]['fullname']);
  | 
        
        
            | 
            | 
           950 | 
                   $this->assertCount(1, $results['courses']);
  | 
        
        
            | 
            | 
           951 | 
              | 
        
        
            | 
            | 
           952 | 
                   // Create the forum.
  | 
        
        
            | 
            | 
           953 | 
                   $record = new stdClass();
  | 
        
        
            | 
            | 
           954 | 
                   $record->introformat = FORMAT_HTML;
  | 
        
        
            | 
            | 
           955 | 
                   $record->course = $course2->id;
  | 
        
        
            | 
            | 
           956 | 
                   // Set Aggregate type = Average of ratings.
  | 
        
        
            | 
            | 
           957 | 
                   $forum = self::getDataGenerator()->create_module('forum', $record);
  | 
        
        
            | 
            | 
           958 | 
              | 
        
        
            | 
            | 
           959 | 
                   // Search by module.
  | 
        
        
            | 
            | 
           960 | 
                   $results = core_course_external::search_courses('modulelist', 'forum');
  | 
        
        
            | 
            | 
           961 | 
                   $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
  | 
        
        
            | 
            | 
           962 | 
                   $this->assertEquals(1, $results['total']);
  | 
        
        
            | 
            | 
           963 | 
              | 
        
        
            | 
            | 
           964 | 
                   // Enable coursetag option.
  | 
        
        
            | 
            | 
           965 | 
                   set_config('block_tags_showcoursetags', true);
  | 
        
        
            | 
            | 
           966 | 
                   // Add tag 'TAG-LABEL ON SECOND COURSE' to Course2.
  | 
        
        
            | 
            | 
           967 | 
                   core_tag_tag::set_item_tags('core', 'course', $course2->id, context_course::instance($course2->id),
  | 
        
        
            | 
            | 
           968 | 
                           array('TAG-LABEL ON SECOND COURSE'));
  | 
        
        
            | 
            | 
           969 | 
                   $taginstance = $DB->get_record('tag_instance',
  | 
        
        
            | 
            | 
           970 | 
                           array('itemtype' => 'course', 'itemid' => $course2->id), '*', MUST_EXIST);
  | 
        
        
            | 
            | 
           971 | 
              | 
        
        
            | 
            | 
           972 | 
                   // Search by tagid.
  | 
        
        
            | 
            | 
           973 | 
                   $results = core_course_external::search_courses('tagid', $taginstance->tagid);
  | 
        
        
            | 
            | 
           974 | 
                   $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
  | 
        
        
            | 
            | 
           975 | 
                   $this->assertEquals($coursedata2['fullname'], $results['courses'][0]['fullname']);
  | 
        
        
            | 
            | 
           976 | 
              | 
        
        
            | 
            | 
           977 | 
                   // Search by block (use news_items default block).
  | 
        
        
            | 
            | 
           978 | 
                   $blockid = $DB->get_field('block', 'id', array('name' => 'news_items'));
  | 
        
        
            | 
            | 
           979 | 
                   $results = core_course_external::search_courses('blocklist', $blockid);
  | 
        
        
            | 
            | 
           980 | 
                   $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
  | 
        
        
            | 
            | 
           981 | 
                   $this->assertEquals(2, $results['total']);
  | 
        
        
            | 
            | 
           982 | 
              | 
        
        
            | 
            | 
           983 | 
                   // Now as a normal user.
  | 
        
        
            | 
            | 
           984 | 
                   $user = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           985 | 
              | 
        
        
            | 
            | 
           986 | 
                   // Add a 3rd, hidden, course we shouldn't see, even when enrolled as student.
  | 
        
        
            | 
            | 
           987 | 
                   $coursedata3['fullname'] = 'HIDDEN COURSE';
  | 
        
        
            | 
            | 
           988 | 
                   $coursedata3['visible'] = 0;
  | 
        
        
            | 
            | 
           989 | 
                   $course3  = self::getDataGenerator()->create_course($coursedata3);
  | 
        
        
            | 
            | 
           990 | 
                   $this->getDataGenerator()->enrol_user($user->id, $course3->id, 'student');
  | 
        
        
            | 
            | 
           991 | 
              | 
        
        
            | 
            | 
           992 | 
                   $this->getDataGenerator()->enrol_user($user->id, $course2->id, 'student');
  | 
        
        
            | 
            | 
           993 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           994 | 
              | 
        
        
            | 
            | 
           995 | 
                   $results = core_course_external::search_courses('search', 'FIRST');
  | 
        
        
            | 
            | 
           996 | 
                   $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
  | 
        
        
            | 
            | 
           997 | 
                   $this->assertCount(1, $results['courses']);
  | 
        
        
            | 
            | 
           998 | 
                   $this->assertEquals(1, $results['total']);
  | 
        
        
            | 
            | 
           999 | 
                   $this->assertEquals($coursedata1['fullname'], $results['courses'][0]['fullname']);
  | 
        
        
            | 
            | 
           1000 | 
              | 
        
        
            | 
            | 
           1001 | 
                   // Check that we can see all courses without the limit to enrolled setting.
  | 
        
        
            | 
            | 
           1002 | 
                   $results = core_course_external::search_courses('search', 'COURSE', 0, 0, array(), 0);
  | 
        
        
            | 
            | 
           1003 | 
                   $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
  | 
        
        
            | 
            | 
           1004 | 
                   $this->assertCount(2, $results['courses']);
  | 
        
        
            | 
            | 
           1005 | 
                   $this->assertEquals(2, $results['total']);
  | 
        
        
            | 
            | 
           1006 | 
              | 
        
        
            | 
            | 
           1007 | 
                   // Check that we only see our enrolled course when limiting.
  | 
        
        
            | 
            | 
           1008 | 
                   $results = core_course_external::search_courses('search', 'COURSE', 0, 0, array(), 1);
  | 
        
        
            | 
            | 
           1009 | 
                   $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
  | 
        
        
            | 
            | 
           1010 | 
                   $this->assertCount(1, $results['courses']);
  | 
        
        
            | 
            | 
           1011 | 
                   $this->assertEquals(1, $results['total']);
  | 
        
        
            | 
            | 
           1012 | 
                   $this->assertEquals($coursedata2['fullname'], $results['courses'][0]['fullname']);
  | 
        
        
            | 
            | 
           1013 | 
              | 
        
        
            | 
            | 
           1014 | 
                   // Search by block (use news_items default block). Should fail (only admins allowed).
  | 
        
        
            | 
            | 
           1015 | 
                   $this->expectException('required_capability_exception');
  | 
        
        
            | 
            | 
           1016 | 
                   $results = core_course_external::search_courses('blocklist', $blockid);
  | 
        
        
            | 
            | 
           1017 | 
               }
  | 
        
        
            | 
            | 
           1018 | 
              | 
        
        
            | 
            | 
           1019 | 
               /**
  | 
        
        
            | 
            | 
           1020 | 
                * Test searching for courses returns custom field data
  | 
        
        
            | 
            | 
           1021 | 
                */
  | 
        
        
            | 
            | 
           1022 | 
               public function test_search_courses_customfields(): void {
  | 
        
        
            | 
            | 
           1023 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           1024 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           1025 | 
              | 
        
        
            | 
            | 
           1026 | 
                   $fieldcategory = $this->getDataGenerator()->create_custom_field_category([]);
  | 
        
        
            | 
            | 
           1027 | 
                   $datefield = $this->getDataGenerator()->create_custom_field([
  | 
        
        
            | 
            | 
           1028 | 
                       'categoryid' => $fieldcategory->get('id'),
  | 
        
        
            | 
            | 
           1029 | 
                       'shortname' => 'mydate',
  | 
        
        
            | 
            | 
           1030 | 
                       'name' => 'My date',
  | 
        
        
            | 
            | 
           1031 | 
                       'type' => 'date',
  | 
        
        
            | 
            | 
           1032 | 
                   ]);
  | 
        
        
            | 
            | 
           1033 | 
              | 
        
        
            | 
            | 
           1034 | 
                   $newcourse = $this->getDataGenerator()->create_course(['customfields' => [
  | 
        
        
            | 
            | 
           1035 | 
                       [
  | 
        
        
            | 
            | 
           1036 | 
                           'shortname' => $datefield->get('shortname'),
  | 
        
        
            | 
            | 
           1037 | 
                           'value' => 1580389200, // 30/01/2020 13:00 GMT.
  | 
        
        
            | 
            | 
           1038 | 
                       ],
  | 
        
        
            | 
            | 
           1039 | 
                   ]]);
  | 
        
        
            | 
            | 
           1040 | 
              | 
        
        
            | 
            | 
           1041 | 
                   $result = external_api::clean_returnvalue(
  | 
        
        
            | 
            | 
           1042 | 
                       core_course_external::search_courses_returns(),
  | 
        
        
            | 
            | 
           1043 | 
                       core_course_external::search_courses('search', $newcourse->shortname)
  | 
        
        
            | 
            | 
           1044 | 
                   );
  | 
        
        
            | 
            | 
           1045 | 
              | 
        
        
            | 
            | 
           1046 | 
                   $this->assertCount(1, $result['courses']);
  | 
        
        
            | 
            | 
           1047 | 
                   $course = reset($result['courses']);
  | 
        
        
            | 
            | 
           1048 | 
              | 
        
        
            | 
            | 
           1049 | 
                   $this->assertArrayHasKey('customfields', $course);
  | 
        
        
            | 
            | 
           1050 | 
                   $this->assertCount(1, $course['customfields']);
  | 
        
        
            | 
            | 
           1051 | 
              | 
        
        
            | 
            | 
           1052 | 
                   // Assert the received custom field, "value" containing a human-readable version and "valueraw" the unmodified version.
  | 
        
        
            | 
            | 
           1053 | 
                   $this->assertEquals([
  | 
        
        
            | 
            | 
           1054 | 
                       'name' => $datefield->get('name'),
  | 
        
        
            | 
            | 
           1055 | 
                       'shortname' => $datefield->get('shortname'),
  | 
        
        
            | 
            | 
           1056 | 
                       'type' => $datefield->get('type'),
  | 
        
        
            | 
            | 
           1057 | 
                       'value' => userdate(1580389200),
  | 
        
        
            | 
            | 
           1058 | 
                       'valueraw' => 1580389200,
  | 
        
        
            | 
            | 
           1059 | 
                   ], reset($course['customfields']));
  | 
        
        
            | 
            | 
           1060 | 
               }
  | 
        
        
            | 
            | 
           1061 | 
              | 
        
        
            | 
            | 
           1062 | 
               /**
  | 
        
        
            | 
            | 
           1063 | 
                * Create a course with contents
  | 
        
        
            | 
            | 
           1064 | 
                * @return array A list with the course object and course modules objects
  | 
        
        
            | 
            | 
           1065 | 
                */
  | 
        
        
            | 
            | 
           1066 | 
               private function prepare_get_course_contents_test() {
  | 
        
        
            | 
            | 
           1067 | 
                   global $DB, $CFG;
  | 
        
        
            | 
            | 
           1068 | 
              | 
        
        
            | 
            | 
           1069 | 
                   $CFG->allowstealth = 1; // Allow stealth activities.
  | 
        
        
            | 
            | 
           1070 | 
                   $CFG->enablecompletion = true;
  | 
        
        
            | 
            | 
           1071 | 
                   // Course with 4 sections (apart from the main section), with completion and not displaying hidden sections.
  | 
        
        
            | 
            | 
           1072 | 
                   $course  = self::getDataGenerator()->create_course(['numsections' => 4, 'enablecompletion' => 1, 'hiddensections' => 1]);
  | 
        
        
            | 
            | 
           1073 | 
              | 
        
        
            | 
            | 
           1074 | 
                   $forumdescription = 'This is the forum description';
  | 
        
        
            | 
            | 
           1075 | 
                   $forum = $this->getDataGenerator()->create_module('forum',
  | 
        
        
            | 
            | 
           1076 | 
                       array('course' => $course->id, 'intro' => $forumdescription, 'trackingtype' => 2),
  | 
        
        
            | 
            | 
           1077 | 
                       array('showdescription' => true, 'completion' => COMPLETION_TRACKING_MANUAL));
  | 
        
        
            | 
            | 
           1078 | 
                   $forumcm = get_coursemodule_from_id('forum', $forum->cmid);
  | 
        
        
            | 
            | 
           1079 | 
                   // Add discussions to the tracking forced forum.
  | 
        
        
            | 
            | 
           1080 | 
                   $record = new stdClass();
  | 
        
        
            | 
            | 
           1081 | 
                   $record->course = $course->id;
  | 
        
        
            | 
            | 
           1082 | 
                   $record->userid = 0;
  | 
        
        
            | 
            | 
           1083 | 
                   $record->forum = $forum->id;
  | 
        
        
            | 
            | 
           1084 | 
                   $discussionforce = $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
  | 
        
        
            | 
            | 
           1085 | 
                   $data = $this->getDataGenerator()->create_module('data',
  | 
        
        
            | 
            | 
           1086 | 
                       array('assessed' => 1, 'scale' => 100, 'course' => $course->id, 'completion' => 2, 'completionentries' => 3));
  | 
        
        
            | 
            | 
           1087 | 
                   $datacm = get_coursemodule_from_instance('data', $data->id);
  | 
        
        
            | 
            | 
           1088 | 
                   $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id));
  | 
        
        
            | 
            | 
           1089 | 
                   $pagecm = get_coursemodule_from_instance('page', $page->id);
  | 
        
        
            | 
            | 
           1090 | 
                   // This is an stealth page (set by visibleoncoursepage).
  | 
        
        
            | 
            | 
           1091 | 
                   $pagestealth = $this->getDataGenerator()->create_module('page', array('course' => $course->id, 'visibleoncoursepage' => 0));
  | 
        
        
            | 
            | 
           1092 | 
                   $labeldescription = 'This is a very long label to test if more than 50 characters are returned.
  | 
        
        
            | 
            | 
           1093 | 
                           So bla bla bla bla <b>bold bold bold</b> bla bla bla bla.';
  | 
        
        
            | 
            | 
           1094 | 
                   $label = $this->getDataGenerator()->create_module('label', array('course' => $course->id,
  | 
        
        
            | 
            | 
           1095 | 
                       'intro' => $labeldescription, 'completion' => COMPLETION_TRACKING_MANUAL));
  | 
        
        
            | 
            | 
           1096 | 
                   $labelcm = get_coursemodule_from_instance('label', $label->id);
  | 
        
        
            | 
            | 
           1097 | 
                   $tomorrow = time() + DAYSECS;
  | 
        
        
            | 
            | 
           1098 | 
                   // Module with availability restrictions not met.
  | 
        
        
            | 
            | 
           1099 | 
                   $availability = '{"op":"&","c":[{"type":"date","d":">=","t":' . $tomorrow . '},'
  | 
        
        
            | 
            | 
           1100 | 
                           .'{"type":"completion","cm":' . $label->cmid .',"e":1}],"showc":[true,true]}';
  | 
        
        
            | 
            | 
           1101 | 
                   $url = $this->getDataGenerator()->create_module('url',
  | 
        
        
            | 
            | 
           1102 | 
                       array('course' => $course->id, 'name' => 'URL: % & $ ../', 'section' => 2, 'display' => RESOURCELIB_DISPLAY_POPUP,
  | 
        
        
            | 
            | 
           1103 | 
                           'popupwidth' => 100, 'popupheight' => 100),
  | 
        
        
            | 
            | 
           1104 | 
                       array('availability' => $availability));
  | 
        
        
            | 
            | 
           1105 | 
                   $urlcm = get_coursemodule_from_instance('url', $url->id);
  | 
        
        
            | 
            | 
           1106 | 
                   // Module for the last section.
  | 
        
        
            | 
            | 
           1107 | 
                   $this->getDataGenerator()->create_module('url',
  | 
        
        
            | 
            | 
           1108 | 
                       array('course' => $course->id, 'name' => 'URL for last section', 'section' => 3));
  | 
        
        
            | 
            | 
           1109 | 
                   // Module for section 1 with availability restrictions met.
  | 
        
        
            | 
            | 
           1110 | 
                   $yesterday = time() - DAYSECS;
  | 
        
        
            | 
            | 
           1111 | 
                   $this->getDataGenerator()->create_module('url',
  | 
        
        
            | 
            | 
           1112 | 
                       array('course' => $course->id, 'name' => 'URL restrictions met', 'section' => 1),
  | 
        
        
            | 
            | 
           1113 | 
                       array('availability' => '{"op":"&","c":[{"type":"date","d":">=","t":'. $yesterday .'}],"showc":[true]}'));
  | 
        
        
            | 
            | 
           1114 | 
              | 
        
        
            | 
            | 
           1115 | 
                   // Set the required capabilities by the external function.
  | 
        
        
            | 
            | 
           1116 | 
                   $context = context_course::instance($course->id);
  | 
        
        
            | 
            | 
           1117 | 
                   $roleid = $this->assignUserCapability('moodle/course:view', $context->id);
  | 
        
        
            | 
            | 
           1118 | 
                   $this->assignUserCapability('moodle/course:update', $context->id, $roleid);
  | 
        
        
            | 
            | 
           1119 | 
                   $this->assignUserCapability('mod/data:view', $context->id, $roleid);
  | 
        
        
            | 
            | 
           1120 | 
              | 
        
        
            | 
            | 
           1121 | 
                   $conditions = array('course' => $course->id, 'section' => 2);
  | 
        
        
            | 
            | 
           1122 | 
                   $DB->set_field('course_sections', 'summary', 'Text with iframe <iframe src="https://moodle.org"></iframe>', $conditions);
  | 
        
        
            | 
            | 
           1123 | 
              | 
        
        
            | 
            | 
           1124 | 
                   // Add date availability condition not met for section 3.
  | 
        
        
            | 
            | 
           1125 | 
                   $availability = '{"op":"&","c":[{"type":"date","d":">=","t":' . $tomorrow . '}],"showc":[true]}';
  | 
        
        
            | 
            | 
           1126 | 
                   $DB->set_field('course_sections', 'availability', $availability,
  | 
        
        
            | 
            | 
           1127 | 
                           array('course' => $course->id, 'section' => 3));
  | 
        
        
            | 
            | 
           1128 | 
              | 
        
        
            | 
            | 
           1129 | 
                   // Create resource for last section.
  | 
        
        
            | 
            | 
           1130 | 
                   $pageinhiddensection = $this->getDataGenerator()->create_module('page',
  | 
        
        
            | 
            | 
           1131 | 
                       array('course' => $course->id, 'name' => 'Page in hidden section', 'section' => 4));
  | 
        
        
            | 
            | 
           1132 | 
                   // Set not visible last section.
  | 
        
        
            | 
            | 
           1133 | 
                   $DB->set_field('course_sections', 'visible', 0,
  | 
        
        
            | 
            | 
           1134 | 
                           array('course' => $course->id, 'section' => 4));
  | 
        
        
            | 
            | 
           1135 | 
              | 
        
        
            | 
            | 
           1136 | 
                   $forumcompleteauto = $this->getDataGenerator()->create_module('forum',
  | 
        
        
            | 
            | 
           1137 | 
                       array('course' => $course->id, 'intro' => 'forum completion tracking auto', 'trackingtype' => 2),
  | 
        
        
            | 
            | 
           1138 | 
                       array('showdescription' => true, 'completionview' => 1, 'completion' => COMPLETION_TRACKING_AUTOMATIC));
  | 
        
        
            | 
            | 
           1139 | 
                   $forumcompleteautocm = get_coursemodule_from_id('forum', $forumcompleteauto->cmid);
  | 
        
        
            | 
            | 
           1140 | 
                   $sectionrecord = $DB->get_record('course_sections', $conditions);
  | 
        
        
            | 
            | 
           1141 | 
                   // Invalidate the section cache by given section number.
  | 
        
        
            | 
            | 
           1142 | 
                   course_modinfo::purge_course_section_cache_by_number($sectionrecord->course, $sectionrecord->section);
  | 
        
        
            | 
            | 
           1143 | 
                   rebuild_course_cache($course->id, true, true);
  | 
        
        
            | 
            | 
           1144 | 
              | 
        
        
            | 
            | 
           1145 | 
                   return array($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm, $forumcompleteautocm);
  | 
        
        
            | 
            | 
           1146 | 
               }
  | 
        
        
            | 
            | 
           1147 | 
              | 
        
        
            | 
            | 
           1148 | 
               /**
  | 
        
        
            | 
            | 
           1149 | 
                * Test get_course_contents
  | 
        
        
            | 
            | 
           1150 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1151 | 
               public function test_get_course_contents(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1152 | 
                   global $CFG;
  | 
        
        
            | 
            | 
           1153 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1154 | 
              | 
        
        
            | 
            | 
           1155 | 
                   $CFG->forum_allowforcedreadtracking = 1;
  | 
        
        
            | 
            | 
           1156 | 
                   list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
  | 
        
        
            | 
            | 
           1157 | 
              | 
        
        
            | 
            | 
           1158 | 
                   // Create a resource with all the appearance options enabled. By default it's a text file and will be added to section 1.
  | 
        
        
            | 
            | 
           1159 | 
                   $record = (object) [
  | 
        
        
            | 
            | 
           1160 | 
                       'course' => $course->id,
  | 
        
        
            | 
            | 
           1161 | 
                       'showsize' => 1,
  | 
        
        
            | 
            | 
           1162 | 
                       'showtype' => 1,
  | 
        
        
            | 
            | 
           1163 | 
                       'showdate' => 1,
  | 
        
        
            | 
            | 
           1164 | 
                   ];
  | 
        
        
            | 
            | 
           1165 | 
                   $resource = self::getDataGenerator()->create_module('resource', $record);
  | 
        
        
            | 
            | 
           1166 | 
                   $h5pactivity = self::getDataGenerator()->create_module('h5pactivity', ['course' => $course]);
  | 
        
        
            | 
            | 
           1167 | 
              | 
        
        
            | 
            | 
           1168 | 
                   // We first run the test as admin.
  | 
        
        
            | 
            | 
           1169 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           1170 | 
                   $sections = core_course_external::get_course_contents($course->id, array());
  | 
        
        
            | 
            | 
           1171 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1172 | 
                   $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
  | 
        
        
            | 
            | 
           1173 | 
              | 
        
        
            | 
            | 
           1174 | 
                   $modinfo = get_fast_modinfo($course);
  | 
        
        
            | 
            | 
           1175 | 
                   $testexecuted = 0;
  | 
        
        
            | 
            | 
           1176 | 
                   foreach ($sections[0]['modules'] as $module) {
  | 
        
        
            | 
            | 
           1177 | 
                       if ($module['id'] == $forumcm->id and $module['modname'] == 'forum') {
  | 
        
        
            | 
            | 
           1178 | 
                           $cm = $modinfo->cms[$forumcm->id];
  | 
        
        
            | 
            | 
           1179 | 
                           $formattedtext = format_text($cm->content, FORMAT_HTML,
  | 
        
        
            | 
            | 
           1180 | 
                               array('noclean' => true, 'para' => false, 'filter' => false));
  | 
        
        
            | 
            | 
           1181 | 
                           $this->assertEquals($formattedtext, $module['description']);
  | 
        
        
            | 
            | 
           1182 | 
                           $this->assertEquals($forumcm->instance, $module['instance']);
  | 
        
        
            | 
            | 
           1183 | 
                           $this->assertEquals(context_module::instance($forumcm->id)->id, $module['contextid']);
  | 
        
        
            | 
            | 
           1184 | 
                           $this->assertFalse($module['noviewlink']);
  | 
        
        
            | 
            | 
           1185 | 
                           $this->assertNotEmpty($module['description']);  // Module showdescription is on.
  | 
        
        
            | 
            | 
           1186 | 
                           // Afterlink for forums has been removed; it has been moved to the new activity badge content.
  | 
        
        
            | 
            | 
           1187 | 
                           $this->assertEmpty($module['afterlink']);
  | 
        
        
            | 
            | 
           1188 | 
                           $this->assertEquals('1 unread post', $module['activitybadge']['badgecontent']);
  | 
        
        
            | 
            | 
           1189 | 
                           $this->assertEquals('bg-dark text-white', $module['activitybadge']['badgestyle']);
  | 
        
        
            | 
            | 
           1190 | 
                           $this->assertEquals(
  | 
        
        
            | 
            | 
           1191 | 
                               plugin_supports(
  | 
        
        
            | 
            | 
           1192 | 
                                   'mod',
  | 
        
        
            | 
            | 
           1193 | 
                                   'forum',
  | 
        
        
            | 
            | 
           1194 | 
                                   FEATURE_MOD_PURPOSE,
  | 
        
        
            | 
            | 
           1195 | 
                                   MOD_PURPOSE_OTHER
  | 
        
        
            | 
            | 
           1196 | 
                               ), $module['purpose']
  | 
        
        
            | 
            | 
           1197 | 
                           );
  | 
        
        
            | 
            | 
           1198 | 
                           $this->assertFalse($module['branded']);
  | 
        
        
            | 
            | 
           1199 | 
                           $this->assertStringContainsString('trackingtype', $module['customdata']);   // The customdata is JSON encoded.
  | 
        
        
            | 
            | 
           1200 | 
                           $testexecuted = $testexecuted + 2;
  | 
        
        
            | 
            | 
           1201 | 
                       } else if ($module['id'] == $labelcm->id and $module['modname'] == 'label') {
  | 
        
        
            | 
            | 
           1202 | 
                           $cm = $modinfo->cms[$labelcm->id];
  | 
        
        
            | 
            | 
           1203 | 
                           $formattedtext = format_text($cm->content, FORMAT_HTML,
  | 
        
        
            | 
            | 
           1204 | 
                               array('noclean' => true, 'para' => false, 'filter' => false));
  | 
        
        
            | 
            | 
           1205 | 
                           $this->assertEquals($formattedtext, $module['description']);
  | 
        
        
            | 
            | 
           1206 | 
                           $this->assertEquals($labelcm->instance, $module['instance']);
  | 
        
        
            | 
            | 
           1207 | 
                           $this->assertEquals(context_module::instance($labelcm->id)->id, $module['contextid']);
  | 
        
        
            | 
            | 
           1208 | 
                           $this->assertTrue($module['noviewlink']);
  | 
        
        
            | 
            | 
           1209 | 
                           $this->assertNotEmpty($module['description']);  // Label always prints the description.
  | 
        
        
            | 
            | 
           1210 | 
                           $this->assertEquals(
  | 
        
        
            | 
            | 
           1211 | 
                               plugin_supports(
  | 
        
        
            | 
            | 
           1212 | 
                                   'mod',
  | 
        
        
            | 
            | 
           1213 | 
                                   'label',
  | 
        
        
            | 
            | 
           1214 | 
                                   FEATURE_MOD_PURPOSE,
  | 
        
        
            | 
            | 
           1215 | 
                                   MOD_PURPOSE_OTHER
  | 
        
        
            | 
            | 
           1216 | 
                               ), $module['purpose']
  | 
        
        
            | 
            | 
           1217 | 
                           );
  | 
        
        
            | 
            | 
           1218 | 
                           $this->assertFalse($module['branded']);
  | 
        
        
            | 
            | 
           1219 | 
                           $testexecuted = $testexecuted + 1;
  | 
        
        
            | 
            | 
           1220 | 
                       } else if ($module['id'] == $datacm->id and $module['modname'] == 'data') {
  | 
        
        
            | 
            | 
           1221 | 
                           $this->assertStringContainsString('customcompletionrules', $module['customdata']);
  | 
        
        
            | 
            | 
           1222 | 
                           $this->assertFalse($module['noviewlink']);
  | 
        
        
            | 
            | 
           1223 | 
                           $this->assertArrayNotHasKey('description', $module);
  | 
        
        
            | 
            | 
           1224 | 
                           $this->assertEquals(
  | 
        
        
            | 
            | 
           1225 | 
                               plugin_supports(
  | 
        
        
            | 
            | 
           1226 | 
                                   'mod',
  | 
        
        
            | 
            | 
           1227 | 
                                   'data',
  | 
        
        
            | 
            | 
           1228 | 
                                   FEATURE_MOD_PURPOSE,
  | 
        
        
            | 
            | 
           1229 | 
                                   MOD_PURPOSE_OTHER
  | 
        
        
            | 
            | 
           1230 | 
                               ), $module['purpose']
  | 
        
        
            | 
            | 
           1231 | 
                           );
  | 
        
        
            | 
            | 
           1232 | 
                           $this->assertFalse($module['branded']);
  | 
        
        
            | 
            | 
           1233 | 
                           $testexecuted = $testexecuted + 1;
  | 
        
        
            | 
            | 
           1234 | 
                       } else if ($module['instance'] == $resource->id && $module['modname'] == 'resource') {
  | 
        
        
            | 
            | 
           1235 | 
                           // Resources have both, afterlink for the size and the update date and activitybadge for the file type.
  | 
        
        
            | 
            | 
           1236 | 
                           $this->assertStringContainsString('32 bytes', $module['afterlink']);
  | 
        
        
            | 
            | 
           1237 | 
                           $this->assertEquals('TXT', $module['activitybadge']['badgecontent']);
  | 
        
        
            | 
            | 
           1238 | 
                           $this->assertEquals('badge-none', $module['activitybadge']['badgestyle']);
  | 
        
        
            | 
            | 
           1239 | 
                           $this->assertEquals(
  | 
        
        
            | 
            | 
           1240 | 
                               plugin_supports(
  | 
        
        
            | 
            | 
           1241 | 
                                   'mod',
  | 
        
        
            | 
            | 
           1242 | 
                                   'resource',
  | 
        
        
            | 
            | 
           1243 | 
                                   FEATURE_MOD_PURPOSE,
  | 
        
        
            | 
            | 
           1244 | 
                                   MOD_PURPOSE_OTHER
  | 
        
        
            | 
            | 
           1245 | 
                               ), $module['purpose']
  | 
        
        
            | 
            | 
           1246 | 
                           );
  | 
        
        
            | 
            | 
           1247 | 
                           $this->assertFalse($module['branded']);
  | 
        
        
            | 
            | 
           1248 | 
                           $testexecuted = $testexecuted + 1;
  | 
        
        
            | 
            | 
           1249 | 
                       } else if ($module['instance'] == $h5pactivity->id && $module['modname'] == 'h5pactivity') {
  | 
        
        
            | 
            | 
           1250 | 
                           $this->assertEquals(
  | 
        
        
            | 
            | 
           1251 | 
                               plugin_supports(
  | 
        
        
            | 
            | 
           1252 | 
                                   'mod',
  | 
        
        
            | 
            | 
           1253 | 
                                   'h5pactivity',
  | 
        
        
            | 
            | 
           1254 | 
                                   FEATURE_MOD_PURPOSE,
  | 
        
        
            | 
            | 
           1255 | 
                                   MOD_PURPOSE_OTHER
  | 
        
        
            | 
            | 
           1256 | 
                               ), $module['purpose']
  | 
        
        
            | 
            | 
           1257 | 
                           );
  | 
        
        
            | 
            | 
           1258 | 
                           $this->assertTrue($module['branded']);
  | 
        
        
            | 
            | 
           1259 | 
                           $testexecuted = $testexecuted + 1;
  | 
        
        
            | 
            | 
           1260 | 
                       }
  | 
        
        
            | 
            | 
           1261 | 
                   }
  | 
        
        
            | 
            | 
           1262 | 
                   foreach ($sections[2]['modules'] as $module) {
  | 
        
        
            | 
            | 
           1263 | 
                       if ($module['id'] == $urlcm->id and $module['modname'] == 'url') {
  | 
        
        
            | 
            | 
           1264 | 
                           $this->assertStringContainsString('width=100,height=100', $module['onclick']);
  | 
        
        
            | 
            | 
           1265 | 
                           $testexecuted = $testexecuted + 1;
  | 
        
        
            | 
            | 
           1266 | 
                       }
  | 
        
        
            | 
            | 
           1267 | 
                   }
  | 
        
        
            | 
            | 
           1268 | 
              | 
        
        
            | 
            | 
           1269 | 
                   $CFG->forum_allowforcedreadtracking = 0;    // Recover original value.
  | 
        
        
            | 
            | 
           1270 | 
                   forum_tp_count_forum_unread_posts($forumcm, $course, true);    // Reset static cache for further tests.
  | 
        
        
            | 
            | 
           1271 | 
              | 
        
        
            | 
            | 
           1272 | 
                   $this->assertEquals(7, $testexecuted);
  | 
        
        
            | 
            | 
           1273 | 
                   $this->assertEquals(0, $sections[0]['section']);
  | 
        
        
            | 
            | 
           1274 | 
              | 
        
        
            | 
            | 
           1275 | 
                   $this->assertCount(8, $sections[0]['modules']);
  | 
        
        
            | 
            | 
           1276 | 
                   $this->assertCount(1, $sections[1]['modules']);
  | 
        
        
            | 
            | 
           1277 | 
                   $this->assertCount(1, $sections[2]['modules']);
  | 
        
        
            | 
            | 
           1278 | 
                   $this->assertCount(1, $sections[3]['modules']); // One module for the section with availability restrictions.
  | 
        
        
            | 
            | 
           1279 | 
                   $this->assertCount(1, $sections[4]['modules']); // One module for the hidden section with a visible activity.
  | 
        
        
            | 
            | 
           1280 | 
                   $this->assertNotEmpty($sections[3]['availabilityinfo']);
  | 
        
        
            | 
            | 
           1281 | 
                   $this->assertEquals(1, $sections[1]['section']);
  | 
        
        
            | 
            | 
           1282 | 
                   $this->assertEquals(2, $sections[2]['section']);
  | 
        
        
            | 
            | 
           1283 | 
                   $this->assertEquals(3, $sections[3]['section']);
  | 
        
        
            | 
            | 
           1284 | 
                   $this->assertEquals(4, $sections[4]['section']);
  | 
        
        
            | 
            | 
           1285 | 
                   $this->assertStringContainsString('<iframe', $sections[2]['summary']);
  | 
        
        
            | 
            | 
           1286 | 
                   $this->assertStringContainsString('</iframe>', $sections[2]['summary']);
  | 
        
        
            | 
            | 
           1287 | 
                   $this->assertNotEmpty($sections[2]['modules'][0]['availabilityinfo']);
  | 
        
        
            | 
            | 
           1288 | 
                   try {
  | 
        
        
            | 
            | 
           1289 | 
                       $sections = core_course_external::get_course_contents($course->id,
  | 
        
        
            | 
            | 
           1290 | 
                                                                               array(array("name" => "invalid", "value" => 1)));
  | 
        
        
            | 
            | 
           1291 | 
                       $this->fail('Exception expected due to invalid option.');
  | 
        
        
            | 
            | 
           1292 | 
                   } catch (moodle_exception $e) {
  | 
        
        
            | 
            | 
           1293 | 
                       $this->assertEquals('errorinvalidparam', $e->errorcode);
  | 
        
        
            | 
            | 
           1294 | 
                   }
  | 
        
        
            | 
            | 
           1295 | 
               }
  | 
        
        
            | 
            | 
           1296 | 
              | 
        
        
            | 
            | 
           1297 | 
              | 
        
        
            | 
            | 
           1298 | 
               /**
  | 
        
        
            | 
            | 
           1299 | 
                * Test get_course_contents as student
  | 
        
        
            | 
            | 
           1300 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1301 | 
               public function test_get_course_contents_student(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1302 | 
                   global $DB;
  | 
        
        
            | 
            | 
           1303 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1304 | 
              | 
        
        
            | 
            | 
           1305 | 
                   list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
  | 
        
        
            | 
            | 
           1306 | 
              | 
        
        
            | 
            | 
           1307 | 
                   $studentroleid = $DB->get_field('role', 'id', array('shortname' => 'student'));
  | 
        
        
            | 
            | 
           1308 | 
                   $user = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           1309 | 
                   self::getDataGenerator()->enrol_user($user->id, $course->id, $studentroleid);
  | 
        
        
            | 
            | 
           1310 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           1311 | 
              | 
        
        
            | 
            | 
           1312 | 
                   $sections = core_course_external::get_course_contents($course->id, array());
  | 
        
        
            | 
            | 
           1313 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1314 | 
                   $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
  | 
        
        
            | 
            | 
           1315 | 
              | 
        
        
            | 
            | 
           1316 | 
                   $this->assertCount(4, $sections); // Nothing for the not visible section.
  | 
        
        
            | 
            | 
           1317 | 
                   $this->assertCount(6, $sections[0]['modules']);
  | 
        
        
            | 
            | 
           1318 | 
                   $this->assertCount(1, $sections[1]['modules']);
  | 
        
        
            | 
            | 
           1319 | 
                   $this->assertCount(1, $sections[2]['modules']);
  | 
        
        
            | 
            | 
           1320 | 
                   $this->assertCount(0, $sections[3]['modules']); // No modules for the section with availability restrictions.
  | 
        
        
            | 
            | 
           1321 | 
              | 
        
        
            | 
            | 
           1322 | 
                   $this->assertNotEmpty($sections[3]['availabilityinfo']);
  | 
        
        
            | 
            | 
           1323 | 
                   $this->assertEquals(1, $sections[1]['section']);
  | 
        
        
            | 
            | 
           1324 | 
                   $this->assertEquals(2, $sections[2]['section']);
  | 
        
        
            | 
            | 
           1325 | 
                   $this->assertEquals(3, $sections[3]['section']);
  | 
        
        
            | 
            | 
           1326 | 
                   // The module with the availability restriction met is returning contents.
  | 
        
        
            | 
            | 
           1327 | 
                   $this->assertNotEmpty($sections[1]['modules'][0]['contents']);
  | 
        
        
            | 
            | 
           1328 | 
                   // The module with the availability restriction not met is not returning contents.
  | 
        
        
            | 
            | 
           1329 | 
                   $this->assertArrayNotHasKey('contents', $sections[2]['modules'][0]);
  | 
        
        
            | 
            | 
           1330 | 
              | 
        
        
            | 
            | 
           1331 | 
                   // Now include flag for returning stealth information (fake section).
  | 
        
        
            | 
            | 
           1332 | 
                   $sections = core_course_external::get_course_contents($course->id,
  | 
        
        
            | 
            | 
           1333 | 
                       array(array("name" => "includestealthmodules", "value" => 1)));
  | 
        
        
            | 
            | 
           1334 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1335 | 
                   $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
  | 
        
        
            | 
            | 
           1336 | 
              | 
        
        
            | 
            | 
           1337 | 
                   $this->assertCount(5, $sections); // Include fake section with stealth activities.
  | 
        
        
            | 
            | 
           1338 | 
                   $this->assertCount(6, $sections[0]['modules']);
  | 
        
        
            | 
            | 
           1339 | 
                   $this->assertCount(1, $sections[1]['modules']);
  | 
        
        
            | 
            | 
           1340 | 
                   $this->assertCount(1, $sections[2]['modules']);
  | 
        
        
            | 
            | 
           1341 | 
                   $this->assertCount(0, $sections[3]['modules']); // No modules for the section with availability restrictions.
  | 
        
        
            | 
            | 
           1342 | 
                   $this->assertCount(1, $sections[4]['modules']); // One stealth module.
  | 
        
        
            | 
            | 
           1343 | 
                   $this->assertEquals(-1, $sections[4]['id']);
  | 
        
        
            | 
            | 
           1344 | 
               }
  | 
        
        
            | 
            | 
           1345 | 
              | 
        
        
            | 
            | 
           1346 | 
               /**
  | 
        
        
            | 
            | 
           1347 | 
                * Test get_course_contents excluding modules
  | 
        
        
            | 
            | 
           1348 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1349 | 
               public function test_get_course_contents_excluding_modules(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1350 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1351 | 
              | 
        
        
            | 
            | 
           1352 | 
                   list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
  | 
        
        
            | 
            | 
           1353 | 
              | 
        
        
            | 
            | 
           1354 | 
                   // Test exclude modules.
  | 
        
        
            | 
            | 
           1355 | 
                   $sections = core_course_external::get_course_contents($course->id, array(array("name" => "excludemodules", "value" => 1)));
  | 
        
        
            | 
            | 
           1356 | 
              | 
        
        
            | 
            | 
           1357 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1358 | 
                   $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
  | 
        
        
            | 
            | 
           1359 | 
              | 
        
        
            | 
            | 
           1360 | 
                   $this->assertEmpty($sections[0]['modules']);
  | 
        
        
            | 
            | 
           1361 | 
                   $this->assertEmpty($sections[1]['modules']);
  | 
        
        
            | 
            | 
           1362 | 
               }
  | 
        
        
            | 
            | 
           1363 | 
              | 
        
        
            | 
            | 
           1364 | 
               /**
  | 
        
        
            | 
            | 
           1365 | 
                * Test get_course_contents excluding contents
  | 
        
        
            | 
            | 
           1366 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1367 | 
               public function test_get_course_contents_excluding_contents(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1368 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1369 | 
              | 
        
        
            | 
            | 
           1370 | 
                   list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
  | 
        
        
            | 
            | 
           1371 | 
              | 
        
        
            | 
            | 
           1372 | 
                   // Test exclude modules.
  | 
        
        
            | 
            | 
           1373 | 
                   $sections = core_course_external::get_course_contents($course->id, array(array("name" => "excludecontents", "value" => 1)));
  | 
        
        
            | 
            | 
           1374 | 
              | 
        
        
            | 
            | 
           1375 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1376 | 
                   $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
  | 
        
        
            | 
            | 
           1377 | 
              | 
        
        
            | 
            | 
           1378 | 
                   foreach ($sections as $section) {
  | 
        
        
            | 
            | 
           1379 | 
                       foreach ($section['modules'] as $module) {
  | 
        
        
            | 
            | 
           1380 | 
                           // Only resources return contents.
  | 
        
        
            | 
            | 
           1381 | 
                           if (isset($module['contents'])) {
  | 
        
        
            | 
            | 
           1382 | 
                               $this->assertEmpty($module['contents']);
  | 
        
        
            | 
            | 
           1383 | 
                           }
  | 
        
        
            | 
            | 
           1384 | 
                       }
  | 
        
        
            | 
            | 
           1385 | 
                   }
  | 
        
        
            | 
            | 
           1386 | 
               }
  | 
        
        
            | 
            | 
           1387 | 
              | 
        
        
            | 
            | 
           1388 | 
               /**
  | 
        
        
            | 
            | 
           1389 | 
                * Test get_course_contents filtering by section number
  | 
        
        
            | 
            | 
           1390 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1391 | 
               public function test_get_course_contents_section_number(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1392 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1393 | 
              | 
        
        
            | 
            | 
           1394 | 
                   list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
  | 
        
        
            | 
            | 
           1395 | 
              | 
        
        
            | 
            | 
           1396 | 
                   // Test exclude modules.
  | 
        
        
            | 
            | 
           1397 | 
                   $sections = core_course_external::get_course_contents($course->id, array(array("name" => "sectionnumber", "value" => 0)));
  | 
        
        
            | 
            | 
           1398 | 
              | 
        
        
            | 
            | 
           1399 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1400 | 
                   $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
  | 
        
        
            | 
            | 
           1401 | 
              | 
        
        
            | 
            | 
           1402 | 
                   $this->assertCount(1, $sections);
  | 
        
        
            | 
            | 
           1403 | 
                   $this->assertCount(6, $sections[0]['modules']);
  | 
        
        
            | 
            | 
           1404 | 
               }
  | 
        
        
            | 
            | 
           1405 | 
              | 
        
        
            | 
            | 
           1406 | 
               /**
  | 
        
        
            | 
            | 
           1407 | 
                * Test get_course_contents filtering by cmid
  | 
        
        
            | 
            | 
           1408 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1409 | 
               public function test_get_course_contents_cmid(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1410 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1411 | 
              | 
        
        
            | 
            | 
           1412 | 
                   list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
  | 
        
        
            | 
            | 
           1413 | 
              | 
        
        
            | 
            | 
           1414 | 
                   // Test exclude modules.
  | 
        
        
            | 
            | 
           1415 | 
                   $sections = core_course_external::get_course_contents($course->id, array(array("name" => "cmid", "value" => $forumcm->id)));
  | 
        
        
            | 
            | 
           1416 | 
              | 
        
        
            | 
            | 
           1417 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1418 | 
                   $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
  | 
        
        
            | 
            | 
           1419 | 
              | 
        
        
            | 
            | 
           1420 | 
                   $this->assertCount(4, $sections);
  | 
        
        
            | 
            | 
           1421 | 
                   $this->assertCount(1, $sections[0]['modules']);
  | 
        
        
            | 
            | 
           1422 | 
                   $this->assertEquals($forumcm->id, $sections[0]['modules'][0]["id"]);
  | 
        
        
            | 
            | 
           1423 | 
               }
  | 
        
        
            | 
            | 
           1424 | 
              | 
        
        
            | 
            | 
           1425 | 
              | 
        
        
            | 
            | 
           1426 | 
               /**
  | 
        
        
            | 
            | 
           1427 | 
                * Test get_course_contents filtering by cmid and section
  | 
        
        
            | 
            | 
           1428 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1429 | 
               public function test_get_course_contents_section_cmid(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1430 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1431 | 
              | 
        
        
            | 
            | 
           1432 | 
                   list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
  | 
        
        
            | 
            | 
           1433 | 
              | 
        
        
            | 
            | 
           1434 | 
                   // Test exclude modules.
  | 
        
        
            | 
            | 
           1435 | 
                   $sections = core_course_external::get_course_contents($course->id, array(
  | 
        
        
            | 
            | 
           1436 | 
                                                                                   array("name" => "cmid", "value" => $forumcm->id),
  | 
        
        
            | 
            | 
           1437 | 
                                                                                   array("name" => "sectionnumber", "value" => 0)
  | 
        
        
            | 
            | 
           1438 | 
                                                                                   ));
  | 
        
        
            | 
            | 
           1439 | 
              | 
        
        
            | 
            | 
           1440 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1441 | 
                   $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
  | 
        
        
            | 
            | 
           1442 | 
              | 
        
        
            | 
            | 
           1443 | 
                   $this->assertCount(1, $sections);
  | 
        
        
            | 
            | 
           1444 | 
                   $this->assertCount(1, $sections[0]['modules']);
  | 
        
        
            | 
            | 
           1445 | 
                   $this->assertEquals($forumcm->id, $sections[0]['modules'][0]["id"]);
  | 
        
        
            | 
            | 
           1446 | 
               }
  | 
        
        
            | 
            | 
           1447 | 
              | 
        
        
            | 
            | 
           1448 | 
               /**
  | 
        
        
            | 
            | 
           1449 | 
                * Test get_course_contents filtering by modname
  | 
        
        
            | 
            | 
           1450 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1451 | 
               public function test_get_course_contents_modname(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1452 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1453 | 
              | 
        
        
            | 
            | 
           1454 | 
                   list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
  | 
        
        
            | 
            | 
           1455 | 
              | 
        
        
            | 
            | 
           1456 | 
                   // Test exclude modules.
  | 
        
        
            | 
            | 
           1457 | 
                   $sections = core_course_external::get_course_contents($course->id, array(array("name" => "modname", "value" => "forum")));
  | 
        
        
            | 
            | 
           1458 | 
              | 
        
        
            | 
            | 
           1459 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1460 | 
                   $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
  | 
        
        
            | 
            | 
           1461 | 
              | 
        
        
            | 
            | 
           1462 | 
                   $this->assertCount(4, $sections);
  | 
        
        
            | 
            | 
           1463 | 
                   $this->assertCount(2, $sections[0]['modules']);
  | 
        
        
            | 
            | 
           1464 | 
                   $this->assertEquals($forumcm->id, $sections[0]['modules'][0]["id"]);
  | 
        
        
            | 
            | 
           1465 | 
               }
  | 
        
        
            | 
            | 
           1466 | 
              | 
        
        
            | 
            | 
           1467 | 
               /**
  | 
        
        
            | 
            | 
           1468 | 
                * Test get_course_contents filtering by modname
  | 
        
        
            | 
            | 
           1469 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1470 | 
               public function test_get_course_contents_modid(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1471 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1472 | 
              | 
        
        
            | 
            | 
           1473 | 
                   list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
  | 
        
        
            | 
            | 
           1474 | 
              | 
        
        
            | 
            | 
           1475 | 
                   // Test exclude modules.
  | 
        
        
            | 
            | 
           1476 | 
                   $sections = core_course_external::get_course_contents($course->id, array(
  | 
        
        
            | 
            | 
           1477 | 
                                                                                       array("name" => "modname", "value" => "page"),
  | 
        
        
            | 
            | 
           1478 | 
                                                                                       array("name" => "modid", "value" => $pagecm->instance),
  | 
        
        
            | 
            | 
           1479 | 
                                                                                       ));
  | 
        
        
            | 
            | 
           1480 | 
              | 
        
        
            | 
            | 
           1481 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1482 | 
                   $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
  | 
        
        
            | 
            | 
           1483 | 
              | 
        
        
            | 
            | 
           1484 | 
                   $this->assertCount(4, $sections);
  | 
        
        
            | 
            | 
           1485 | 
                   $this->assertCount(1, $sections[0]['modules']);
  | 
        
        
            | 
            | 
           1486 | 
                   $this->assertEquals("page", $sections[0]['modules'][0]["modname"]);
  | 
        
        
            | 
            | 
           1487 | 
                   $this->assertEquals($pagecm->instance, $sections[0]['modules'][0]["instance"]);
  | 
        
        
            | 
            | 
           1488 | 
               }
  | 
        
        
            | 
            | 
           1489 | 
              | 
        
        
            | 
            | 
           1490 | 
               /**
  | 
        
        
            | 
            | 
           1491 | 
                * Test get_course_contents returns downloadcontent value.
  | 
        
        
            | 
            | 
           1492 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1493 | 
               public function test_get_course_contents_downloadcontent(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1494 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           1495 | 
              | 
        
        
            | 
            | 
           1496 | 
                   list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
  | 
        
        
            | 
            | 
           1497 | 
              | 
        
        
            | 
            | 
           1498 | 
                   // Test exclude modules.
  | 
        
        
            | 
            | 
           1499 | 
                   $sections = core_course_external::get_course_contents($course->id, [
  | 
        
        
            | 
            | 
           1500 | 
                       ['name' => 'modname', 'value' => 'page'],
  | 
        
        
            | 
            | 
           1501 | 
                       ['name' => 'modid', 'value' => $pagecm->instance]
  | 
        
        
            | 
            | 
           1502 | 
                   ]);
  | 
        
        
            | 
            | 
           1503 | 
              | 
        
        
            | 
            | 
           1504 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1505 | 
                   $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
  | 
        
        
            | 
            | 
           1506 | 
                   $this->assertCount(1, $sections[0]['modules']);
  | 
        
        
            | 
            | 
           1507 | 
                   $this->assertEquals('page', $sections[0]['modules'][0]['modname']);
  | 
        
        
            | 
            | 
           1508 | 
                   $this->assertEquals($pagecm->downloadcontent, $sections[0]['modules'][0]['downloadcontent']);
  | 
        
        
            | 
            | 
           1509 | 
                   $this->assertEquals(DOWNLOAD_COURSE_CONTENT_ENABLED, $sections[0]['modules'][0]['downloadcontent']);
  | 
        
        
            | 
            | 
           1510 | 
               }
  | 
        
        
            | 
            | 
           1511 | 
              | 
        
        
            | 
            | 
           1512 | 
               /**
  | 
        
        
            | 
            | 
           1513 | 
                * Test get course contents completion manual
  | 
        
        
            | 
            | 
           1514 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1515 | 
               public function test_get_course_contents_completion_manual(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1516 | 
                   global $CFG;
  | 
        
        
            | 
            | 
           1517 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1518 | 
              | 
        
        
            | 
            | 
           1519 | 
                   list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm, $forumcompleteautocm) =
  | 
        
        
            | 
            | 
           1520 | 
                       $this->prepare_get_course_contents_test();
  | 
        
        
            | 
            | 
           1521 | 
                   availability_completion\condition::wipe_static_cache();
  | 
        
        
            | 
            | 
           1522 | 
              | 
        
        
            | 
            | 
           1523 | 
                   // Test activity not completed yet.
  | 
        
        
            | 
            | 
           1524 | 
                   $result = core_course_external::get_course_contents($course->id, array(
  | 
        
        
            | 
            | 
           1525 | 
                       array("name" => "modname", "value" => "forum"), array("name" => "modid", "value" => $forumcm->instance)));
  | 
        
        
            | 
            | 
           1526 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1527 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $result);
  | 
        
        
            | 
            | 
           1528 | 
              | 
        
        
            | 
            | 
           1529 | 
                   $completiondata = $result[0]['modules'][0]["completiondata"];
  | 
        
        
            | 
            | 
           1530 | 
                   $this->assertCount(1, $result[0]['modules']);
  | 
        
        
            | 
            | 
           1531 | 
                   $this->assertEquals("forum", $result[0]['modules'][0]["modname"]);
  | 
        
        
            | 
            | 
           1532 | 
                   $this->assertEquals(COMPLETION_TRACKING_MANUAL, $result[0]['modules'][0]["completion"]);
  | 
        
        
            | 
            | 
           1533 | 
                   $this->assertEquals(0, $completiondata['state']);
  | 
        
        
            | 
            | 
           1534 | 
                   $this->assertEquals(0, $completiondata['timecompleted']);
  | 
        
        
            | 
            | 
           1535 | 
                   $this->assertEmpty($completiondata['overrideby']);
  | 
        
        
            | 
            | 
           1536 | 
                   $this->assertFalse($completiondata['valueused']);
  | 
        
        
            | 
            | 
           1537 | 
                   $this->assertTrue($completiondata['hascompletion']);
  | 
        
        
            | 
            | 
           1538 | 
                   $this->assertFalse($completiondata['isautomatic']);
  | 
        
        
            | 
            | 
           1539 | 
                   $this->assertFalse($completiondata['istrackeduser']);
  | 
        
        
            | 
            | 
           1540 | 
                   $this->assertTrue($completiondata['uservisible']);
  | 
        
        
            | 
            | 
           1541 | 
                   $this->assertFalse($completiondata['isoverallcomplete']);
  | 
        
        
            | 
            | 
           1542 | 
              | 
        
        
            | 
            | 
           1543 | 
                   // Set activity completed.
  | 
        
        
            | 
            | 
           1544 | 
                   core_completion_external::update_activity_completion_status_manually($forumcm->id, true);
  | 
        
        
            | 
            | 
           1545 | 
              | 
        
        
            | 
            | 
           1546 | 
                   $result = core_course_external::get_course_contents($course->id, array(
  | 
        
        
            | 
            | 
           1547 | 
                       array("name" => "modname", "value" => "forum"), array("name" => "modid", "value" => $forumcm->instance)));
  | 
        
        
            | 
            | 
           1548 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1549 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $result);
  | 
        
        
            | 
            | 
           1550 | 
              | 
        
        
            | 
            | 
           1551 | 
                   $this->assertEquals(COMPLETION_COMPLETE, $result[0]['modules'][0]["completiondata"]['state']);
  | 
        
        
            | 
            | 
           1552 | 
                   $this->assertTrue($result[0]['modules'][0]["completiondata"]['isoverallcomplete']);
  | 
        
        
            | 
            | 
           1553 | 
                   $this->assertNotEmpty($result[0]['modules'][0]["completiondata"]['timecompleted']);
  | 
        
        
            | 
            | 
           1554 | 
                   $this->assertEmpty($result[0]['modules'][0]["completiondata"]['overrideby']);
  | 
        
        
            | 
            | 
           1555 | 
              | 
        
        
            | 
            | 
           1556 | 
                   // Test activity with completion value that is used in an availability condition.
  | 
        
        
            | 
            | 
           1557 | 
                   $result = core_course_external::get_course_contents($course->id, array(
  | 
        
        
            | 
            | 
           1558 | 
                           array("name" => "modname", "value" => "label"), array("name" => "modid", "value" => $labelcm->instance)));
  | 
        
        
            | 
            | 
           1559 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1560 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $result);
  | 
        
        
            | 
            | 
           1561 | 
              | 
        
        
            | 
            | 
           1562 | 
                   $completiondata = $result[0]['modules'][0]["completiondata"];
  | 
        
        
            | 
            | 
           1563 | 
                   $this->assertCount(1, $result[0]['modules']);
  | 
        
        
            | 
            | 
           1564 | 
                   $this->assertEquals("label", $result[0]['modules'][0]["modname"]);
  | 
        
        
            | 
            | 
           1565 | 
                   $this->assertEquals(COMPLETION_TRACKING_MANUAL, $result[0]['modules'][0]["completion"]);
  | 
        
        
            | 
            | 
           1566 | 
                   $this->assertEquals(0, $completiondata['state']);
  | 
        
        
            | 
            | 
           1567 | 
                   $this->assertEquals(0, $completiondata['timecompleted']);
  | 
        
        
            | 
            | 
           1568 | 
                   $this->assertEmpty($completiondata['overrideby']);
  | 
        
        
            | 
            | 
           1569 | 
                   $this->assertTrue($completiondata['valueused']);
  | 
        
        
            | 
            | 
           1570 | 
                   $this->assertTrue($completiondata['hascompletion']);
  | 
        
        
            | 
            | 
           1571 | 
                   $this->assertFalse($completiondata['isautomatic']);
  | 
        
        
            | 
            | 
           1572 | 
                   $this->assertFalse($completiondata['istrackeduser']);
  | 
        
        
            | 
            | 
           1573 | 
                   $this->assertTrue($completiondata['uservisible']);
  | 
        
        
            | 
            | 
           1574 | 
                   $this->assertFalse($completiondata['isoverallcomplete']);
  | 
        
        
            | 
            | 
           1575 | 
              | 
        
        
            | 
            | 
           1576 | 
                   // Disable completion.
  | 
        
        
            | 
            | 
           1577 | 
                   $CFG->enablecompletion = 0;
  | 
        
        
            | 
            | 
           1578 | 
                   $result = core_course_external::get_course_contents($course->id, array(
  | 
        
        
            | 
            | 
           1579 | 
                       array("name" => "modname", "value" => "forum"), array("name" => "modid", "value" => $forumcm->instance)));
  | 
        
        
            | 
            | 
           1580 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1581 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $result);
  | 
        
        
            | 
            | 
           1582 | 
              | 
        
        
            | 
            | 
           1583 | 
                   $this->assertArrayNotHasKey('completiondata', $result[0]['modules'][0]);
  | 
        
        
            | 
            | 
           1584 | 
               }
  | 
        
        
            | 
            | 
           1585 | 
              | 
        
        
            | 
            | 
           1586 | 
               /**
  | 
        
        
            | 
            | 
           1587 | 
                * Test get course contents completion auto
  | 
        
        
            | 
            | 
           1588 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1589 | 
               public function test_get_course_contents_completion_auto(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1590 | 
                   global $CFG;
  | 
        
        
            | 
            | 
           1591 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1592 | 
              | 
        
        
            | 
            | 
           1593 | 
                   list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm, $forumcompleteautocm) =
  | 
        
        
            | 
            | 
           1594 | 
                       $this->prepare_get_course_contents_test();
  | 
        
        
            | 
            | 
           1595 | 
                   availability_completion\condition::wipe_static_cache();
  | 
        
        
            | 
            | 
           1596 | 
              | 
        
        
            | 
            | 
           1597 | 
                   // Test activity not completed yet.
  | 
        
        
            | 
            | 
           1598 | 
                   $result = core_course_external::get_course_contents($course->id, [
  | 
        
        
            | 
            | 
           1599 | 
                       [
  | 
        
        
            | 
            | 
           1600 | 
                           "name" => "modname",
  | 
        
        
            | 
            | 
           1601 | 
                           "value" => "forum"
  | 
        
        
            | 
            | 
           1602 | 
                       ],
  | 
        
        
            | 
            | 
           1603 | 
                       [
  | 
        
        
            | 
            | 
           1604 | 
                           "name" => "modid",
  | 
        
        
            | 
            | 
           1605 | 
                           "value" => $forumcompleteautocm->instance
  | 
        
        
            | 
            | 
           1606 | 
                       ]
  | 
        
        
            | 
            | 
           1607 | 
                   ]);
  | 
        
        
            | 
            | 
           1608 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1609 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $result);
  | 
        
        
            | 
            | 
           1610 | 
              | 
        
        
            | 
            | 
           1611 | 
                   $forummod = $result[0]['modules'][0];
  | 
        
        
            | 
            | 
           1612 | 
                   $completiondata = $forummod["completiondata"];
  | 
        
        
            | 
            | 
           1613 | 
                   $this->assertCount(1, $result[0]['modules']);
  | 
        
        
            | 
            | 
           1614 | 
                   $this->assertEquals("forum", $forummod["modname"]);
  | 
        
        
            | 
            | 
           1615 | 
                   $this->assertEquals(COMPLETION_TRACKING_AUTOMATIC, $forummod["completion"]);
  | 
        
        
            | 
            | 
           1616 | 
                   $this->assertEquals(0, $completiondata['state']);
  | 
        
        
            | 
            | 
           1617 | 
                   $this->assertEquals(0, $completiondata['timecompleted']);
  | 
        
        
            | 
            | 
           1618 | 
                   $this->assertEmpty($completiondata['overrideby']);
  | 
        
        
            | 
            | 
           1619 | 
                   $this->assertFalse($completiondata['valueused']);
  | 
        
        
            | 
            | 
           1620 | 
                   $this->assertTrue($completiondata['hascompletion']);
  | 
        
        
            | 
            | 
           1621 | 
                   $this->assertTrue($completiondata['isautomatic']);
  | 
        
        
            | 
            | 
           1622 | 
                   $this->assertFalse($completiondata['istrackeduser']);
  | 
        
        
            | 
            | 
           1623 | 
                   $this->assertTrue($completiondata['uservisible']);
  | 
        
        
            | 
            | 
           1624 | 
                   $this->assertCount(1, $completiondata['details']);
  | 
        
        
            | 
            | 
           1625 | 
                   $this->assertFalse($completiondata['isoverallcomplete']);
  | 
        
        
            | 
            | 
           1626 | 
               }
  | 
        
        
            | 
            | 
           1627 | 
              | 
        
        
            | 
            | 
           1628 | 
               /**
  | 
        
        
            | 
            | 
           1629 | 
                * Test mimetype is returned for resources with showtype set.
  | 
        
        
            | 
            | 
           1630 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1631 | 
               public function test_get_course_contents_including_mimetype(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1632 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1633 | 
              | 
        
        
            | 
            | 
           1634 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           1635 | 
                   $course = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           1636 | 
              | 
        
        
            | 
            | 
           1637 | 
                   $record = new stdClass();
  | 
        
        
            | 
            | 
           1638 | 
                   $record->course = $course->id;
  | 
        
        
            | 
            | 
           1639 | 
                   $record->showtype = 1;
  | 
        
        
            | 
            | 
           1640 | 
                   $resource = self::getDataGenerator()->create_module('resource', $record);
  | 
        
        
            | 
            | 
           1641 | 
              | 
        
        
            | 
            | 
           1642 | 
                   $result = core_course_external::get_course_contents($course->id);
  | 
        
        
            | 
            | 
           1643 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $result);
  | 
        
        
            | 
            | 
           1644 | 
                   $this->assertCount(1, $result[0]['modules']);   // One module, first section.
  | 
        
        
            | 
            | 
           1645 | 
                   $customdata = json_decode($result[0]['modules'][0]['customdata']);
  | 
        
        
            | 
            | 
           1646 | 
                   $displayoptions = unserialize($customdata->displayoptions);
  | 
        
        
            | 
            | 
           1647 | 
                   $this->assertEquals('text/plain', $displayoptions['filedetails']['mimetype']);
  | 
        
        
            | 
            | 
           1648 | 
               }
  | 
        
        
            | 
            | 
           1649 | 
              | 
        
        
            | 
            | 
           1650 | 
               /**
  | 
        
        
            | 
            | 
           1651 | 
                * Test contents info is returned.
  | 
        
        
            | 
            | 
           1652 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1653 | 
               public function test_get_course_contents_contentsinfo(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1654 | 
                   global $USER;
  | 
        
        
            | 
            | 
           1655 | 
              | 
        
        
            | 
            | 
           1656 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1657 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           1658 | 
                   $timenow = time();
  | 
        
        
            | 
            | 
           1659 | 
              | 
        
        
            | 
            | 
           1660 | 
                   $course = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           1661 | 
              | 
        
        
            | 
            | 
           1662 | 
                   $record = new stdClass();
  | 
        
        
            | 
            | 
           1663 | 
                   $record->course = $course->id;
  | 
        
        
            | 
            | 
           1664 | 
                   // One resource with one file.
  | 
        
        
            | 
            | 
           1665 | 
                   $resource1 = self::getDataGenerator()->create_module('resource', $record);
  | 
        
        
            | 
            | 
           1666 | 
              | 
        
        
            | 
            | 
           1667 | 
                   // More type of files.
  | 
        
        
            | 
            | 
           1668 | 
                   $record->files = file_get_unused_draft_itemid();
  | 
        
        
            | 
            | 
           1669 | 
                   $usercontext = context_user::instance($USER->id);
  | 
        
        
            | 
            | 
           1670 | 
                   $extensions = array('txt', 'png', 'pdf');
  | 
        
        
            | 
            | 
           1671 | 
                   $fs = get_file_storage();
  | 
        
        
            | 
            | 
           1672 | 
                   foreach ($extensions as $key => $extension) {
  | 
        
        
            | 
            | 
           1673 | 
                       // Add actual file there.
  | 
        
        
            | 
            | 
           1674 | 
                       $filerecord = array('component' => 'user', 'filearea' => 'draft',
  | 
        
        
            | 
            | 
           1675 | 
                               'contextid' => $usercontext->id, 'itemid' => $record->files,
  | 
        
        
            | 
            | 
           1676 | 
                               'filename' => 'resource' . $key . '.' . $extension, 'filepath' => '/');
  | 
        
        
            | 
            | 
           1677 | 
                       $fs->create_file_from_string($filerecord, 'Test resource ' . $key . ' file');
  | 
        
        
            | 
            | 
           1678 | 
                   }
  | 
        
        
            | 
            | 
           1679 | 
              | 
        
        
            | 
            | 
           1680 | 
                   // Create file reference.
  | 
        
        
            | 
            | 
           1681 | 
                   $repos = repository::get_instances(array('type' => 'user'));
  | 
        
        
            | 
            | 
           1682 | 
                   $userrepository = reset($repos);
  | 
        
        
            | 
            | 
           1683 | 
              | 
        
        
            | 
            | 
           1684 | 
                   // Create a user private file.
  | 
        
        
            | 
            | 
           1685 | 
                   $userfilerecord = new stdClass;
  | 
        
        
            | 
            | 
           1686 | 
                   $userfilerecord->contextid = $usercontext->id;
  | 
        
        
            | 
            | 
           1687 | 
                   $userfilerecord->component = 'user';
  | 
        
        
            | 
            | 
           1688 | 
                   $userfilerecord->filearea  = 'private';
  | 
        
        
            | 
            | 
           1689 | 
                   $userfilerecord->itemid    = 0;
  | 
        
        
            | 
            | 
           1690 | 
                   $userfilerecord->filepath  = '/';
  | 
        
        
            | 
            | 
           1691 | 
                   $userfilerecord->filename  = 'userfile.txt';
  | 
        
        
            | 
            | 
           1692 | 
                   $userfilerecord->source    = 'test';
  | 
        
        
            | 
            | 
           1693 | 
                   $userfile = $fs->create_file_from_string($userfilerecord, 'User file content');
  | 
        
        
            | 
            | 
           1694 | 
                   $userfileref = $fs->pack_reference($userfilerecord);
  | 
        
        
            | 
            | 
           1695 | 
              | 
        
        
            | 
            | 
           1696 | 
                   // Clone latest "normal" file.
  | 
        
        
            | 
            | 
           1697 | 
                   $filerefrecord = clone (object) $filerecord;
  | 
        
        
            | 
            | 
           1698 | 
                   $filerefrecord->filename = 'testref.txt';
  | 
        
        
            | 
            | 
           1699 | 
                   $fileref = $fs->create_file_from_reference($filerefrecord, $userrepository->id, $userfileref);
  | 
        
        
            | 
            | 
           1700 | 
                   // Set main file pointing to the file reference.
  | 
        
        
            | 
            | 
           1701 | 
                   file_set_sortorder($usercontext->id, 'user', 'draft', $record->files, $filerefrecord->filepath,
  | 
        
        
            | 
            | 
           1702 | 
                       $filerefrecord->filename, 1);
  | 
        
        
            | 
            | 
           1703 | 
              | 
        
        
            | 
            | 
           1704 | 
                   // Once the reference has been created, create the file resource.
  | 
        
        
            | 
            | 
           1705 | 
                   $resource2 = self::getDataGenerator()->create_module('resource', $record);
  | 
        
        
            | 
            | 
           1706 | 
              | 
        
        
            | 
            | 
           1707 | 
                   $result = core_course_external::get_course_contents($course->id);
  | 
        
        
            | 
            | 
           1708 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $result);
  | 
        
        
            | 
            | 
           1709 | 
                   $this->assertCount(2, $result[0]['modules']);
  | 
        
        
            | 
            | 
           1710 | 
                   foreach ($result[0]['modules'] as $module) {
  | 
        
        
            | 
            | 
           1711 | 
                       if ($module['instance'] == $resource1->id) {
  | 
        
        
            | 
            | 
           1712 | 
                           $this->assertEquals(1, $module['contentsinfo']['filescount']);
  | 
        
        
            | 
            | 
           1713 | 
                           $this->assertGreaterThanOrEqual($timenow, $module['contentsinfo']['lastmodified']);
  | 
        
        
            | 
            | 
           1714 | 
                           $this->assertEquals($module['contents'][0]['filesize'], $module['contentsinfo']['filessize']);
  | 
        
        
            | 
            | 
           1715 | 
                           $this->assertEquals(array('text/plain'), $module['contentsinfo']['mimetypes']);
  | 
        
        
            | 
            | 
           1716 | 
                       } else {
  | 
        
        
            | 
            | 
           1717 | 
                           $this->assertEquals(count($extensions) + 1, $module['contentsinfo']['filescount']);
  | 
        
        
            | 
            | 
           1718 | 
                           $filessize = $module['contents'][0]['filesize'] + $module['contents'][1]['filesize'] +
  | 
        
        
            | 
            | 
           1719 | 
                               $module['contents'][2]['filesize'] + $module['contents'][3]['filesize'];
  | 
        
        
            | 
            | 
           1720 | 
                           $this->assertEquals($filessize, $module['contentsinfo']['filessize']);
  | 
        
        
            | 
            | 
           1721 | 
                           $this->assertEquals('user', $module['contentsinfo']['repositorytype']);
  | 
        
        
            | 
            | 
           1722 | 
                           $this->assertGreaterThanOrEqual($timenow, $module['contentsinfo']['lastmodified']);
  | 
        
        
            | 
            | 
           1723 | 
                           $this->assertEquals(array('text/plain', 'image/png', 'application/pdf'), $module['contentsinfo']['mimetypes']);
  | 
        
        
            | 
            | 
           1724 | 
                       }
  | 
        
        
            | 
            | 
           1725 | 
                   }
  | 
        
        
            | 
            | 
           1726 | 
               }
  | 
        
        
            | 
            | 
           1727 | 
              | 
        
        
            | 
            | 
           1728 | 
               /**
  | 
        
        
            | 
            | 
           1729 | 
                * Test get_course_contents when hidden sections are displayed.
  | 
        
        
            | 
            | 
           1730 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1731 | 
               public function test_get_course_contents_hiddensections(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1732 | 
                   global $DB;
  | 
        
        
            | 
            | 
           1733 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1734 | 
              | 
        
        
            | 
            | 
           1735 | 
                   list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
  | 
        
        
            | 
            | 
           1736 | 
                   // Force returning hidden sections.
  | 
        
        
            | 
            | 
           1737 | 
                   $course->hiddensections = 0;
  | 
        
        
            | 
            | 
           1738 | 
                   update_course($course);
  | 
        
        
            | 
            | 
           1739 | 
              | 
        
        
            | 
            | 
           1740 | 
                   $studentroleid = $DB->get_field('role', 'id', array('shortname' => 'student'));
  | 
        
        
            | 
            | 
           1741 | 
                   $user = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           1742 | 
                   self::getDataGenerator()->enrol_user($user->id, $course->id, $studentroleid);
  | 
        
        
            | 
            | 
           1743 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           1744 | 
              | 
        
        
            | 
            | 
           1745 | 
                   $sections = core_course_external::get_course_contents($course->id, array());
  | 
        
        
            | 
            | 
           1746 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1747 | 
                   $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
  | 
        
        
            | 
            | 
           1748 | 
              | 
        
        
            | 
            | 
           1749 | 
                   $this->assertCount(5, $sections); // All the sections, including the "not visible" one.
  | 
        
        
            | 
            | 
           1750 | 
                   $this->assertCount(6, $sections[0]['modules']);
  | 
        
        
            | 
            | 
           1751 | 
                   $this->assertCount(1, $sections[1]['modules']);
  | 
        
        
            | 
            | 
           1752 | 
                   $this->assertCount(1, $sections[2]['modules']);
  | 
        
        
            | 
            | 
           1753 | 
                   $this->assertCount(0, $sections[3]['modules']); // No modules for the section with availability restrictions.
  | 
        
        
            | 
            | 
           1754 | 
                   $this->assertCount(0, $sections[4]['modules']); // No modules for the section hidden.
  | 
        
        
            | 
            | 
           1755 | 
              | 
        
        
            | 
            | 
           1756 | 
                   $this->assertNotEmpty($sections[3]['availabilityinfo']);
  | 
        
        
            | 
            | 
           1757 | 
                   $this->assertEquals(1, $sections[1]['section']);
  | 
        
        
            | 
            | 
           1758 | 
                   $this->assertEquals(2, $sections[2]['section']);
  | 
        
        
            | 
            | 
           1759 | 
                   $this->assertEquals(3, $sections[3]['section']);
  | 
        
        
            | 
            | 
           1760 | 
                   // The module with the availability restriction met is returning contents.
  | 
        
        
            | 
            | 
           1761 | 
                   $this->assertNotEmpty($sections[1]['modules'][0]['contents']);
  | 
        
        
            | 
            | 
           1762 | 
                   // The module with the availability restriction not met is not returning contents.
  | 
        
        
            | 
            | 
           1763 | 
                   $this->assertArrayNotHasKey('contents', $sections[2]['modules'][0]);
  | 
        
        
            | 
            | 
           1764 | 
              | 
        
        
            | 
            | 
           1765 | 
                   // Now include flag for returning stealth information (fake section).
  | 
        
        
            | 
            | 
           1766 | 
                   $sections = core_course_external::get_course_contents($course->id,
  | 
        
        
            | 
            | 
           1767 | 
                       array(array("name" => "includestealthmodules", "value" => 1)));
  | 
        
        
            | 
            | 
           1768 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1769 | 
                   $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
  | 
        
        
            | 
            | 
           1770 | 
              | 
        
        
            | 
            | 
           1771 | 
                   $this->assertCount(6, $sections); // Include fake section with stealth activities.
  | 
        
        
            | 
            | 
           1772 | 
                   $this->assertCount(6, $sections[0]['modules']);
  | 
        
        
            | 
            | 
           1773 | 
                   $this->assertCount(1, $sections[1]['modules']);
  | 
        
        
            | 
            | 
           1774 | 
                   $this->assertCount(1, $sections[2]['modules']);
  | 
        
        
            | 
            | 
           1775 | 
                   $this->assertCount(0, $sections[3]['modules']); // No modules for the section with availability restrictions.
  | 
        
        
            | 
            | 
           1776 | 
                   $this->assertCount(0, $sections[4]['modules']); // No modules for the section hidden.
  | 
        
        
            | 
            | 
           1777 | 
                   $this->assertCount(1, $sections[5]['modules']); // One stealth module.
  | 
        
        
            | 
            | 
           1778 | 
                   $this->assertEquals(-1, $sections[5]['id']);
  | 
        
        
            | 
            | 
           1779 | 
               }
  | 
        
        
            | 
            | 
           1780 | 
              | 
        
        
            | 
            | 
           1781 | 
               /**
  | 
        
        
            | 
            | 
           1782 | 
                * Test get course contents dates.
  | 
        
        
            | 
            | 
           1783 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1784 | 
               public function test_get_course_contents_dates(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1785 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1786 | 
              | 
        
        
            | 
            | 
           1787 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           1788 | 
                   set_config('enablecourserelativedates', 1);
  | 
        
        
            | 
            | 
           1789 | 
              | 
        
        
            | 
            | 
           1790 | 
                   // Course with just main section.
  | 
        
        
            | 
            | 
           1791 | 
                   $timenow = time();
  | 
        
        
            | 
            | 
           1792 | 
                   $course = self::getDataGenerator()->create_course(
  | 
        
        
            | 
            | 
           1793 | 
                       ['numsections' => 0, 'relativedatesmode' => true, 'startdate' => $timenow - DAYSECS]);
  | 
        
        
            | 
            | 
           1794 | 
              | 
        
        
            | 
            | 
           1795 | 
                   $teacher = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           1796 | 
                   self::getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');
  | 
        
        
            | 
            | 
           1797 | 
              | 
        
        
            | 
            | 
           1798 | 
                   $this->setUser($teacher);
  | 
        
        
            | 
            | 
           1799 | 
              | 
        
        
            | 
            | 
           1800 | 
                   // Create resource (empty dates).
  | 
        
        
            | 
            | 
           1801 | 
                   $resource = self::getDataGenerator()->create_module('resource', ['course' => $course->id]);
  | 
        
        
            | 
            | 
           1802 | 
                   // Create activities with dates.
  | 
        
        
            | 
            | 
           1803 | 
                   $resource = self::getDataGenerator()->create_module('forum', ['course' => $course->id, 'duedate' => $timenow]);
  | 
        
        
            | 
            | 
           1804 | 
                   $resource = self::getDataGenerator()->create_module('choice',
  | 
        
        
            | 
            | 
           1805 | 
                       ['course' => $course->id, 'timeopen' => $timenow, 'timeclose' => $timenow + DAYSECS]);
  | 
        
        
            | 
            | 
           1806 | 
                   $resource = self::getDataGenerator()->create_module('assign',
  | 
        
        
            | 
            | 
           1807 | 
                       ['course' => $course->id, 'allowsubmissionsfromdate' => $timenow]);
  | 
        
        
            | 
            | 
           1808 | 
              | 
        
        
            | 
            | 
           1809 | 
                   $result = core_course_external::get_course_contents($course->id);
  | 
        
        
            | 
            | 
           1810 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $result);
  | 
        
        
            | 
            | 
           1811 | 
              | 
        
        
            | 
            | 
           1812 | 
                   foreach ($result[0]['modules'] as $module) {
  | 
        
        
            | 
            | 
           1813 | 
                       if ($module['modname'] == 'resource') {
  | 
        
        
            | 
            | 
           1814 | 
                           $this->assertEmpty($module['dates']);
  | 
        
        
            | 
            | 
           1815 | 
                       } else if ($module['modname'] == 'forum') {
  | 
        
        
            | 
            | 
           1816 | 
                           $this->assertCount(1, $module['dates']);
  | 
        
        
            | 
            | 
           1817 | 
                           $this->assertEquals('duedate', $module['dates'][0]['dataid']);
  | 
        
        
            | 
            | 
           1818 | 
                           $this->assertEquals($timenow, $module['dates'][0]['timestamp']);
  | 
        
        
            | 
            | 
           1819 | 
                       } else if ($module['modname'] == 'choice') {
  | 
        
        
            | 
            | 
           1820 | 
                           $this->assertCount(2, $module['dates']);
  | 
        
        
            | 
            | 
           1821 | 
                           $this->assertEquals('timeopen', $module['dates'][0]['dataid']);
  | 
        
        
            | 
            | 
           1822 | 
                           $this->assertEquals($timenow, $module['dates'][0]['timestamp']);
  | 
        
        
            | 
            | 
           1823 | 
                           $this->assertEquals('timeclose', $module['dates'][1]['dataid']);
  | 
        
        
            | 
            | 
           1824 | 
                           $this->assertEquals($timenow + DAYSECS, $module['dates'][1]['timestamp']);
  | 
        
        
            | 
            | 
           1825 | 
                       } else if ($module['modname'] == 'assign') {
  | 
        
        
            | 
            | 
           1826 | 
                           $this->assertCount(1, $module['dates']);
  | 
        
        
            | 
            | 
           1827 | 
                           $this->assertEquals('allowsubmissionsfromdate', $module['dates'][0]['dataid']);
  | 
        
        
            | 
            | 
           1828 | 
                           $this->assertEquals($timenow, $module['dates'][0]['timestamp']);
  | 
        
        
            | 
            | 
           1829 | 
                           $this->assertEquals($course->startdate, $module['dates'][0]['relativeto']);
  | 
        
        
            | 
            | 
           1830 | 
                       }
  | 
        
        
            | 
            | 
           1831 | 
                   }
  | 
        
        
            | 
            | 
           1832 | 
               }
  | 
        
        
            | 
            | 
           1833 | 
              | 
        
        
            | 
            | 
           1834 | 
               /**
  | 
        
        
            | 
            | 
           1835 | 
                * Test get_course_contents for courses with invalid course format.
  | 
        
        
            | 
            | 
           1836 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1837 | 
               public function test_get_course_contents_invalid_format(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1838 | 
                   global $DB;
  | 
        
        
            | 
            | 
           1839 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           1840 | 
              | 
        
        
            | 
            | 
           1841 | 
                   list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
  | 
        
        
            | 
            | 
           1842 | 
              | 
        
        
            | 
            | 
           1843 | 
                   $DB->set_field('course', 'format', 'fakeformat', ['id' => $course->id]);
  | 
        
        
            | 
            | 
           1844 | 
              | 
        
        
            | 
            | 
           1845 | 
                   // WS should falback to default course format (topics) and avoid exceptions (but debugging will happen).
  | 
        
        
            | 
            | 
           1846 | 
                   $result = core_course_external::get_course_contents($course->id);
  | 
        
        
            | 
            | 
           1847 | 
                   $this->assertDebuggingCalled();
  | 
        
        
            | 
            | 
           1848 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $result);
  | 
        
        
            | 
            | 
           1849 | 
               }
  | 
        
        
            | 
            | 
           1850 | 
              | 
        
        
            | 
            | 
           1851 | 
               /**
  | 
        
        
            | 
            | 
           1852 | 
                * Test duplicate_course
  | 
        
        
            | 
            | 
           1853 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1854 | 
               public function test_duplicate_course(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1855 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1856 | 
              | 
        
        
            | 
            | 
           1857 | 
                   // Create one course with three modules.
  | 
        
        
            | 
            | 
           1858 | 
                   $course  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           1859 | 
                   $forum = $this->getDataGenerator()->create_module('forum', array('course'=>$course->id));
  | 
        
        
            | 
            | 
           1860 | 
                   $forumcm = get_coursemodule_from_id('forum', $forum->cmid);
  | 
        
        
            | 
            | 
           1861 | 
                   $forumcontext = context_module::instance($forum->cmid);
  | 
        
        
            | 
            | 
           1862 | 
                   $data = $this->getDataGenerator()->create_module('data', array('assessed'=>1, 'scale'=>100, 'course'=>$course->id));
  | 
        
        
            | 
            | 
           1863 | 
                   $datacontext = context_module::instance($data->cmid);
  | 
        
        
            | 
            | 
           1864 | 
                   $datacm = get_coursemodule_from_instance('page', $data->id);
  | 
        
        
            | 
            | 
           1865 | 
                   $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
  | 
        
        
            | 
            | 
           1866 | 
                   $pagecontext = context_module::instance($page->cmid);
  | 
        
        
            | 
            | 
           1867 | 
                   $pagecm = get_coursemodule_from_instance('page', $page->id);
  | 
        
        
            | 
            | 
           1868 | 
              | 
        
        
            | 
            | 
           1869 | 
                   // Set the required capabilities by the external function.
  | 
        
        
            | 
            | 
           1870 | 
                   $coursecontext = context_course::instance($course->id);
  | 
        
        
            | 
            | 
           1871 | 
                   $categorycontext = context_coursecat::instance($course->category);
  | 
        
        
            | 
            | 
           1872 | 
                   $roleid = $this->assignUserCapability('moodle/course:create', $categorycontext->id);
  | 
        
        
            | 
            | 
           1873 | 
                   $this->assignUserCapability('moodle/course:view', $categorycontext->id, $roleid);
  | 
        
        
            | 
            | 
           1874 | 
                   $this->assignUserCapability('moodle/restore:restorecourse', $categorycontext->id, $roleid);
  | 
        
        
            | 
            | 
           1875 | 
                   $this->assignUserCapability('moodle/backup:backupcourse', $coursecontext->id, $roleid);
  | 
        
        
            | 
            | 
           1876 | 
                   $this->assignUserCapability('moodle/backup:configure', $coursecontext->id, $roleid);
  | 
        
        
            | 
            | 
           1877 | 
                   // Optional capabilities to copy user data.
  | 
        
        
            | 
            | 
           1878 | 
                   $this->assignUserCapability('moodle/backup:userinfo', $coursecontext->id, $roleid);
  | 
        
        
            | 
            | 
           1879 | 
                   $this->assignUserCapability('moodle/restore:userinfo', $categorycontext->id, $roleid);
  | 
        
        
            | 
            | 
           1880 | 
              | 
        
        
            | 
            | 
           1881 | 
                   $newcourse['fullname'] = 'Course duplicate';
  | 
        
        
            | 
            | 
           1882 | 
                   $newcourse['shortname'] = 'courseduplicate';
  | 
        
        
            | 
            | 
           1883 | 
                   $newcourse['categoryid'] = $course->category;
  | 
        
        
            | 
            | 
           1884 | 
                   $newcourse['visible'] = true;
  | 
        
        
            | 
            | 
           1885 | 
                   $newcourse['options'][] = array('name' => 'users', 'value' => true);
  | 
        
        
            | 
            | 
           1886 | 
              | 
        
        
            | 
            | 
           1887 | 
                   $duplicate = core_course_external::duplicate_course($course->id, $newcourse['fullname'],
  | 
        
        
            | 
            | 
           1888 | 
                           $newcourse['shortname'], $newcourse['categoryid'], $newcourse['visible'], $newcourse['options']);
  | 
        
        
            | 
            | 
           1889 | 
              | 
        
        
            | 
            | 
           1890 | 
                   // We need to execute the return values cleaning process to simulate the web service server.
  | 
        
        
            | 
            | 
           1891 | 
                   $duplicate = external_api::clean_returnvalue(core_course_external::duplicate_course_returns(), $duplicate);
  | 
        
        
            | 
            | 
           1892 | 
              | 
        
        
            | 
            | 
           1893 | 
                   // Check that the course has been duplicated.
  | 
        
        
            | 
            | 
           1894 | 
                   $this->assertEquals($newcourse['shortname'], $duplicate['shortname']);
  | 
        
        
            | 
            | 
           1895 | 
               }
  | 
        
        
            | 
            | 
           1896 | 
              | 
        
        
            | 
            | 
           1897 | 
               /**
  | 
        
        
            | 
            | 
           1898 | 
                * Test update_courses
  | 
        
        
            | 
            | 
           1899 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           1900 | 
               public function test_update_courses(): void {
  | 
        
        
           | 1 | 
           efrain | 
           1901 | 
                   global $DB, $CFG, $USER, $COURSE;
  | 
        
        
            | 
            | 
           1902 | 
              | 
        
        
            | 
            | 
           1903 | 
                   // Get current $COURSE to be able to restore it later (defaults to $SITE). We need this
  | 
        
        
            | 
            | 
           1904 | 
                   // trick because we are both updating and getting (for testing) course information
  | 
        
        
            | 
            | 
           1905 | 
                   // in the same request and core_course_external::update_courses()
  | 
        
        
            | 
            | 
           1906 | 
                   // is overwriting $COURSE all over the time with OLD values, so later
  | 
        
        
            | 
            | 
           1907 | 
                   // use of get_course() fetches those OLD values instead of the updated ones.
  | 
        
        
            | 
            | 
           1908 | 
                   // See MDL-39723 for more info.
  | 
        
        
            | 
            | 
           1909 | 
                   $origcourse = clone($COURSE);
  | 
        
        
            | 
            | 
           1910 | 
              | 
        
        
            | 
            | 
           1911 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           1912 | 
              | 
        
        
            | 
            | 
           1913 | 
                   // Set the required capabilities by the external function.
  | 
        
        
            | 
            | 
           1914 | 
                   $contextid = context_system::instance()->id;
  | 
        
        
            | 
            | 
           1915 | 
                   $roleid = $this->assignUserCapability('moodle/course:update', $contextid);
  | 
        
        
            | 
            | 
           1916 | 
                   $this->assignUserCapability('moodle/course:changecategory', $contextid, $roleid);
  | 
        
        
            | 
            | 
           1917 | 
                   $this->assignUserCapability('moodle/course:changelockedcustomfields', $contextid, $roleid);
  | 
        
        
            | 
            | 
           1918 | 
                   $this->assignUserCapability('moodle/course:changefullname', $contextid, $roleid);
  | 
        
        
            | 
            | 
           1919 | 
                   $this->assignUserCapability('moodle/course:changeshortname', $contextid, $roleid);
  | 
        
        
            | 
            | 
           1920 | 
                   $this->assignUserCapability('moodle/course:changeidnumber', $contextid, $roleid);
  | 
        
        
            | 
            | 
           1921 | 
                   $this->assignUserCapability('moodle/course:changesummary', $contextid, $roleid);
  | 
        
        
            | 
            | 
           1922 | 
                   $this->assignUserCapability('moodle/course:visibility', $contextid, $roleid);
  | 
        
        
            | 
            | 
           1923 | 
                   $this->assignUserCapability('moodle/course:viewhiddencourses', $contextid, $roleid);
  | 
        
        
            | 
            | 
           1924 | 
                   $this->assignUserCapability('moodle/course:setforcedlanguage', $contextid, $roleid);
  | 
        
        
            | 
            | 
           1925 | 
              | 
        
        
            | 
            | 
           1926 | 
                   // Create category and courses.
  | 
        
        
            | 
            | 
           1927 | 
                   $category1  = self::getDataGenerator()->create_category();
  | 
        
        
            | 
            | 
           1928 | 
                   $category2  = self::getDataGenerator()->create_category();
  | 
        
        
            | 
            | 
           1929 | 
              | 
        
        
            | 
            | 
           1930 | 
                   $originalcourse1 = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           1931 | 
                   self::getDataGenerator()->enrol_user($USER->id, $originalcourse1->id, $roleid);
  | 
        
        
            | 
            | 
           1932 | 
              | 
        
        
            | 
            | 
           1933 | 
                   $originalcourse2 = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           1934 | 
                   self::getDataGenerator()->enrol_user($USER->id, $originalcourse2->id, $roleid);
  | 
        
        
            | 
            | 
           1935 | 
              | 
        
        
            | 
            | 
           1936 | 
                   // Course with custom fields.
  | 
        
        
            | 
            | 
           1937 | 
                   $fieldcategory = self::getDataGenerator()->create_custom_field_category(['name' => 'Other fields']);
  | 
        
        
            | 
            | 
           1938 | 
              | 
        
        
            | 
            | 
           1939 | 
                   $fieldtext = self::getDataGenerator()->create_custom_field([
  | 
        
        
            | 
            | 
           1940 | 
                       'categoryid' => $fieldcategory->get('id'), 'name' => 'Text', 'shortname' => 'text', 'type' => 'text', 'configdata' => [
  | 
        
        
            | 
            | 
           1941 | 
                           'locked' => 1,
  | 
        
        
            | 
            | 
           1942 | 
                       ],
  | 
        
        
            | 
            | 
           1943 | 
                   ]);
  | 
        
        
            | 
            | 
           1944 | 
                   $fieldtextarea = self::getDataGenerator()->create_custom_field([
  | 
        
        
            | 
            | 
           1945 | 
                       'categoryid' => $fieldcategory->get('id'), 'name' => 'Textarea', 'shortname' => 'textarea', 'type' => 'textarea',
  | 
        
        
            | 
            | 
           1946 | 
                   ]);
  | 
        
        
            | 
            | 
           1947 | 
              | 
        
        
            | 
            | 
           1948 | 
                   $originalcourse3 = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           1949 | 
                   self::getDataGenerator()->enrol_user($USER->id, $originalcourse3->id, $roleid);
  | 
        
        
            | 
            | 
           1950 | 
              | 
        
        
            | 
            | 
           1951 | 
                   // Course values to be updated.
  | 
        
        
            | 
            | 
           1952 | 
                   $course1['id'] = $originalcourse1->id;
  | 
        
        
            | 
            | 
           1953 | 
                   $course1['fullname'] = 'Updated test course 1';
  | 
        
        
            | 
            | 
           1954 | 
                   $course1['shortname'] = 'Udestedtestcourse1';
  | 
        
        
            | 
            | 
           1955 | 
                   $course1['categoryid'] = $category1->id;
  | 
        
        
            | 
            | 
           1956 | 
              | 
        
        
            | 
            | 
           1957 | 
                   $course2['id'] = $originalcourse2->id;
  | 
        
        
            | 
            | 
           1958 | 
                   $course2['fullname'] = 'Updated test course 2';
  | 
        
        
            | 
            | 
           1959 | 
                   $course2['shortname'] = 'Updestedtestcourse2';
  | 
        
        
            | 
            | 
           1960 | 
                   $course2['categoryid'] = $category2->id;
  | 
        
        
            | 
            | 
           1961 | 
                   $course2['idnumber'] = 'Updatedidnumber2';
  | 
        
        
            | 
            | 
           1962 | 
                   $course2['summary'] = 'Updaated description for course 2';
  | 
        
        
            | 
            | 
           1963 | 
                   $course2['summaryformat'] = FORMAT_HTML;
  | 
        
        
            | 
            | 
           1964 | 
                   $course2['format'] = 'topics';
  | 
        
        
            | 
            | 
           1965 | 
                   $course2['showgrades'] = 1;
  | 
        
        
            | 
            | 
           1966 | 
                   $course2['newsitems'] = 3;
  | 
        
        
            | 
            | 
           1967 | 
                   $course2['startdate'] = 1420092000; // 01/01/2015.
  | 
        
        
            | 
            | 
           1968 | 
                   $course2['enddate'] = 1422669600; // 01/31/2015.
  | 
        
        
            | 
            | 
           1969 | 
                   $course2['maxbytes'] = 100000;
  | 
        
        
            | 
            | 
           1970 | 
                   $course2['showreports'] = 1;
  | 
        
        
            | 
            | 
           1971 | 
                   $course2['visible'] = 0;
  | 
        
        
            | 
            | 
           1972 | 
                   $course2['hiddensections'] = 0;
  | 
        
        
            | 
            | 
           1973 | 
                   $course2['groupmode'] = 0;
  | 
        
        
            | 
            | 
           1974 | 
                   $course2['groupmodeforce'] = 0;
  | 
        
        
            | 
            | 
           1975 | 
                   $course2['defaultgroupingid'] = 0;
  | 
        
        
            | 
            | 
           1976 | 
                   $course2['enablecompletion'] = 1;
  | 
        
        
            | 
            | 
           1977 | 
                   $course2['lang'] = 'en';
  | 
        
        
            | 
            | 
           1978 | 
                   $course2['forcetheme'] = 'classic';
  | 
        
        
            | 
            | 
           1979 | 
              | 
        
        
            | 
            | 
           1980 | 
                   $course3['id'] = $originalcourse3->id;
  | 
        
        
            | 
            | 
           1981 | 
                   $course3['customfields'] = [
  | 
        
        
            | 
            | 
           1982 | 
                       ['shortname' => $fieldtext->get('shortname'), 'value' => 'I long to see the sunlight in your hair'],
  | 
        
        
            | 
            | 
           1983 | 
                       ['shortname' => $fieldtextarea->get('shortname'), 'value' => 'And tell you time and time again'],
  | 
        
        
            | 
            | 
           1984 | 
                    ];
  | 
        
        
            | 
            | 
           1985 | 
              | 
        
        
            | 
            | 
           1986 | 
                   $courses = array($course1, $course2, $course3);
  | 
        
        
            | 
            | 
           1987 | 
              | 
        
        
            | 
            | 
           1988 | 
                   $updatedcoursewarnings = core_course_external::update_courses($courses);
  | 
        
        
            | 
            | 
           1989 | 
                   $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(),
  | 
        
        
            | 
            | 
           1990 | 
                           $updatedcoursewarnings);
  | 
        
        
            | 
            | 
           1991 | 
                   $COURSE = $origcourse; // Restore $COURSE. Instead of using the OLD one set by the previous line.
  | 
        
        
            | 
            | 
           1992 | 
              | 
        
        
            | 
            | 
           1993 | 
                   // Check that right number of courses were created.
  | 
        
        
            | 
            | 
           1994 | 
                   $this->assertEquals(0, count($updatedcoursewarnings['warnings']));
  | 
        
        
            | 
            | 
           1995 | 
              | 
        
        
            | 
            | 
           1996 | 
                   // Check that the courses were correctly created.
  | 
        
        
            | 
            | 
           1997 | 
                   foreach ($courses as $course) {
  | 
        
        
            | 
            | 
           1998 | 
                       $courseinfo = course_get_format($course['id'])->get_course();
  | 
        
        
            | 
            | 
           1999 | 
                       $customfields = \core_course\customfield\course_handler::create()->export_instance_data_object($course['id']);
  | 
        
        
            | 
            | 
           2000 | 
                       if ($course['id'] == $course2['id']) {
  | 
        
        
            | 
            | 
           2001 | 
                           $this->assertEquals($course2['fullname'], $courseinfo->fullname);
  | 
        
        
            | 
            | 
           2002 | 
                           $this->assertEquals($course2['shortname'], $courseinfo->shortname);
  | 
        
        
            | 
            | 
           2003 | 
                           $this->assertEquals($course2['categoryid'], $courseinfo->category);
  | 
        
        
            | 
            | 
           2004 | 
                           $this->assertEquals($course2['idnumber'], $courseinfo->idnumber);
  | 
        
        
            | 
            | 
           2005 | 
                           $this->assertEquals($course2['summary'], $courseinfo->summary);
  | 
        
        
            | 
            | 
           2006 | 
                           $this->assertEquals($course2['summaryformat'], $courseinfo->summaryformat);
  | 
        
        
            | 
            | 
           2007 | 
                           $this->assertEquals($course2['format'], $courseinfo->format);
  | 
        
        
            | 
            | 
           2008 | 
                           $this->assertEquals($course2['showgrades'], $courseinfo->showgrades);
  | 
        
        
            | 
            | 
           2009 | 
                           $this->assertEquals($course2['newsitems'], $courseinfo->newsitems);
  | 
        
        
            | 
            | 
           2010 | 
                           $this->assertEquals($course2['startdate'], $courseinfo->startdate);
  | 
        
        
            | 
            | 
           2011 | 
                           $this->assertEquals($course2['enddate'], $courseinfo->enddate);
  | 
        
        
            | 
            | 
           2012 | 
                           $this->assertEquals($course2['maxbytes'], $courseinfo->maxbytes);
  | 
        
        
            | 
            | 
           2013 | 
                           $this->assertEquals($course2['showreports'], $courseinfo->showreports);
  | 
        
        
            | 
            | 
           2014 | 
                           $this->assertEquals($course2['visible'], $courseinfo->visible);
  | 
        
        
            | 
            | 
           2015 | 
                           $this->assertEquals($course2['hiddensections'], $courseinfo->hiddensections);
  | 
        
        
            | 
            | 
           2016 | 
                           $this->assertEquals($course2['groupmode'], $courseinfo->groupmode);
  | 
        
        
            | 
            | 
           2017 | 
                           $this->assertEquals($course2['groupmodeforce'], $courseinfo->groupmodeforce);
  | 
        
        
            | 
            | 
           2018 | 
                           $this->assertEquals($course2['defaultgroupingid'], $courseinfo->defaultgroupingid);
  | 
        
        
            | 
            | 
           2019 | 
                           $this->assertEquals($course2['lang'], $courseinfo->lang);
  | 
        
        
            | 
            | 
           2020 | 
              | 
        
        
            | 
            | 
           2021 | 
                           if (!empty($CFG->allowcoursethemes)) {
  | 
        
        
            | 
            | 
           2022 | 
                               $this->assertEquals($course2['forcetheme'], $courseinfo->theme);
  | 
        
        
            | 
            | 
           2023 | 
                           }
  | 
        
        
            | 
            | 
           2024 | 
              | 
        
        
            | 
            | 
           2025 | 
                           $this->assertEquals($course2['enablecompletion'], $courseinfo->enablecompletion);
  | 
        
        
            | 
            | 
           2026 | 
                           $this->assertEquals((object) [
  | 
        
        
            | 
            | 
           2027 | 
                               'text' => null,
  | 
        
        
            | 
            | 
           2028 | 
                               'textarea' => null,
  | 
        
        
            | 
            | 
           2029 | 
                           ], $customfields);
  | 
        
        
            | 
            | 
           2030 | 
                       } else if ($course['id'] == $course1['id']) {
  | 
        
        
            | 
            | 
           2031 | 
                           $this->assertEquals($course1['fullname'], $courseinfo->fullname);
  | 
        
        
            | 
            | 
           2032 | 
                           $this->assertEquals($course1['shortname'], $courseinfo->shortname);
  | 
        
        
            | 
            | 
           2033 | 
                           $this->assertEquals($course1['categoryid'], $courseinfo->category);
  | 
        
        
            | 
            | 
           2034 | 
                           $this->assertEquals(FORMAT_MOODLE, $courseinfo->summaryformat);
  | 
        
        
            | 
            | 
           2035 | 
                           $this->assertEquals('topics', $courseinfo->format);
  | 
        
        
            | 
            | 
           2036 | 
                           $this->assertEquals(5, course_get_format($course['id'])->get_last_section_number());
  | 
        
        
            | 
            | 
           2037 | 
                           $this->assertEquals(0, $courseinfo->newsitems);
  | 
        
        
            | 
            | 
           2038 | 
                           $this->assertEquals(FORMAT_MOODLE, $courseinfo->summaryformat);
  | 
        
        
            | 
            | 
           2039 | 
                           $this->assertEquals((object) [
  | 
        
        
            | 
            | 
           2040 | 
                               'text' => null,
  | 
        
        
            | 
            | 
           2041 | 
                               'textarea' => null,
  | 
        
        
            | 
            | 
           2042 | 
                           ], $customfields);
  | 
        
        
            | 
            | 
           2043 | 
                       } else if ($course['id'] == $course3['id']) {
  | 
        
        
            | 
            | 
           2044 | 
                           $this->assertEquals((object) [
  | 
        
        
            | 
            | 
           2045 | 
                               'text' => 'I long to see the sunlight in your hair',
  | 
        
        
            | 
            | 
           2046 | 
                               'textarea' => '<div class="text_to_html">And tell you time and time again</div>',
  | 
        
        
            | 
            | 
           2047 | 
                           ], $customfields);
  | 
        
        
            | 
            | 
           2048 | 
                       } else {
  | 
        
        
            | 
            | 
           2049 | 
                           throw new moodle_exception('Unexpected shortname');
  | 
        
        
            | 
            | 
           2050 | 
                       }
  | 
        
        
            | 
            | 
           2051 | 
                   }
  | 
        
        
            | 
            | 
           2052 | 
              | 
        
        
            | 
            | 
           2053 | 
                   $courses = array($course1);
  | 
        
        
            | 
            | 
           2054 | 
                   // Try update course without update capability.
  | 
        
        
            | 
            | 
           2055 | 
                   $user = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2056 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           2057 | 
                   $this->unassignUserCapability('moodle/course:update', $contextid, $roleid);
  | 
        
        
            | 
            | 
           2058 | 
                   self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid);
  | 
        
        
            | 
            | 
           2059 | 
                   $updatedcoursewarnings = core_course_external::update_courses($courses);
  | 
        
        
            | 
            | 
           2060 | 
                   $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(),
  | 
        
        
            | 
            | 
           2061 | 
                                                                               $updatedcoursewarnings);
  | 
        
        
            | 
            | 
           2062 | 
                   $this->assertEquals(1, count($updatedcoursewarnings['warnings']));
  | 
        
        
            | 
            | 
           2063 | 
              | 
        
        
            | 
            | 
           2064 | 
                   // Try update course category without capability.
  | 
        
        
            | 
            | 
           2065 | 
                   $this->assignUserCapability('moodle/course:update', $contextid, $roleid);
  | 
        
        
            | 
            | 
           2066 | 
                   $this->unassignUserCapability('moodle/course:changecategory', $contextid, $roleid);
  | 
        
        
            | 
            | 
           2067 | 
                   $user = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2068 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           2069 | 
                   self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid);
  | 
        
        
            | 
            | 
           2070 | 
                   $course1['categoryid'] = $category2->id;
  | 
        
        
            | 
            | 
           2071 | 
                   $courses = array($course1);
  | 
        
        
            | 
            | 
           2072 | 
                   $updatedcoursewarnings = core_course_external::update_courses($courses);
  | 
        
        
            | 
            | 
           2073 | 
                   $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(),
  | 
        
        
            | 
            | 
           2074 | 
                                                                               $updatedcoursewarnings);
  | 
        
        
            | 
            | 
           2075 | 
                   $this->assertEquals(1, count($updatedcoursewarnings['warnings']));
  | 
        
        
            | 
            | 
           2076 | 
              | 
        
        
            | 
            | 
           2077 | 
                   // Try update course fullname without capability.
  | 
        
        
            | 
            | 
           2078 | 
                   $this->assignUserCapability('moodle/course:changecategory', $contextid, $roleid);
  | 
        
        
            | 
            | 
           2079 | 
                   $this->unassignUserCapability('moodle/course:changefullname', $contextid, $roleid);
  | 
        
        
            | 
            | 
           2080 | 
                   $user = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2081 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           2082 | 
                   self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid);
  | 
        
        
            | 
            | 
           2083 | 
                   $updatedcoursewarnings = core_course_external::update_courses($courses);
  | 
        
        
            | 
            | 
           2084 | 
                   $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(),
  | 
        
        
            | 
            | 
           2085 | 
                                                                               $updatedcoursewarnings);
  | 
        
        
            | 
            | 
           2086 | 
                   $this->assertEquals(0, count($updatedcoursewarnings['warnings']));
  | 
        
        
            | 
            | 
           2087 | 
                   $course1['fullname'] = 'Testing fullname without permission';
  | 
        
        
            | 
            | 
           2088 | 
                   $courses = array($course1);
  | 
        
        
            | 
            | 
           2089 | 
                   $updatedcoursewarnings = core_course_external::update_courses($courses);
  | 
        
        
            | 
            | 
           2090 | 
                   $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(),
  | 
        
        
            | 
            | 
           2091 | 
                                                                               $updatedcoursewarnings);
  | 
        
        
            | 
            | 
           2092 | 
                   $this->assertEquals(1, count($updatedcoursewarnings['warnings']));
  | 
        
        
            | 
            | 
           2093 | 
              | 
        
        
            | 
            | 
           2094 | 
                   // Try update course shortname without capability.
  | 
        
        
            | 
            | 
           2095 | 
                   $this->assignUserCapability('moodle/course:changefullname', $contextid, $roleid);
  | 
        
        
            | 
            | 
           2096 | 
                   $this->unassignUserCapability('moodle/course:changeshortname', $contextid, $roleid);
  | 
        
        
            | 
            | 
           2097 | 
                   $user = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2098 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           2099 | 
                   self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid);
  | 
        
        
            | 
            | 
           2100 | 
                   $updatedcoursewarnings = core_course_external::update_courses($courses);
  | 
        
        
            | 
            | 
           2101 | 
                   $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(),
  | 
        
        
            | 
            | 
           2102 | 
                                                                               $updatedcoursewarnings);
  | 
        
        
            | 
            | 
           2103 | 
                   $this->assertEquals(0, count($updatedcoursewarnings['warnings']));
  | 
        
        
            | 
            | 
           2104 | 
                   $course1['shortname'] = 'Testing shortname without permission';
  | 
        
        
            | 
            | 
           2105 | 
                   $courses = array($course1);
  | 
        
        
            | 
            | 
           2106 | 
                   $updatedcoursewarnings = core_course_external::update_courses($courses);
  | 
        
        
            | 
            | 
           2107 | 
                   $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(),
  | 
        
        
            | 
            | 
           2108 | 
                                                                               $updatedcoursewarnings);
  | 
        
        
            | 
            | 
           2109 | 
                   $this->assertEquals(1, count($updatedcoursewarnings['warnings']));
  | 
        
        
            | 
            | 
           2110 | 
              | 
        
        
            | 
            | 
           2111 | 
                   // Try update course idnumber without capability.
  | 
        
        
            | 
            | 
           2112 | 
                   $this->assignUserCapability('moodle/course:changeshortname', $contextid, $roleid);
  | 
        
        
            | 
            | 
           2113 | 
                   $this->unassignUserCapability('moodle/course:changeidnumber', $contextid, $roleid);
  | 
        
        
            | 
            | 
           2114 | 
                   $user = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2115 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           2116 | 
                   self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid);
  | 
        
        
            | 
            | 
           2117 | 
                   $updatedcoursewarnings = core_course_external::update_courses($courses);
  | 
        
        
            | 
            | 
           2118 | 
                   $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(),
  | 
        
        
            | 
            | 
           2119 | 
                                                                               $updatedcoursewarnings);
  | 
        
        
            | 
            | 
           2120 | 
                   $this->assertEquals(0, count($updatedcoursewarnings['warnings']));
  | 
        
        
            | 
            | 
           2121 | 
                   $course1['idnumber'] = 'NEWIDNUMBER';
  | 
        
        
            | 
            | 
           2122 | 
                   $courses = array($course1);
  | 
        
        
            | 
            | 
           2123 | 
                   $updatedcoursewarnings = core_course_external::update_courses($courses);
  | 
        
        
            | 
            | 
           2124 | 
                   $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(),
  | 
        
        
            | 
            | 
           2125 | 
                                                                               $updatedcoursewarnings);
  | 
        
        
            | 
            | 
           2126 | 
                   $this->assertEquals(1, count($updatedcoursewarnings['warnings']));
  | 
        
        
            | 
            | 
           2127 | 
              | 
        
        
            | 
            | 
           2128 | 
                   // Try update course summary without capability.
  | 
        
        
            | 
            | 
           2129 | 
                   $this->assignUserCapability('moodle/course:changeidnumber', $contextid, $roleid);
  | 
        
        
            | 
            | 
           2130 | 
                   $this->unassignUserCapability('moodle/course:changesummary', $contextid, $roleid);
  | 
        
        
            | 
            | 
           2131 | 
                   $user = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2132 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           2133 | 
                   self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid);
  | 
        
        
            | 
            | 
           2134 | 
                   $updatedcoursewarnings = core_course_external::update_courses($courses);
  | 
        
        
            | 
            | 
           2135 | 
                   $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(),
  | 
        
        
            | 
            | 
           2136 | 
                                                                               $updatedcoursewarnings);
  | 
        
        
            | 
            | 
           2137 | 
                   $this->assertEquals(0, count($updatedcoursewarnings['warnings']));
  | 
        
        
            | 
            | 
           2138 | 
                   $course1['summary'] = 'New summary';
  | 
        
        
            | 
            | 
           2139 | 
                   $courses = array($course1);
  | 
        
        
            | 
            | 
           2140 | 
                   $updatedcoursewarnings = core_course_external::update_courses($courses);
  | 
        
        
            | 
            | 
           2141 | 
                   $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(),
  | 
        
        
            | 
            | 
           2142 | 
                                                                               $updatedcoursewarnings);
  | 
        
        
            | 
            | 
           2143 | 
                   $this->assertEquals(1, count($updatedcoursewarnings['warnings']));
  | 
        
        
            | 
            | 
           2144 | 
              | 
        
        
            | 
            | 
           2145 | 
                   // Try update course with invalid summary format.
  | 
        
        
            | 
            | 
           2146 | 
                   $this->assignUserCapability('moodle/course:changesummary', $contextid, $roleid);
  | 
        
        
            | 
            | 
           2147 | 
                   $user = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2148 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           2149 | 
                   self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid);
  | 
        
        
            | 
            | 
           2150 | 
                   $updatedcoursewarnings = core_course_external::update_courses($courses);
  | 
        
        
            | 
            | 
           2151 | 
                   $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(),
  | 
        
        
            | 
            | 
           2152 | 
                                                                               $updatedcoursewarnings);
  | 
        
        
            | 
            | 
           2153 | 
                   $this->assertEquals(0, count($updatedcoursewarnings['warnings']));
  | 
        
        
            | 
            | 
           2154 | 
                   $course1['summaryformat'] = 10;
  | 
        
        
            | 
            | 
           2155 | 
                   $courses = array($course1);
  | 
        
        
            | 
            | 
           2156 | 
                   $updatedcoursewarnings = core_course_external::update_courses($courses);
  | 
        
        
            | 
            | 
           2157 | 
                   $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(),
  | 
        
        
            | 
            | 
           2158 | 
                                                                               $updatedcoursewarnings);
  | 
        
        
            | 
            | 
           2159 | 
                   $this->assertEquals(1, count($updatedcoursewarnings['warnings']));
  | 
        
        
            | 
            | 
           2160 | 
              | 
        
        
            | 
            | 
           2161 | 
                   // Try update course visibility without capability.
  | 
        
        
            | 
            | 
           2162 | 
                   $this->unassignUserCapability('moodle/course:visibility', $contextid, $roleid);
  | 
        
        
            | 
            | 
           2163 | 
                   $user = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2164 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           2165 | 
                   self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid);
  | 
        
        
            | 
            | 
           2166 | 
                   $course1['summaryformat'] = FORMAT_MOODLE;
  | 
        
        
            | 
            | 
           2167 | 
                   $courses = array($course1);
  | 
        
        
            | 
            | 
           2168 | 
                   $updatedcoursewarnings = core_course_external::update_courses($courses);
  | 
        
        
            | 
            | 
           2169 | 
                   $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(),
  | 
        
        
            | 
            | 
           2170 | 
                                                                               $updatedcoursewarnings);
  | 
        
        
            | 
            | 
           2171 | 
                   $this->assertEquals(0, count($updatedcoursewarnings['warnings']));
  | 
        
        
            | 
            | 
           2172 | 
                   $course1['visible'] = 0;
  | 
        
        
            | 
            | 
           2173 | 
                   $courses = array($course1);
  | 
        
        
            | 
            | 
           2174 | 
                   $updatedcoursewarnings = core_course_external::update_courses($courses);
  | 
        
        
            | 
            | 
           2175 | 
                   $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(),
  | 
        
        
            | 
            | 
           2176 | 
                                                                               $updatedcoursewarnings);
  | 
        
        
            | 
            | 
           2177 | 
                   $this->assertEquals(1, count($updatedcoursewarnings['warnings']));
  | 
        
        
            | 
            | 
           2178 | 
              | 
        
        
            | 
            | 
           2179 | 
                   // Try update course custom fields without capability.
  | 
        
        
            | 
            | 
           2180 | 
                   $this->unassignUserCapability('moodle/course:changelockedcustomfields', $contextid, $roleid);
  | 
        
        
            | 
            | 
           2181 | 
                   $user = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2182 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           2183 | 
                   self::getDataGenerator()->enrol_user($user->id, $course3['id'], $roleid);
  | 
        
        
            | 
            | 
           2184 | 
              | 
        
        
            | 
            | 
           2185 | 
                   $course3['customfields'] = [
  | 
        
        
            | 
            | 
           2186 | 
                       ['shortname' => 'text', 'value' => 'New updated value'],
  | 
        
        
            | 
            | 
           2187 | 
                   ];
  | 
        
        
            | 
            | 
           2188 | 
              | 
        
        
            | 
            | 
           2189 | 
                   core_course_external::update_courses([$course3]);
  | 
        
        
            | 
            | 
           2190 | 
              | 
        
        
            | 
            | 
           2191 | 
                   // Custom field was not updated.
  | 
        
        
            | 
            | 
           2192 | 
                   $customfields = \core_course\customfield\course_handler::create()->export_instance_data_object($course3['id']);
  | 
        
        
            | 
            | 
           2193 | 
                   $this->assertEquals((object) [
  | 
        
        
            | 
            | 
           2194 | 
                       'text' => 'I long to see the sunlight in your hair',
  | 
        
        
            | 
            | 
           2195 | 
                       'textarea' => '<div class="text_to_html">And tell you time and time again</div>',
  | 
        
        
            | 
            | 
           2196 | 
                   ], $customfields);
  | 
        
        
            | 
            | 
           2197 | 
               }
  | 
        
        
            | 
            | 
           2198 | 
              | 
        
        
            | 
            | 
           2199 | 
               /**
  | 
        
        
            | 
            | 
           2200 | 
                * Test delete course_module.
  | 
        
        
            | 
            | 
           2201 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           2202 | 
               public function test_delete_modules(): void {
  | 
        
        
           | 1 | 
           efrain | 
           2203 | 
                   global $DB;
  | 
        
        
            | 
            | 
           2204 | 
              | 
        
        
            | 
            | 
           2205 | 
                   // Ensure we reset the data after this test.
  | 
        
        
            | 
            | 
           2206 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           2207 | 
              | 
        
        
            | 
            | 
           2208 | 
                   // Create a user.
  | 
        
        
            | 
            | 
           2209 | 
                   $user = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2210 | 
              | 
        
        
            | 
            | 
           2211 | 
                   // Set the tests to run as the user.
  | 
        
        
            | 
            | 
           2212 | 
                   self::setUser($user);
  | 
        
        
            | 
            | 
           2213 | 
              | 
        
        
            | 
            | 
           2214 | 
                   // Create a course to add the modules.
  | 
        
        
            | 
            | 
           2215 | 
                   $course = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2216 | 
              | 
        
        
            | 
            | 
           2217 | 
                   // Create two test modules.
  | 
        
        
            | 
            | 
           2218 | 
                   $record = new stdClass();
  | 
        
        
            | 
            | 
           2219 | 
                   $record->course = $course->id;
  | 
        
        
            | 
            | 
           2220 | 
                   $module1 = self::getDataGenerator()->create_module('forum', $record);
  | 
        
        
            | 
            | 
           2221 | 
                   $module2 = self::getDataGenerator()->create_module('assign', $record);
  | 
        
        
            | 
            | 
           2222 | 
              | 
        
        
            | 
            | 
           2223 | 
                   // Check the forum was correctly created.
  | 
        
        
            | 
            | 
           2224 | 
                   $this->assertEquals(1, $DB->count_records('forum', array('id' => $module1->id)));
  | 
        
        
            | 
            | 
           2225 | 
              | 
        
        
            | 
            | 
           2226 | 
                   // Check the assignment was correctly created.
  | 
        
        
            | 
            | 
           2227 | 
                   $this->assertEquals(1, $DB->count_records('assign', array('id' => $module2->id)));
  | 
        
        
            | 
            | 
           2228 | 
              | 
        
        
            | 
            | 
           2229 | 
                   // Check data exists in the course modules table.
  | 
        
        
            | 
            | 
           2230 | 
                   $this->assertEquals(2, $DB->count_records_select('course_modules', 'id = :module1 OR id = :module2',
  | 
        
        
            | 
            | 
           2231 | 
                           array('module1' => $module1->cmid, 'module2' => $module2->cmid)));
  | 
        
        
            | 
            | 
           2232 | 
              | 
        
        
            | 
            | 
           2233 | 
                   // Enrol the user in the course.
  | 
        
        
            | 
            | 
           2234 | 
                   $enrol = enrol_get_plugin('manual');
  | 
        
        
            | 
            | 
           2235 | 
                   $enrolinstances = enrol_get_instances($course->id, true);
  | 
        
        
            | 
            | 
           2236 | 
                   foreach ($enrolinstances as $courseenrolinstance) {
  | 
        
        
            | 
            | 
           2237 | 
                       if ($courseenrolinstance->enrol == "manual") {
  | 
        
        
            | 
            | 
           2238 | 
                           $instance = $courseenrolinstance;
  | 
        
        
            | 
            | 
           2239 | 
                           break;
  | 
        
        
            | 
            | 
           2240 | 
                       }
  | 
        
        
            | 
            | 
           2241 | 
                   }
  | 
        
        
            | 
            | 
           2242 | 
                   $enrol->enrol_user($instance, $user->id);
  | 
        
        
            | 
            | 
           2243 | 
              | 
        
        
            | 
            | 
           2244 | 
                   // Assign capabilities to delete module 1.
  | 
        
        
            | 
            | 
           2245 | 
                   $modcontext = context_module::instance($module1->cmid);
  | 
        
        
            | 
            | 
           2246 | 
                   $this->assignUserCapability('moodle/course:manageactivities', $modcontext->id);
  | 
        
        
            | 
            | 
           2247 | 
              | 
        
        
            | 
            | 
           2248 | 
                   // Assign capabilities to delete module 2.
  | 
        
        
            | 
            | 
           2249 | 
                   $modcontext = context_module::instance($module2->cmid);
  | 
        
        
            | 
            | 
           2250 | 
                   $newrole = create_role('Role 2', 'role2', 'Role 2 description');
  | 
        
        
            | 
            | 
           2251 | 
                   $this->assignUserCapability('moodle/course:manageactivities', $modcontext->id, $newrole);
  | 
        
        
            | 
            | 
           2252 | 
              | 
        
        
            | 
            | 
           2253 | 
                   // Deleting these module instances.
  | 
        
        
            | 
            | 
           2254 | 
                   core_course_external::delete_modules(array($module1->cmid, $module2->cmid));
  | 
        
        
            | 
            | 
           2255 | 
              | 
        
        
            | 
            | 
           2256 | 
                   // Check the forum was deleted.
  | 
        
        
            | 
            | 
           2257 | 
                   $this->assertEquals(0, $DB->count_records('forum', array('id' => $module1->id)));
  | 
        
        
            | 
            | 
           2258 | 
              | 
        
        
            | 
            | 
           2259 | 
                   // Check the assignment was deleted.
  | 
        
        
            | 
            | 
           2260 | 
                   $this->assertEquals(0, $DB->count_records('assign', array('id' => $module2->id)));
  | 
        
        
            | 
            | 
           2261 | 
              | 
        
        
            | 
            | 
           2262 | 
                   // Check we retrieve no data in the course modules table.
  | 
        
        
            | 
            | 
           2263 | 
                   $this->assertEquals(0, $DB->count_records_select('course_modules', 'id = :module1 OR id = :module2',
  | 
        
        
            | 
            | 
           2264 | 
                           array('module1' => $module1->cmid, 'module2' => $module2->cmid)));
  | 
        
        
            | 
            | 
           2265 | 
              | 
        
        
            | 
            | 
           2266 | 
                   // Call with non-existent course module id and ensure exception thrown.
  | 
        
        
            | 
            | 
           2267 | 
                   try {
  | 
        
        
            | 
            | 
           2268 | 
                       core_course_external::delete_modules(array('1337'));
  | 
        
        
            | 
            | 
           2269 | 
                       $this->fail('Exception expected due to missing course module.');
  | 
        
        
            | 
            | 
           2270 | 
                   } catch (dml_missing_record_exception $e) {
  | 
        
        
            | 
            | 
           2271 | 
                       $this->assertEquals('invalidcoursemodule', $e->errorcode);
  | 
        
        
            | 
            | 
           2272 | 
                   }
  | 
        
        
            | 
            | 
           2273 | 
              | 
        
        
            | 
            | 
           2274 | 
                   // Create two modules.
  | 
        
        
            | 
            | 
           2275 | 
                   $module1 = self::getDataGenerator()->create_module('forum', $record);
  | 
        
        
            | 
            | 
           2276 | 
                   $module2 = self::getDataGenerator()->create_module('assign', $record);
  | 
        
        
            | 
            | 
           2277 | 
              | 
        
        
            | 
            | 
           2278 | 
                   // Since these modules were recreated the user will not have capabilities
  | 
        
        
            | 
            | 
           2279 | 
                   // to delete them, ensure exception is thrown if they try.
  | 
        
        
            | 
            | 
           2280 | 
                   try {
  | 
        
        
            | 
            | 
           2281 | 
                       core_course_external::delete_modules(array($module1->cmid, $module2->cmid));
  | 
        
        
            | 
            | 
           2282 | 
                       $this->fail('Exception expected due to missing capability.');
  | 
        
        
            | 
            | 
           2283 | 
                   } catch (moodle_exception $e) {
  | 
        
        
            | 
            | 
           2284 | 
                       $this->assertEquals('nopermissions', $e->errorcode);
  | 
        
        
            | 
            | 
           2285 | 
                   }
  | 
        
        
            | 
            | 
           2286 | 
              | 
        
        
            | 
            | 
           2287 | 
                   // Unenrol user from the course.
  | 
        
        
            | 
            | 
           2288 | 
                   $enrol->unenrol_user($instance, $user->id);
  | 
        
        
            | 
            | 
           2289 | 
              | 
        
        
            | 
            | 
           2290 | 
                   // Try and delete modules from the course the user was unenrolled in, make sure exception thrown.
  | 
        
        
            | 
            | 
           2291 | 
                   try {
  | 
        
        
            | 
            | 
           2292 | 
                       core_course_external::delete_modules(array($module1->cmid, $module2->cmid));
  | 
        
        
            | 
            | 
           2293 | 
                       $this->fail('Exception expected due to being unenrolled from the course.');
  | 
        
        
            | 
            | 
           2294 | 
                   } catch (moodle_exception $e) {
  | 
        
        
            | 
            | 
           2295 | 
                       $this->assertEquals('requireloginerror', $e->errorcode);
  | 
        
        
            | 
            | 
           2296 | 
                   }
  | 
        
        
            | 
            | 
           2297 | 
               }
  | 
        
        
            | 
            | 
           2298 | 
              | 
        
        
            | 
            | 
           2299 | 
               /**
  | 
        
        
            | 
            | 
           2300 | 
                * Test import_course into an empty course
  | 
        
        
            | 
            | 
           2301 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           2302 | 
               public function test_import_course_empty(): void {
  | 
        
        
           | 1 | 
           efrain | 
           2303 | 
                   global $USER;
  | 
        
        
            | 
            | 
           2304 | 
              | 
        
        
            | 
            | 
           2305 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           2306 | 
              | 
        
        
            | 
            | 
           2307 | 
                   $course1  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2308 | 
                   $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course1->id, 'name' => 'Forum test'));
  | 
        
        
            | 
            | 
           2309 | 
                   $page = $this->getDataGenerator()->create_module('page', array('course' => $course1->id, 'name' => 'Page test'));
  | 
        
        
            | 
            | 
           2310 | 
              | 
        
        
            | 
            | 
           2311 | 
                   $course2  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2312 | 
              | 
        
        
            | 
            | 
           2313 | 
                   $course1cms = get_fast_modinfo($course1->id)->get_cms();
  | 
        
        
            | 
            | 
           2314 | 
                   $course2cms = get_fast_modinfo($course2->id)->get_cms();
  | 
        
        
            | 
            | 
           2315 | 
              | 
        
        
            | 
            | 
           2316 | 
                   // Verify the state of the courses before we do the import.
  | 
        
        
            | 
            | 
           2317 | 
                   $this->assertCount(2, $course1cms);
  | 
        
        
            | 
            | 
           2318 | 
                   $this->assertEmpty($course2cms);
  | 
        
        
            | 
            | 
           2319 | 
              | 
        
        
            | 
            | 
           2320 | 
                   // Setup the user to run the operation (ugly hack because validate_context() will
  | 
        
        
            | 
            | 
           2321 | 
                   // fail as the email is not set by $this->setAdminUser()).
  | 
        
        
            | 
            | 
           2322 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           2323 | 
                   $USER->email = 'emailtopass@example.com';
  | 
        
        
            | 
            | 
           2324 | 
              | 
        
        
            | 
            | 
           2325 | 
                   // Import from course1 to course2.
  | 
        
        
            | 
            | 
           2326 | 
                   core_course_external::import_course($course1->id, $course2->id, 0);
  | 
        
        
            | 
            | 
           2327 | 
              | 
        
        
            | 
            | 
           2328 | 
                   // Verify that now we have two modules in both courses.
  | 
        
        
            | 
            | 
           2329 | 
                   $course1cms = get_fast_modinfo($course1->id)->get_cms();
  | 
        
        
            | 
            | 
           2330 | 
                   $course2cms = get_fast_modinfo($course2->id)->get_cms();
  | 
        
        
            | 
            | 
           2331 | 
                   $this->assertCount(2, $course1cms);
  | 
        
        
            | 
            | 
           2332 | 
                   $this->assertCount(2, $course2cms);
  | 
        
        
            | 
            | 
           2333 | 
              | 
        
        
            | 
            | 
           2334 | 
                   // Verify that the names transfered across correctly.
  | 
        
        
            | 
            | 
           2335 | 
                   foreach ($course2cms as $cm) {
  | 
        
        
            | 
            | 
           2336 | 
                       if ($cm->modname === 'page') {
  | 
        
        
            | 
            | 
           2337 | 
                           $this->assertEquals($cm->name, $page->name);
  | 
        
        
            | 
            | 
           2338 | 
                       } else if ($cm->modname === 'forum') {
  | 
        
        
            | 
            | 
           2339 | 
                           $this->assertEquals($cm->name, $forum->name);
  | 
        
        
            | 
            | 
           2340 | 
                       } else {
  | 
        
        
            | 
            | 
           2341 | 
                           $this->fail('Unknown CM found.');
  | 
        
        
            | 
            | 
           2342 | 
                       }
  | 
        
        
            | 
            | 
           2343 | 
                   }
  | 
        
        
            | 
            | 
           2344 | 
               }
  | 
        
        
            | 
            | 
           2345 | 
              | 
        
        
            | 
            | 
           2346 | 
               /**
  | 
        
        
            | 
            | 
           2347 | 
                * Test import_course into an filled course
  | 
        
        
            | 
            | 
           2348 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           2349 | 
               public function test_import_course_filled(): void {
  | 
        
        
           | 1 | 
           efrain | 
           2350 | 
                   global $USER;
  | 
        
        
            | 
            | 
           2351 | 
              | 
        
        
            | 
            | 
           2352 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           2353 | 
              | 
        
        
            | 
            | 
           2354 | 
                   // Add forum and page to course1.
  | 
        
        
            | 
            | 
           2355 | 
                   $course1  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2356 | 
                   $forum = $this->getDataGenerator()->create_module('forum', array('course'=>$course1->id, 'name' => 'Forum test'));
  | 
        
        
            | 
            | 
           2357 | 
                   $page = $this->getDataGenerator()->create_module('page', array('course'=>$course1->id, 'name' => 'Page test'));
  | 
        
        
            | 
            | 
           2358 | 
              | 
        
        
            | 
            | 
           2359 | 
                   // Add quiz to course 2.
  | 
        
        
            | 
            | 
           2360 | 
                   $course2  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2361 | 
                   $quiz = $this->getDataGenerator()->create_module('quiz', array('course'=>$course2->id, 'name' => 'Page test'));
  | 
        
        
            | 
            | 
           2362 | 
              | 
        
        
            | 
            | 
           2363 | 
                   $course1cms = get_fast_modinfo($course1->id)->get_cms();
  | 
        
        
            | 
            | 
           2364 | 
                   $course2cms = get_fast_modinfo($course2->id)->get_cms();
  | 
        
        
            | 
            | 
           2365 | 
              | 
        
        
            | 
            | 
           2366 | 
                   // Verify the state of the courses before we do the import.
  | 
        
        
            | 
            | 
           2367 | 
                   $this->assertCount(2, $course1cms);
  | 
        
        
            | 
            | 
           2368 | 
                   $this->assertCount(1, $course2cms);
  | 
        
        
            | 
            | 
           2369 | 
              | 
        
        
            | 
            | 
           2370 | 
                   // Setup the user to run the operation (ugly hack because validate_context() will
  | 
        
        
            | 
            | 
           2371 | 
                   // fail as the email is not set by $this->setAdminUser()).
  | 
        
        
            | 
            | 
           2372 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           2373 | 
                   $USER->email = 'emailtopass@example.com';
  | 
        
        
            | 
            | 
           2374 | 
              | 
        
        
            | 
            | 
           2375 | 
                   // Import from course1 to course2 without deleting content.
  | 
        
        
            | 
            | 
           2376 | 
                   core_course_external::import_course($course1->id, $course2->id, 0);
  | 
        
        
            | 
            | 
           2377 | 
              | 
        
        
            | 
            | 
           2378 | 
                   $course2cms = get_fast_modinfo($course2->id)->get_cms();
  | 
        
        
            | 
            | 
           2379 | 
              | 
        
        
            | 
            | 
           2380 | 
                   // Verify that now we have three modules in course2.
  | 
        
        
            | 
            | 
           2381 | 
                   $this->assertCount(3, $course2cms);
  | 
        
        
            | 
            | 
           2382 | 
              | 
        
        
            | 
            | 
           2383 | 
                   // Verify that the names transfered across correctly.
  | 
        
        
            | 
            | 
           2384 | 
                   foreach ($course2cms as $cm) {
  | 
        
        
            | 
            | 
           2385 | 
                       if ($cm->modname === 'page') {
  | 
        
        
            | 
            | 
           2386 | 
                           $this->assertEquals($cm->name, $page->name);
  | 
        
        
            | 
            | 
           2387 | 
                       } else if ($cm->modname === 'forum') {
  | 
        
        
            | 
            | 
           2388 | 
                           $this->assertEquals($cm->name, $forum->name);
  | 
        
        
            | 
            | 
           2389 | 
                       } else if ($cm->modname === 'quiz') {
  | 
        
        
            | 
            | 
           2390 | 
                           $this->assertEquals($cm->name, $quiz->name);
  | 
        
        
            | 
            | 
           2391 | 
                       } else {
  | 
        
        
            | 
            | 
           2392 | 
                           $this->fail('Unknown CM found.');
  | 
        
        
            | 
            | 
           2393 | 
                       }
  | 
        
        
            | 
            | 
           2394 | 
                   }
  | 
        
        
            | 
            | 
           2395 | 
               }
  | 
        
        
            | 
            | 
           2396 | 
              | 
        
        
            | 
            | 
           2397 | 
               /**
  | 
        
        
            | 
            | 
           2398 | 
                * Test import_course with only blocks set to backup
  | 
        
        
            | 
            | 
           2399 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           2400 | 
               public function test_import_course_blocksonly(): void {
  | 
        
        
           | 1 | 
           efrain | 
           2401 | 
                   global $USER, $DB;
  | 
        
        
            | 
            | 
           2402 | 
              | 
        
        
            | 
            | 
           2403 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           2404 | 
              | 
        
        
            | 
            | 
           2405 | 
                   // Add forum and page to course1.
  | 
        
        
            | 
            | 
           2406 | 
                   $course1  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2407 | 
                   $course1ctx = context_course::instance($course1->id);
  | 
        
        
            | 
            | 
           2408 | 
                   $forum = $this->getDataGenerator()->create_module('forum', array('course'=>$course1->id, 'name' => 'Forum test'));
  | 
        
        
            | 
            | 
           2409 | 
                   $block = $this->getDataGenerator()->create_block('online_users', array('parentcontextid' => $course1ctx->id));
  | 
        
        
            | 
            | 
           2410 | 
              | 
        
        
            | 
            | 
           2411 | 
                   $course2  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2412 | 
                   $course2ctx = context_course::instance($course2->id);
  | 
        
        
            | 
            | 
           2413 | 
                   $initialblockcount = $DB->count_records('block_instances', array('parentcontextid' => $course2ctx->id));
  | 
        
        
            | 
            | 
           2414 | 
                   $initialcmcount = count(get_fast_modinfo($course2->id)->get_cms());
  | 
        
        
            | 
            | 
           2415 | 
              | 
        
        
            | 
            | 
           2416 | 
                   // Setup the user to run the operation (ugly hack because validate_context() will
  | 
        
        
            | 
            | 
           2417 | 
                   // fail as the email is not set by $this->setAdminUser()).
  | 
        
        
            | 
            | 
           2418 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           2419 | 
                   $USER->email = 'emailtopass@example.com';
  | 
        
        
            | 
            | 
           2420 | 
              | 
        
        
            | 
            | 
           2421 | 
                   // Import from course1 to course2 without deleting content, but excluding
  | 
        
        
            | 
            | 
           2422 | 
                   // activities.
  | 
        
        
            | 
            | 
           2423 | 
                   $options = array(
  | 
        
        
            | 
            | 
           2424 | 
                       array('name' => 'activities', 'value' => 0),
  | 
        
        
            | 
            | 
           2425 | 
                       array('name' => 'blocks', 'value' => 1),
  | 
        
        
            | 
            | 
           2426 | 
                       array('name' => 'filters', 'value' => 0),
  | 
        
        
            | 
            | 
           2427 | 
                   );
  | 
        
        
            | 
            | 
           2428 | 
              | 
        
        
            | 
            | 
           2429 | 
                   core_course_external::import_course($course1->id, $course2->id, 0, $options);
  | 
        
        
            | 
            | 
           2430 | 
              | 
        
        
            | 
            | 
           2431 | 
                   $newcmcount = count(get_fast_modinfo($course2->id)->get_cms());
  | 
        
        
            | 
            | 
           2432 | 
                   $newblockcount = $DB->count_records('block_instances', array('parentcontextid' => $course2ctx->id));
  | 
        
        
            | 
            | 
           2433 | 
                   // Check that course modules haven't changed, but that blocks have.
  | 
        
        
            | 
            | 
           2434 | 
                   $this->assertEquals($initialcmcount, $newcmcount);
  | 
        
        
            | 
            | 
           2435 | 
                   $this->assertEquals(($initialblockcount + 1), $newblockcount);
  | 
        
        
            | 
            | 
           2436 | 
               }
  | 
        
        
            | 
            | 
           2437 | 
              | 
        
        
            | 
            | 
           2438 | 
               /**
  | 
        
        
            | 
            | 
           2439 | 
                * Test import_course into an filled course, deleting content.
  | 
        
        
            | 
            | 
           2440 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           2441 | 
               public function test_import_course_deletecontent(): void {
  | 
        
        
           | 1 | 
           efrain | 
           2442 | 
                   global $USER;
  | 
        
        
            | 
            | 
           2443 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           2444 | 
              | 
        
        
            | 
            | 
           2445 | 
                   // Add forum and page to course1.
  | 
        
        
            | 
            | 
           2446 | 
                   $course1  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2447 | 
                   $forum = $this->getDataGenerator()->create_module('forum', array('course'=>$course1->id, 'name' => 'Forum test'));
  | 
        
        
            | 
            | 
           2448 | 
                   $page = $this->getDataGenerator()->create_module('page', array('course'=>$course1->id, 'name' => 'Page test'));
  | 
        
        
            | 
            | 
           2449 | 
              | 
        
        
            | 
            | 
           2450 | 
                   // Add quiz to course 2.
  | 
        
        
            | 
            | 
           2451 | 
                   $course2  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2452 | 
                   $quiz = $this->getDataGenerator()->create_module('quiz', array('course'=>$course2->id, 'name' => 'Page test'));
  | 
        
        
            | 
            | 
           2453 | 
              | 
        
        
            | 
            | 
           2454 | 
                   $course1cms = get_fast_modinfo($course1->id)->get_cms();
  | 
        
        
            | 
            | 
           2455 | 
                   $course2cms = get_fast_modinfo($course2->id)->get_cms();
  | 
        
        
            | 
            | 
           2456 | 
              | 
        
        
            | 
            | 
           2457 | 
                   // Verify the state of the courses before we do the import.
  | 
        
        
            | 
            | 
           2458 | 
                   $this->assertCount(2, $course1cms);
  | 
        
        
            | 
            | 
           2459 | 
                   $this->assertCount(1, $course2cms);
  | 
        
        
            | 
            | 
           2460 | 
              | 
        
        
            | 
            | 
           2461 | 
                   // Setup the user to run the operation (ugly hack because validate_context() will
  | 
        
        
            | 
            | 
           2462 | 
                   // fail as the email is not set by $this->setAdminUser()).
  | 
        
        
            | 
            | 
           2463 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           2464 | 
                   $USER->email = 'emailtopass@example.com';
  | 
        
        
            | 
            | 
           2465 | 
              | 
        
        
            | 
            | 
           2466 | 
                   // Import from course1 to course2,  deleting content.
  | 
        
        
            | 
            | 
           2467 | 
                   core_course_external::import_course($course1->id, $course2->id, 1);
  | 
        
        
            | 
            | 
           2468 | 
              | 
        
        
            | 
            | 
           2469 | 
                   $course2cms = get_fast_modinfo($course2->id)->get_cms();
  | 
        
        
            | 
            | 
           2470 | 
              | 
        
        
            | 
            | 
           2471 | 
                   // Verify that now we have two modules in course2.
  | 
        
        
            | 
            | 
           2472 | 
                   $this->assertCount(2, $course2cms);
  | 
        
        
            | 
            | 
           2473 | 
              | 
        
        
            | 
            | 
           2474 | 
                   // Verify that the course only contains the imported modules.
  | 
        
        
            | 
            | 
           2475 | 
                   foreach ($course2cms as $cm) {
  | 
        
        
            | 
            | 
           2476 | 
                       if ($cm->modname === 'page') {
  | 
        
        
            | 
            | 
           2477 | 
                           $this->assertEquals($cm->name, $page->name);
  | 
        
        
            | 
            | 
           2478 | 
                       } else if ($cm->modname === 'forum') {
  | 
        
        
            | 
            | 
           2479 | 
                           $this->assertEquals($cm->name, $forum->name);
  | 
        
        
            | 
            | 
           2480 | 
                       } else {
  | 
        
        
            | 
            | 
           2481 | 
                           $this->fail('Unknown CM found: '.$cm->name);
  | 
        
        
            | 
            | 
           2482 | 
                       }
  | 
        
        
            | 
            | 
           2483 | 
                   }
  | 
        
        
            | 
            | 
           2484 | 
               }
  | 
        
        
            | 
            | 
           2485 | 
              | 
        
        
            | 
            | 
           2486 | 
               /**
  | 
        
        
            | 
            | 
           2487 | 
                * Ensure import_course handles incorrect deletecontent option correctly.
  | 
        
        
            | 
            | 
           2488 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           2489 | 
               public function test_import_course_invalid_deletecontent_option(): void {
  | 
        
        
           | 1 | 
           efrain | 
           2490 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           2491 | 
              | 
        
        
            | 
            | 
           2492 | 
                   $course1  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2493 | 
                   $course2  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2494 | 
              | 
        
        
            | 
            | 
           2495 | 
                   $this->expectException('moodle_exception');
  | 
        
        
            | 
            | 
           2496 | 
                   $this->expectExceptionMessage(get_string('invalidextparam', 'webservice', -1));
  | 
        
        
            | 
            | 
           2497 | 
                   // Import from course1 to course2, with invalid option
  | 
        
        
            | 
            | 
           2498 | 
                   core_course_external::import_course($course1->id, $course2->id, -1);;
  | 
        
        
            | 
            | 
           2499 | 
               }
  | 
        
        
            | 
            | 
           2500 | 
              | 
        
        
            | 
            | 
           2501 | 
               /**
  | 
        
        
            | 
            | 
           2502 | 
                * Test view_course function
  | 
        
        
            | 
            | 
           2503 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           2504 | 
               public function test_view_course(): void {
  | 
        
        
           | 1 | 
           efrain | 
           2505 | 
              | 
        
        
            | 
            | 
           2506 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           2507 | 
              | 
        
        
            | 
            | 
           2508 | 
                   // Course without sections.
  | 
        
        
            | 
            | 
           2509 | 
                   $course = $this->getDataGenerator()->create_course(array('numsections' => 5), array('createsections' => true));
  | 
        
        
            | 
            | 
           2510 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           2511 | 
              | 
        
        
            | 
            | 
           2512 | 
                   // Redirect events to the sink, so we can recover them later.
  | 
        
        
            | 
            | 
           2513 | 
                   $sink = $this->redirectEvents();
  | 
        
        
            | 
            | 
           2514 | 
              | 
        
        
            | 
            | 
           2515 | 
                   $result = core_course_external::view_course($course->id, 1);
  | 
        
        
            | 
            | 
           2516 | 
                   $result = external_api::clean_returnvalue(core_course_external::view_course_returns(), $result);
  | 
        
        
            | 
            | 
           2517 | 
                   $events = $sink->get_events();
  | 
        
        
            | 
            | 
           2518 | 
                   $event = reset($events);
  | 
        
        
            | 
            | 
           2519 | 
              | 
        
        
            | 
            | 
           2520 | 
                   // Check the event details are correct.
  | 
        
        
            | 
            | 
           2521 | 
                   $this->assertInstanceOf('\core\event\course_viewed', $event);
  | 
        
        
            | 
            | 
           2522 | 
                   $this->assertEquals(context_course::instance($course->id), $event->get_context());
  | 
        
        
            | 
            | 
           2523 | 
                   $this->assertEquals(1, $event->other['coursesectionnumber']);
  | 
        
        
            | 
            | 
           2524 | 
              | 
        
        
            | 
            | 
           2525 | 
                   $result = core_course_external::view_course($course->id);
  | 
        
        
            | 
            | 
           2526 | 
                   $result = external_api::clean_returnvalue(core_course_external::view_course_returns(), $result);
  | 
        
        
            | 
            | 
           2527 | 
                   $events = $sink->get_events();
  | 
        
        
            | 
            | 
           2528 | 
                   $event = array_pop($events);
  | 
        
        
            | 
            | 
           2529 | 
                   $sink->close();
  | 
        
        
            | 
            | 
           2530 | 
              | 
        
        
            | 
            | 
           2531 | 
                   // Check the event details are correct.
  | 
        
        
            | 
            | 
           2532 | 
                   $this->assertInstanceOf('\core\event\course_viewed', $event);
  | 
        
        
            | 
            | 
           2533 | 
                   $this->assertEquals(context_course::instance($course->id), $event->get_context());
  | 
        
        
            | 
            | 
           2534 | 
                   $this->assertEmpty($event->other);
  | 
        
        
            | 
            | 
           2535 | 
              | 
        
        
            | 
            | 
           2536 | 
               }
  | 
        
        
            | 
            | 
           2537 | 
              | 
        
        
            | 
            | 
           2538 | 
               /**
  | 
        
        
            | 
            | 
           2539 | 
                * Test get_course_module
  | 
        
        
            | 
            | 
           2540 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           2541 | 
               public function test_get_course_module(): void {
  | 
        
        
           | 1 | 
           efrain | 
           2542 | 
                   global $DB;
  | 
        
        
            | 
            | 
           2543 | 
              | 
        
        
            | 
            | 
           2544 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           2545 | 
              | 
        
        
            | 
            | 
           2546 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           2547 | 
                   $course = self::getDataGenerator()->create_course(['enablecompletion' => 1]);
  | 
        
        
            | 
            | 
           2548 | 
                   $record = array(
  | 
        
        
            | 
            | 
           2549 | 
                       'course' => $course->id,
  | 
        
        
            | 
            | 
           2550 | 
                       'name' => 'First Assignment'
  | 
        
        
            | 
            | 
           2551 | 
                   );
  | 
        
        
            | 
            | 
           2552 | 
                   $options = array(
  | 
        
        
            | 
            | 
           2553 | 
                       'idnumber' => 'ABC',
  | 
        
        
            | 
            | 
           2554 | 
                       'visible' => 0,
  | 
        
        
            | 
            | 
           2555 | 
                       'completion' => COMPLETION_TRACKING_AUTOMATIC,
  | 
        
        
            | 
            | 
           2556 | 
                       'completiongradeitemnumber' => 0,
  | 
        
        
            | 
            | 
           2557 | 
                       'completionpassgrade' => 1,
  | 
        
        
            | 
            | 
           2558 | 
                   );
  | 
        
        
            | 
            | 
           2559 | 
                   // Hidden activity.
  | 
        
        
            | 
            | 
           2560 | 
                   $assign = self::getDataGenerator()->create_module('assign', $record, $options);
  | 
        
        
            | 
            | 
           2561 | 
              | 
        
        
            | 
            | 
           2562 | 
                   $outcomescale = 'Distinction, Very Good, Good, Pass, Fail';
  | 
        
        
            | 
            | 
           2563 | 
              | 
        
        
            | 
            | 
           2564 | 
                   // Insert a custom grade scale to be used by an outcome.
  | 
        
        
            | 
            | 
           2565 | 
                   $gradescale = new grade_scale();
  | 
        
        
            | 
            | 
           2566 | 
                   $gradescale->name        = 'gettcoursemodulescale';
  | 
        
        
            | 
            | 
           2567 | 
                   $gradescale->courseid    = $course->id;
  | 
        
        
            | 
            | 
           2568 | 
                   $gradescale->userid      = 0;
  | 
        
        
            | 
            | 
           2569 | 
                   $gradescale->scale       = $outcomescale;
  | 
        
        
            | 
            | 
           2570 | 
                   $gradescale->description = 'This scale is used to mark standard assignments.';
  | 
        
        
            | 
            | 
           2571 | 
                   $gradescale->insert();
  | 
        
        
            | 
            | 
           2572 | 
              | 
        
        
            | 
            | 
           2573 | 
                   // Insert an outcome.
  | 
        
        
            | 
            | 
           2574 | 
                   $data = new stdClass();
  | 
        
        
            | 
            | 
           2575 | 
                   $data->courseid = $course->id;
  | 
        
        
            | 
            | 
           2576 | 
                   $data->fullname = 'Team work';
  | 
        
        
            | 
            | 
           2577 | 
                   $data->shortname = 'Team work';
  | 
        
        
            | 
            | 
           2578 | 
                   $data->scaleid = $gradescale->id;
  | 
        
        
            | 
            | 
           2579 | 
                   $outcome = new grade_outcome($data, false);
  | 
        
        
            | 
            | 
           2580 | 
                   $outcome->insert();
  | 
        
        
            | 
            | 
           2581 | 
              | 
        
        
            | 
            | 
           2582 | 
                   $outcomegradeitem = new grade_item();
  | 
        
        
            | 
            | 
           2583 | 
                   $outcomegradeitem->itemname = $outcome->shortname;
  | 
        
        
            | 
            | 
           2584 | 
                   $outcomegradeitem->itemtype = 'mod';
  | 
        
        
            | 
            | 
           2585 | 
                   $outcomegradeitem->itemmodule = 'assign';
  | 
        
        
            | 
            | 
           2586 | 
                   $outcomegradeitem->iteminstance = $assign->id;
  | 
        
        
            | 
            | 
           2587 | 
                   $outcomegradeitem->outcomeid = $outcome->id;
  | 
        
        
            | 
            | 
           2588 | 
                   $outcomegradeitem->cmid = 0;
  | 
        
        
            | 
            | 
           2589 | 
                   $outcomegradeitem->courseid = $course->id;
  | 
        
        
            | 
            | 
           2590 | 
                   $outcomegradeitem->aggregationcoef = 0;
  | 
        
        
            | 
            | 
           2591 | 
                   $outcomegradeitem->itemnumber = 1000; // Outcomes start at 1000.
  | 
        
        
            | 
            | 
           2592 | 
                   $outcomegradeitem->gradetype = GRADE_TYPE_SCALE;
  | 
        
        
            | 
            | 
           2593 | 
                   $outcomegradeitem->scaleid = $outcome->scaleid;
  | 
        
        
            | 
            | 
           2594 | 
                   $outcomegradeitem->insert();
  | 
        
        
            | 
            | 
           2595 | 
              | 
        
        
            | 
            | 
           2596 | 
                   $assignmentgradeitem = grade_item::fetch(
  | 
        
        
            | 
            | 
           2597 | 
                       array(
  | 
        
        
            | 
            | 
           2598 | 
                           'itemtype' => 'mod',
  | 
        
        
            | 
            | 
           2599 | 
                           'itemmodule' => 'assign',
  | 
        
        
            | 
            | 
           2600 | 
                           'iteminstance' => $assign->id,
  | 
        
        
            | 
            | 
           2601 | 
                           'itemnumber' => 0,
  | 
        
        
            | 
            | 
           2602 | 
                           'courseid' => $course->id
  | 
        
        
            | 
            | 
           2603 | 
                       )
  | 
        
        
            | 
            | 
           2604 | 
                   );
  | 
        
        
            | 
            | 
           2605 | 
                   $outcomegradeitem->set_parent($assignmentgradeitem->categoryid);
  | 
        
        
            | 
            | 
           2606 | 
                   $outcomegradeitem->move_after_sortorder($assignmentgradeitem->sortorder);
  | 
        
        
            | 
            | 
           2607 | 
              | 
        
        
            | 
            | 
           2608 | 
                   // Test admin user can see the complete hidden activity.
  | 
        
        
            | 
            | 
           2609 | 
                   $result = core_course_external::get_course_module($assign->cmid);
  | 
        
        
            | 
            | 
           2610 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_course_module_returns(), $result);
  | 
        
        
            | 
            | 
           2611 | 
              | 
        
        
            | 
            | 
           2612 | 
                   $this->assertCount(0, $result['warnings']);
  | 
        
        
            | 
            | 
           2613 | 
                   // Test we retrieve all the fields.
  | 
        
        
            | 
            | 
           2614 | 
                   $this->assertCount(30, $result['cm']);
  | 
        
        
            | 
            | 
           2615 | 
                   $this->assertEquals($record['name'], $result['cm']['name']);
  | 
        
        
            | 
            | 
           2616 | 
                   $this->assertEquals($options['idnumber'], $result['cm']['idnumber']);
  | 
        
        
            | 
            | 
           2617 | 
                   $this->assertEquals(100, $result['cm']['grade']);
  | 
        
        
            | 
            | 
           2618 | 
                   $this->assertEquals(0.0, $result['cm']['gradepass']);
  | 
        
        
            | 
            | 
           2619 | 
                   $this->assertEquals('submissions', $result['cm']['advancedgrading'][0]['area']);
  | 
        
        
            | 
            | 
           2620 | 
                   $this->assertEmpty($result['cm']['advancedgrading'][0]['method']);
  | 
        
        
            | 
            | 
           2621 | 
                   $this->assertEquals($outcomescale, $result['cm']['outcomes'][0]['scale']);
  | 
        
        
            | 
            | 
           2622 | 
                   $this->assertEquals(DOWNLOAD_COURSE_CONTENT_ENABLED, $result['cm']['downloadcontent']);
  | 
        
        
            | 
            | 
           2623 | 
              | 
        
        
            | 
            | 
           2624 | 
                   $student = $this->getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2625 | 
                   $studentrole = $DB->get_record('role', array('shortname' => 'student'));
  | 
        
        
            | 
            | 
           2626 | 
              | 
        
        
            | 
            | 
           2627 | 
                   self::getDataGenerator()->enrol_user($student->id,  $course->id, $studentrole->id);
  | 
        
        
            | 
            | 
           2628 | 
                   $this->setUser($student);
  | 
        
        
            | 
            | 
           2629 | 
              | 
        
        
            | 
            | 
           2630 | 
                   // The user shouldn't be able to see the activity.
  | 
        
        
            | 
            | 
           2631 | 
                   try {
  | 
        
        
            | 
            | 
           2632 | 
                       core_course_external::get_course_module($assign->cmid);
  | 
        
        
            | 
            | 
           2633 | 
                       $this->fail('Exception expected due to invalid permissions.');
  | 
        
        
            | 
            | 
           2634 | 
                   } catch (moodle_exception $e) {
  | 
        
        
            | 
            | 
           2635 | 
                       $this->assertEquals('requireloginerror', $e->errorcode);
  | 
        
        
            | 
            | 
           2636 | 
                   }
  | 
        
        
            | 
            | 
           2637 | 
              | 
        
        
            | 
            | 
           2638 | 
                   // Make module visible.
  | 
        
        
            | 
            | 
           2639 | 
                   set_coursemodule_visible($assign->cmid, 1);
  | 
        
        
            | 
            | 
           2640 | 
              | 
        
        
            | 
            | 
           2641 | 
                   // Test student user.
  | 
        
        
            | 
            | 
           2642 | 
                   $result = core_course_external::get_course_module($assign->cmid);
  | 
        
        
            | 
            | 
           2643 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_course_module_returns(), $result);
  | 
        
        
            | 
            | 
           2644 | 
              | 
        
        
            | 
            | 
           2645 | 
                   $this->assertCount(0, $result['warnings']);
  | 
        
        
            | 
            | 
           2646 | 
                   // Test we retrieve only the few files we can see.
  | 
        
        
            | 
            | 
           2647 | 
                   $this->assertCount(12, $result['cm']);
  | 
        
        
            | 
            | 
           2648 | 
                   $this->assertEquals($assign->cmid, $result['cm']['id']);
  | 
        
        
            | 
            | 
           2649 | 
                   $this->assertEquals($course->id, $result['cm']['course']);
  | 
        
        
            | 
            | 
           2650 | 
                   $this->assertEquals('assign', $result['cm']['modname']);
  | 
        
        
            | 
            | 
           2651 | 
                   $this->assertEquals($assign->id, $result['cm']['instance']);
  | 
        
        
            | 
            | 
           2652 | 
              | 
        
        
            | 
            | 
           2653 | 
               }
  | 
        
        
            | 
            | 
           2654 | 
              | 
        
        
            | 
            | 
           2655 | 
               /**
  | 
        
        
            | 
            | 
           2656 | 
                * Test get_course_module_by_instance
  | 
        
        
            | 
            | 
           2657 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           2658 | 
               public function test_get_course_module_by_instance(): void {
  | 
        
        
           | 1 | 
           efrain | 
           2659 | 
                   global $DB;
  | 
        
        
            | 
            | 
           2660 | 
              | 
        
        
            | 
            | 
           2661 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           2662 | 
              | 
        
        
            | 
            | 
           2663 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           2664 | 
                   $course = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2665 | 
                   $record = array(
  | 
        
        
            | 
            | 
           2666 | 
                       'course' => $course->id,
  | 
        
        
            | 
            | 
           2667 | 
                       'name' => 'First quiz',
  | 
        
        
            | 
            | 
           2668 | 
                       'grade' => 90.00
  | 
        
        
            | 
            | 
           2669 | 
                   );
  | 
        
        
            | 
            | 
           2670 | 
                   $options = array(
  | 
        
        
            | 
            | 
           2671 | 
                       'idnumber' => 'ABC',
  | 
        
        
            | 
            | 
           2672 | 
                       'visible' => 0
  | 
        
        
            | 
            | 
           2673 | 
                   );
  | 
        
        
            | 
            | 
           2674 | 
                   // Hidden activity.
  | 
        
        
            | 
            | 
           2675 | 
                   $quiz = self::getDataGenerator()->create_module('quiz', $record, $options);
  | 
        
        
            | 
            | 
           2676 | 
              | 
        
        
            | 
            | 
           2677 | 
                   // Test admin user can see the complete hidden activity.
  | 
        
        
            | 
            | 
           2678 | 
                   $result = core_course_external::get_course_module_by_instance('quiz', $quiz->id);
  | 
        
        
            | 
            | 
           2679 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_course_module_by_instance_returns(), $result);
  | 
        
        
            | 
            | 
           2680 | 
              | 
        
        
            | 
            | 
           2681 | 
                   $this->assertCount(0, $result['warnings']);
  | 
        
        
            | 
            | 
           2682 | 
                   // Test we retrieve all the fields.
  | 
        
        
            | 
            | 
           2683 | 
                   $this->assertCount(28, $result['cm']);
  | 
        
        
            | 
            | 
           2684 | 
                   $this->assertEquals($record['name'], $result['cm']['name']);
  | 
        
        
            | 
            | 
           2685 | 
                   $this->assertEquals($record['grade'], $result['cm']['grade']);
  | 
        
        
            | 
            | 
           2686 | 
                   $this->assertEquals($options['idnumber'], $result['cm']['idnumber']);
  | 
        
        
            | 
            | 
           2687 | 
                   $this->assertEquals(DOWNLOAD_COURSE_CONTENT_ENABLED, $result['cm']['downloadcontent']);
  | 
        
        
            | 
            | 
           2688 | 
              | 
        
        
            | 
            | 
           2689 | 
                   $student = $this->getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2690 | 
                   $studentrole = $DB->get_record('role', array('shortname' => 'student'));
  | 
        
        
            | 
            | 
           2691 | 
              | 
        
        
            | 
            | 
           2692 | 
                   self::getDataGenerator()->enrol_user($student->id,  $course->id, $studentrole->id);
  | 
        
        
            | 
            | 
           2693 | 
                   $this->setUser($student);
  | 
        
        
            | 
            | 
           2694 | 
              | 
        
        
            | 
            | 
           2695 | 
                   // The user shouldn't be able to see the activity.
  | 
        
        
            | 
            | 
           2696 | 
                   try {
  | 
        
        
            | 
            | 
           2697 | 
                       core_course_external::get_course_module_by_instance('quiz', $quiz->id);
  | 
        
        
            | 
            | 
           2698 | 
                       $this->fail('Exception expected due to invalid permissions.');
  | 
        
        
            | 
            | 
           2699 | 
                   } catch (moodle_exception $e) {
  | 
        
        
            | 
            | 
           2700 | 
                       $this->assertEquals('requireloginerror', $e->errorcode);
  | 
        
        
            | 
            | 
           2701 | 
                   }
  | 
        
        
            | 
            | 
           2702 | 
              | 
        
        
            | 
            | 
           2703 | 
                   // Make module visible.
  | 
        
        
            | 
            | 
           2704 | 
                   set_coursemodule_visible($quiz->cmid, 1);
  | 
        
        
            | 
            | 
           2705 | 
              | 
        
        
            | 
            | 
           2706 | 
                   // Test student user.
  | 
        
        
            | 
            | 
           2707 | 
                   $result = core_course_external::get_course_module_by_instance('quiz', $quiz->id);
  | 
        
        
            | 
            | 
           2708 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_course_module_by_instance_returns(), $result);
  | 
        
        
            | 
            | 
           2709 | 
              | 
        
        
            | 
            | 
           2710 | 
                   $this->assertCount(0, $result['warnings']);
  | 
        
        
            | 
            | 
           2711 | 
                   // Test we retrieve only the few files we can see.
  | 
        
        
            | 
            | 
           2712 | 
                   $this->assertCount(12, $result['cm']);
  | 
        
        
            | 
            | 
           2713 | 
                   $this->assertEquals($quiz->cmid, $result['cm']['id']);
  | 
        
        
            | 
            | 
           2714 | 
                   $this->assertEquals($course->id, $result['cm']['course']);
  | 
        
        
            | 
            | 
           2715 | 
                   $this->assertEquals('quiz', $result['cm']['modname']);
  | 
        
        
            | 
            | 
           2716 | 
                   $this->assertEquals($quiz->id, $result['cm']['instance']);
  | 
        
        
            | 
            | 
           2717 | 
              | 
        
        
            | 
            | 
           2718 | 
                   // Try with an invalid module name.
  | 
        
        
            | 
            | 
           2719 | 
                   try {
  | 
        
        
            | 
            | 
           2720 | 
                       core_course_external::get_course_module_by_instance('abc', $quiz->id);
  | 
        
        
            | 
            | 
           2721 | 
                       $this->fail('Exception expected due to invalid module name.');
  | 
        
        
            | 
            | 
           2722 | 
                   } catch (dml_read_exception $e) {
  | 
        
        
            | 
            | 
           2723 | 
                       $this->assertEquals('dmlreadexception', $e->errorcode);
  | 
        
        
            | 
            | 
           2724 | 
                   }
  | 
        
        
            | 
            | 
           2725 | 
              | 
        
        
            | 
            | 
           2726 | 
               }
  | 
        
        
            | 
            | 
           2727 | 
              | 
        
        
            | 
            | 
           2728 | 
               /**
  | 
        
        
            | 
            | 
           2729 | 
                * Test get_user_navigation_options
  | 
        
        
            | 
            | 
           2730 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           2731 | 
               public function test_get_user_navigation_options(): void {
  | 
        
        
           | 1 | 
           efrain | 
           2732 | 
                   global $USER;
  | 
        
        
            | 
            | 
           2733 | 
              | 
        
        
            | 
            | 
           2734 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           2735 | 
                   $course1 = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2736 | 
                   $course2 = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2737 | 
              | 
        
        
            | 
            | 
           2738 | 
                   // Create a viewer user.
  | 
        
        
            | 
            | 
           2739 | 
                   $viewer = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2740 | 
                   $this->getDataGenerator()->enrol_user($viewer->id, $course1->id);
  | 
        
        
            | 
            | 
           2741 | 
                   $this->getDataGenerator()->enrol_user($viewer->id, $course2->id);
  | 
        
        
            | 
            | 
           2742 | 
              | 
        
        
            | 
            | 
           2743 | 
                   $this->setUser($viewer->id);
  | 
        
        
            | 
            | 
           2744 | 
                   $courses = array($course1->id , $course2->id, SITEID);
  | 
        
        
            | 
            | 
           2745 | 
              | 
        
        
            | 
            | 
           2746 | 
                   $result = core_course_external::get_user_navigation_options($courses);
  | 
        
        
            | 
            | 
           2747 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_user_navigation_options_returns(), $result);
  | 
        
        
            | 
            | 
           2748 | 
              | 
        
        
            | 
            | 
           2749 | 
                   $this->assertCount(0, $result['warnings']);
  | 
        
        
            | 
            | 
           2750 | 
                   $this->assertCount(3, $result['courses']);
  | 
        
        
            | 
            | 
           2751 | 
              | 
        
        
            | 
            | 
           2752 | 
                   foreach ($result['courses'] as $course) {
  | 
        
        
            | 
            | 
           2753 | 
                       $navoptions = new stdClass;
  | 
        
        
            | 
            | 
           2754 | 
                       foreach ($course['options'] as $option) {
  | 
        
        
            | 
            | 
           2755 | 
                           $navoptions->{$option['name']} = $option['available'];
  | 
        
        
            | 
            | 
           2756 | 
                       }
  | 
        
        
            | 
            | 
           2757 | 
                       $this->assertCount(9, $course['options']);
  | 
        
        
            | 
            | 
           2758 | 
                       if ($course['id'] == SITEID) {
  | 
        
        
            | 
            | 
           2759 | 
                           $this->assertTrue($navoptions->blogs);
  | 
        
        
            | 
            | 
           2760 | 
                           $this->assertFalse($navoptions->notes);
  | 
        
        
            | 
            | 
           2761 | 
                           $this->assertFalse($navoptions->participants);
  | 
        
        
            | 
            | 
           2762 | 
                           $this->assertTrue($navoptions->badges);
  | 
        
        
            | 
            | 
           2763 | 
                           $this->assertTrue($navoptions->tags);
  | 
        
        
            | 
            | 
           2764 | 
                           $this->assertFalse($navoptions->grades);
  | 
        
        
            | 
            | 
           2765 | 
                           $this->assertFalse($navoptions->search);
  | 
        
        
            | 
            | 
           2766 | 
                           $this->assertTrue($navoptions->competencies);
  | 
        
        
            | 
            | 
           2767 | 
                           $this->assertFalse($navoptions->communication);
  | 
        
        
            | 
            | 
           2768 | 
                       } else {
  | 
        
        
            | 
            | 
           2769 | 
                           $this->assertTrue($navoptions->blogs);
  | 
        
        
            | 
            | 
           2770 | 
                           $this->assertFalse($navoptions->notes);
  | 
        
        
            | 
            | 
           2771 | 
                           $this->assertTrue($navoptions->participants);
  | 
        
        
            | 
            | 
           2772 | 
                           $this->assertFalse($navoptions->badges);
  | 
        
        
            | 
            | 
           2773 | 
                           $this->assertFalse($navoptions->tags);
  | 
        
        
            | 
            | 
           2774 | 
                           $this->assertTrue($navoptions->grades);
  | 
        
        
            | 
            | 
           2775 | 
                           $this->assertFalse($navoptions->search);
  | 
        
        
            | 
            | 
           2776 | 
                           $this->assertTrue($navoptions->competencies);
  | 
        
        
            | 
            | 
           2777 | 
                           $this->assertFalse($navoptions->communication);
  | 
        
        
            | 
            | 
           2778 | 
                       }
  | 
        
        
            | 
            | 
           2779 | 
                   }
  | 
        
        
            | 
            | 
           2780 | 
               }
  | 
        
        
            | 
            | 
           2781 | 
              | 
        
        
            | 
            | 
           2782 | 
               /**
  | 
        
        
            | 
            | 
           2783 | 
                * Test get_user_administration_options
  | 
        
        
            | 
            | 
           2784 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           2785 | 
               public function test_get_user_administration_options(): void {
  | 
        
        
           | 1 | 
           efrain | 
           2786 | 
                   global $USER;
  | 
        
        
            | 
            | 
           2787 | 
              | 
        
        
            | 
            | 
           2788 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           2789 | 
                   $course1 = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2790 | 
                   $course2 = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           2791 | 
              | 
        
        
            | 
            | 
           2792 | 
                   // Create a viewer user.
  | 
        
        
            | 
            | 
           2793 | 
                   $viewer = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2794 | 
                   $this->getDataGenerator()->enrol_user($viewer->id, $course1->id);
  | 
        
        
            | 
            | 
           2795 | 
                   $this->getDataGenerator()->enrol_user($viewer->id, $course2->id);
  | 
        
        
            | 
            | 
           2796 | 
              | 
        
        
            | 
            | 
           2797 | 
                   $this->setUser($viewer->id);
  | 
        
        
            | 
            | 
           2798 | 
                   $courses = array($course1->id , $course2->id, SITEID);
  | 
        
        
            | 
            | 
           2799 | 
              | 
        
        
            | 
            | 
           2800 | 
                   $result = core_course_external::get_user_administration_options($courses);
  | 
        
        
            | 
            | 
           2801 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_user_administration_options_returns(), $result);
  | 
        
        
            | 
            | 
           2802 | 
              | 
        
        
            | 
            | 
           2803 | 
                   $this->assertCount(0, $result['warnings']);
  | 
        
        
            | 
            | 
           2804 | 
                   $this->assertCount(3, $result['courses']);
  | 
        
        
            | 
            | 
           2805 | 
              | 
        
        
            | 
            | 
           2806 | 
                   foreach ($result['courses'] as $course) {
  | 
        
        
            | 
            | 
           2807 | 
                       $adminoptions = new stdClass;
  | 
        
        
            | 
            | 
           2808 | 
                       foreach ($course['options'] as $option) {
  | 
        
        
            | 
            | 
           2809 | 
                           $adminoptions->{$option['name']} = $option['available'];
  | 
        
        
            | 
            | 
           2810 | 
                       }
  | 
        
        
            | 
            | 
           2811 | 
                       if ($course['id'] == SITEID) {
  | 
        
        
            | 
            | 
           2812 | 
                           $this->assertCount(17, $course['options']);
  | 
        
        
            | 
            | 
           2813 | 
                           $this->assertFalse($adminoptions->update);
  | 
        
        
            | 
            | 
           2814 | 
                           $this->assertFalse($adminoptions->filters);
  | 
        
        
            | 
            | 
           2815 | 
                           $this->assertFalse($adminoptions->reports);
  | 
        
        
            | 
            | 
           2816 | 
                           $this->assertFalse($adminoptions->backup);
  | 
        
        
            | 
            | 
           2817 | 
                           $this->assertFalse($adminoptions->restore);
  | 
        
        
            | 
            | 
           2818 | 
                           $this->assertFalse($adminoptions->files);
  | 
        
        
            | 
            | 
           2819 | 
                           $this->assertFalse(!isset($adminoptions->tags));
  | 
        
        
            | 
            | 
           2820 | 
                           $this->assertFalse($adminoptions->gradebook);
  | 
        
        
            | 
            | 
           2821 | 
                           $this->assertFalse($adminoptions->outcomes);
  | 
        
        
            | 
            | 
           2822 | 
                           $this->assertFalse($adminoptions->badges);
  | 
        
        
            | 
            | 
           2823 | 
                           $this->assertFalse($adminoptions->import);
  | 
        
        
            | 
            | 
           2824 | 
                           $this->assertFalse($adminoptions->reset);
  | 
        
        
            | 
            | 
           2825 | 
                           $this->assertFalse($adminoptions->roles);
  | 
        
        
            | 
            | 
           2826 | 
                           $this->assertFalse($adminoptions->editcompletion);
  | 
        
        
            | 
            | 
           2827 | 
                           $this->assertFalse($adminoptions->copy);
  | 
        
        
            | 
            | 
           2828 | 
                       } else {
  | 
        
        
            | 
            | 
           2829 | 
                           $this->assertCount(15, $course['options']);
  | 
        
        
            | 
            | 
           2830 | 
                           $this->assertFalse($adminoptions->update);
  | 
        
        
            | 
            | 
           2831 | 
                           $this->assertFalse($adminoptions->filters);
  | 
        
        
            | 
            | 
           2832 | 
                           $this->assertFalse($adminoptions->reports);
  | 
        
        
            | 
            | 
           2833 | 
                           $this->assertFalse($adminoptions->backup);
  | 
        
        
            | 
            | 
           2834 | 
                           $this->assertFalse($adminoptions->restore);
  | 
        
        
            | 
            | 
           2835 | 
                           $this->assertFalse($adminoptions->files);
  | 
        
        
            | 
            | 
           2836 | 
                           $this->assertFalse($adminoptions->tags);
  | 
        
        
            | 
            | 
           2837 | 
                           $this->assertFalse($adminoptions->gradebook);
  | 
        
        
            | 
            | 
           2838 | 
                           $this->assertFalse($adminoptions->outcomes);
  | 
        
        
            | 
            | 
           2839 | 
                           $this->assertTrue($adminoptions->badges);
  | 
        
        
            | 
            | 
           2840 | 
                           $this->assertFalse($adminoptions->import);
  | 
        
        
            | 
            | 
           2841 | 
                           $this->assertFalse($adminoptions->reset);
  | 
        
        
            | 
            | 
           2842 | 
                           $this->assertFalse($adminoptions->roles);
  | 
        
        
            | 
            | 
           2843 | 
                           $this->assertFalse($adminoptions->editcompletion);
  | 
        
        
            | 
            | 
           2844 | 
                           $this->assertFalse($adminoptions->copy);
  | 
        
        
            | 
            | 
           2845 | 
                       }
  | 
        
        
            | 
            | 
           2846 | 
                   }
  | 
        
        
            | 
            | 
           2847 | 
               }
  | 
        
        
            | 
            | 
           2848 | 
              | 
        
        
            | 
            | 
           2849 | 
               /**
  | 
        
        
            | 
            | 
           2850 | 
                * Test get_courses_by_fields
  | 
        
        
            | 
            | 
           2851 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           2852 | 
               public function test_get_courses_by_field(): void {
  | 
        
        
           | 1 | 
           efrain | 
           2853 | 
                   global $DB, $USER;
  | 
        
        
            | 
            | 
           2854 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           2855 | 
              | 
        
        
            | 
            | 
           2856 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           2857 | 
              | 
        
        
            | 
            | 
           2858 | 
                   $category1 = self::getDataGenerator()->create_category(array('name' => 'Cat 1'));
  | 
        
        
            | 
            | 
           2859 | 
                   $category2 = self::getDataGenerator()->create_category(array('parent' => $category1->id));
  | 
        
        
            | 
            | 
           2860 | 
                   $course1 = self::getDataGenerator()->create_course(
  | 
        
        
            | 
            | 
           2861 | 
                       array('category' => $category1->id, 'shortname' => 'c1', 'format' => 'topics'));
  | 
        
        
            | 
            | 
           2862 | 
              | 
        
        
            | 
            | 
           2863 | 
                   $fieldcategory = self::getDataGenerator()->create_custom_field_category(['name' => 'Other fields']);
  | 
        
        
            | 
            | 
           2864 | 
                   $customfield = ['shortname' => 'test', 'name' => 'Custom field', 'type' => 'text',
  | 
        
        
            | 
            | 
           2865 | 
                       'categoryid' => $fieldcategory->get('id')];
  | 
        
        
            | 
            | 
           2866 | 
                   $field = self::getDataGenerator()->create_custom_field($customfield);
  | 
        
        
            | 
            | 
           2867 | 
                   $customfieldvalue = ['shortname' => 'test', 'value' => 'Test value'];
  | 
        
        
            | 
            | 
           2868 | 
                   // Create course image.
  | 
        
        
            | 
            | 
           2869 | 
                   $draftid = file_get_unused_draft_itemid();
  | 
        
        
            | 
            | 
           2870 | 
                   $filerecord = [
  | 
        
        
            | 
            | 
           2871 | 
                       'component' => 'user',
  | 
        
        
            | 
            | 
           2872 | 
                       'filearea' => 'draft',
  | 
        
        
            | 
            | 
           2873 | 
                       'contextid' => context_user::instance($USER->id)->id,
  | 
        
        
            | 
            | 
           2874 | 
                       'itemid' => $draftid,
  | 
        
        
            | 
            | 
           2875 | 
                       'filename' => 'image.jpg',
  | 
        
        
            | 
            | 
           2876 | 
                       'filepath' => '/',
  | 
        
        
            | 
            | 
           2877 | 
                   ];
  | 
        
        
            | 
            | 
           2878 | 
                   $fs = get_file_storage();
  | 
        
        
            | 
            | 
           2879 | 
                   $fs->create_file_from_pathname($filerecord, __DIR__ . '/fixtures/image.jpg');
  | 
        
        
            | 
            | 
           2880 | 
                   $course2 = self::getDataGenerator()->create_course([
  | 
        
        
            | 
            | 
           2881 | 
                       'visible' => 0,
  | 
        
        
            | 
            | 
           2882 | 
                       'category' => $category2->id,
  | 
        
        
            | 
            | 
           2883 | 
                       'idnumber' => 'i2',
  | 
        
        
            | 
            | 
           2884 | 
                       'customfields' => [$customfieldvalue],
  | 
        
        
            | 
            | 
           2885 | 
                       'overviewfiles_filemanager' => $draftid
  | 
        
        
            | 
            | 
           2886 | 
                   ]);
  | 
        
        
            | 
            | 
           2887 | 
              | 
        
        
            | 
            | 
           2888 | 
                   $student1 = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2889 | 
                   $user1 = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           2890 | 
                   $studentrole = $DB->get_record('role', array('shortname' => 'student'));
  | 
        
        
            | 
            | 
           2891 | 
                   self::getDataGenerator()->enrol_user($student1->id, $course1->id, $studentrole->id);
  | 
        
        
            | 
            | 
           2892 | 
                   self::getDataGenerator()->enrol_user($student1->id, $course2->id, $studentrole->id);
  | 
        
        
            | 
            | 
           2893 | 
              | 
        
        
            | 
            | 
           2894 | 
                   self::setAdminUser();
  | 
        
        
            | 
            | 
           2895 | 
                   // As admins, we should be able to retrieve everything.
  | 
        
        
            | 
            | 
           2896 | 
                   $result = core_course_external::get_courses_by_field();
  | 
        
        
            | 
            | 
           2897 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           2898 | 
                   $this->assertCount(3, $result['courses']);
  | 
        
        
            | 
            | 
           2899 | 
                   // Expect to receive all the fields.
  | 
        
        
            | 
            | 
           2900 | 
                   $this->assertCount(41, $result['courses'][0]);
  | 
        
        
            | 
            | 
           2901 | 
                   $this->assertCount(42, $result['courses'][1]);  // One more field because is not the site course.
  | 
        
        
            | 
            | 
           2902 | 
                   $this->assertCount(42, $result['courses'][2]);  // One more field because is not the site course.
  | 
        
        
            | 
            | 
           2903 | 
              | 
        
        
            | 
            | 
           2904 | 
                   $result = core_course_external::get_courses_by_field('id', $course1->id);
  | 
        
        
            | 
            | 
           2905 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           2906 | 
                   $this->assertCount(1, $result['courses']);
  | 
        
        
            | 
            | 
           2907 | 
                   $this->assertEquals($course1->id, $result['courses'][0]['id']);
  | 
        
        
            | 
            | 
           2908 | 
                   // Expect to receive all the fields.
  | 
        
        
            | 
            | 
           2909 | 
                   $this->assertCount(42, $result['courses'][0]);
  | 
        
        
            | 
            | 
           2910 | 
                   // Check default values for course format topics.
  | 
        
        
            | 
            | 
           2911 | 
                   $this->assertCount(3, $result['courses'][0]['courseformatoptions']);
  | 
        
        
            | 
            | 
           2912 | 
                   foreach ($result['courses'][0]['courseformatoptions'] as $option) {
  | 
        
        
            | 
            | 
           2913 | 
                       switch ($option['name']) {
  | 
        
        
            | 
            | 
           2914 | 
                           case 'hiddensections':
  | 
        
        
            | 
            | 
           2915 | 
                               $this->assertEquals(1, $option['value']);
  | 
        
        
            | 
            | 
           2916 | 
                               break;
  | 
        
        
            | 
            | 
           2917 | 
                           case 'coursedisplay':
  | 
        
        
            | 
            | 
           2918 | 
                               $this->assertEquals(0, $option['value']);
  | 
        
        
            | 
            | 
           2919 | 
                               break;
  | 
        
        
            | 
            | 
           2920 | 
                           case 'indentation':
  | 
        
        
            | 
            | 
           2921 | 
                               $this->assertEquals(1, $option['value']);
  | 
        
        
            | 
            | 
           2922 | 
                               break;
  | 
        
        
            | 
            | 
           2923 | 
                           default:
  | 
        
        
            | 
            | 
           2924 | 
                       }
  | 
        
        
            | 
            | 
           2925 | 
                   }
  | 
        
        
            | 
            | 
           2926 | 
                   $this->assertStringContainsString('/course/generated', $result['courses'][0]['courseimage']);
  | 
        
        
            | 
            | 
           2927 | 
              | 
        
        
            | 
            | 
           2928 | 
                   $result = core_course_external::get_courses_by_field('id', $course2->id);
  | 
        
        
            | 
            | 
           2929 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           2930 | 
                   $this->assertCount(1, $result['courses']);
  | 
        
        
            | 
            | 
           2931 | 
                   $this->assertEquals($course2->id, $result['courses'][0]['id']);
  | 
        
        
            | 
            | 
           2932 | 
                   // Check custom fields properly returned.
  | 
        
        
            | 
            | 
           2933 | 
                   $this->assertEquals([
  | 
        
        
            | 
            | 
           2934 | 
                       'shortname' => $customfield['shortname'],
  | 
        
        
            | 
            | 
           2935 | 
                       'name' => $customfield['name'],
  | 
        
        
            | 
            | 
           2936 | 
                       'type' => $customfield['type'],
  | 
        
        
            | 
            | 
           2937 | 
                       'value' => $customfieldvalue['value'],
  | 
        
        
            | 
            | 
           2938 | 
                       'valueraw' => $customfieldvalue['value'],
  | 
        
        
            | 
            | 
           2939 | 
                   ], $result['courses'][0]['customfields'][0]);
  | 
        
        
            | 
            | 
           2940 | 
                   $this->assertStringContainsString('/course/overviewfiles', $result['courses'][0]['courseimage']);
  | 
        
        
            | 
            | 
           2941 | 
              | 
        
        
            | 
            | 
           2942 | 
                   $result = core_course_external::get_courses_by_field('ids', "$course1->id,$course2->id");
  | 
        
        
            | 
            | 
           2943 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           2944 | 
                   $this->assertCount(2, $result['courses']);
  | 
        
        
            | 
            | 
           2945 | 
              | 
        
        
            | 
            | 
           2946 | 
                   // Check default filters.
  | 
        
        
            | 
            | 
           2947 | 
                   $this->assertCount(6, $result['courses'][0]['filters']);
  | 
        
        
            | 
            | 
           2948 | 
                   $this->assertCount(6, $result['courses'][1]['filters']);
  | 
        
        
            | 
            | 
           2949 | 
              | 
        
        
            | 
            | 
           2950 | 
                   $result = core_course_external::get_courses_by_field('category', $category1->id);
  | 
        
        
            | 
            | 
           2951 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           2952 | 
                   $this->assertCount(1, $result['courses']);
  | 
        
        
            | 
            | 
           2953 | 
                   $this->assertEquals($course1->id, $result['courses'][0]['id']);
  | 
        
        
            | 
            | 
           2954 | 
                   $this->assertEquals('Cat 1', $result['courses'][0]['categoryname']);
  | 
        
        
            | 
            | 
           2955 | 
              | 
        
        
            | 
            | 
           2956 | 
                   $result = core_course_external::get_courses_by_field('shortname', 'c1');
  | 
        
        
            | 
            | 
           2957 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           2958 | 
                   $this->assertCount(1, $result['courses']);
  | 
        
        
            | 
            | 
           2959 | 
                   $this->assertEquals($course1->id, $result['courses'][0]['id']);
  | 
        
        
            | 
            | 
           2960 | 
              | 
        
        
            | 
            | 
           2961 | 
                   $result = core_course_external::get_courses_by_field('idnumber', 'i2');
  | 
        
        
            | 
            | 
           2962 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           2963 | 
                   $this->assertCount(1, $result['courses']);
  | 
        
        
            | 
            | 
           2964 | 
                   $this->assertEquals($course2->id, $result['courses'][0]['id']);
  | 
        
        
            | 
            | 
           2965 | 
              | 
        
        
            | 
            | 
           2966 | 
                   $result = core_course_external::get_courses_by_field('idnumber', 'x');
  | 
        
        
            | 
            | 
           2967 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           2968 | 
                   $this->assertCount(0, $result['courses']);
  | 
        
        
            | 
            | 
           2969 | 
              | 
        
        
            | 
            | 
           2970 | 
                   // Change filter value.
  | 
        
        
            | 
            | 
           2971 | 
                   filter_set_local_state('mediaplugin', context_course::instance($course1->id)->id, TEXTFILTER_OFF);
  | 
        
        
            | 
            | 
           2972 | 
              | 
        
        
            | 
            | 
           2973 | 
                   self::setUser($student1);
  | 
        
        
            | 
            | 
           2974 | 
                   // All visible courses  (including front page) for normal student.
  | 
        
        
            | 
            | 
           2975 | 
                   $result = core_course_external::get_courses_by_field();
  | 
        
        
            | 
            | 
           2976 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           2977 | 
                   $this->assertCount(2, $result['courses']);
  | 
        
        
            | 
            | 
           2978 | 
                   $this->assertCount(34, $result['courses'][0]);
  | 
        
        
            | 
            | 
           2979 | 
                   $this->assertCount(35, $result['courses'][1]);  // One field more (course format options), not present in site course.
  | 
        
        
            | 
            | 
           2980 | 
              | 
        
        
            | 
            | 
           2981 | 
                   $result = core_course_external::get_courses_by_field('id', $course1->id);
  | 
        
        
            | 
            | 
           2982 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           2983 | 
                   $this->assertCount(1, $result['courses']);
  | 
        
        
            | 
            | 
           2984 | 
                   $this->assertEquals($course1->id, $result['courses'][0]['id']);
  | 
        
        
            | 
            | 
           2985 | 
                   // Expect to receive all the files that a student can see.
  | 
        
        
            | 
            | 
           2986 | 
                   $this->assertCount(35, $result['courses'][0]);
  | 
        
        
            | 
            | 
           2987 | 
              | 
        
        
            | 
            | 
           2988 | 
                   // Check default filters.
  | 
        
        
            | 
            | 
           2989 | 
                   $filters = $result['courses'][0]['filters'];
  | 
        
        
            | 
            | 
           2990 | 
                   $this->assertCount(6, $filters);
  | 
        
        
            | 
            | 
           2991 | 
                   $found = false;
  | 
        
        
            | 
            | 
           2992 | 
                   foreach ($filters as $filter) {
  | 
        
        
            | 
            | 
           2993 | 
                       if ($filter['filter'] == 'mediaplugin' and $filter['localstate'] == TEXTFILTER_OFF) {
  | 
        
        
            | 
            | 
           2994 | 
                           $found = true;
  | 
        
        
            | 
            | 
           2995 | 
                       }
  | 
        
        
            | 
            | 
           2996 | 
                   }
  | 
        
        
            | 
            | 
           2997 | 
                   $this->assertTrue($found);
  | 
        
        
            | 
            | 
           2998 | 
              | 
        
        
            | 
            | 
           2999 | 
                   // Course 2 is not visible.
  | 
        
        
            | 
            | 
           3000 | 
                   $result = core_course_external::get_courses_by_field('id', $course2->id);
  | 
        
        
            | 
            | 
           3001 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3002 | 
                   $this->assertCount(0, $result['courses']);
  | 
        
        
            | 
            | 
           3003 | 
              | 
        
        
            | 
            | 
           3004 | 
                   $result = core_course_external::get_courses_by_field('ids', "$course1->id,$course2->id");
  | 
        
        
            | 
            | 
           3005 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3006 | 
                   $this->assertCount(1, $result['courses']);
  | 
        
        
            | 
            | 
           3007 | 
              | 
        
        
            | 
            | 
           3008 | 
                   $result = core_course_external::get_courses_by_field('category', $category1->id);
  | 
        
        
            | 
            | 
           3009 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3010 | 
                   $this->assertCount(1, $result['courses']);
  | 
        
        
            | 
            | 
           3011 | 
                   $this->assertEquals($course1->id, $result['courses'][0]['id']);
  | 
        
        
            | 
            | 
           3012 | 
              | 
        
        
            | 
            | 
           3013 | 
                   $result = core_course_external::get_courses_by_field('shortname', 'c1');
  | 
        
        
            | 
            | 
           3014 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3015 | 
                   $this->assertCount(1, $result['courses']);
  | 
        
        
            | 
            | 
           3016 | 
                   $this->assertEquals($course1->id, $result['courses'][0]['id']);
  | 
        
        
            | 
            | 
           3017 | 
              | 
        
        
            | 
            | 
           3018 | 
                   $result = core_course_external::get_courses_by_field('idnumber', 'i2');
  | 
        
        
            | 
            | 
           3019 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3020 | 
                   $this->assertCount(0, $result['courses']);
  | 
        
        
            | 
            | 
           3021 | 
              | 
        
        
            | 
            | 
           3022 | 
                   $result = core_course_external::get_courses_by_field('idnumber', 'x');
  | 
        
        
            | 
            | 
           3023 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3024 | 
                   $this->assertCount(0, $result['courses']);
  | 
        
        
            | 
            | 
           3025 | 
              | 
        
        
            | 
            | 
           3026 | 
                   self::setUser($user1);
  | 
        
        
            | 
            | 
           3027 | 
                   // All visible courses (including front page) for authenticated user.
  | 
        
        
            | 
            | 
           3028 | 
                   $result = core_course_external::get_courses_by_field();
  | 
        
        
            | 
            | 
           3029 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3030 | 
                   $this->assertCount(2, $result['courses']);
  | 
        
        
            | 
            | 
           3031 | 
                   $this->assertCount(34, $result['courses'][0]);  // Site course.
  | 
        
        
            | 
            | 
           3032 | 
                   $this->assertCount(17, $result['courses'][1]);  // Only public information, not enrolled.
  | 
        
        
            | 
            | 
           3033 | 
              | 
        
        
            | 
            | 
           3034 | 
                   $result = core_course_external::get_courses_by_field('id', $course1->id);
  | 
        
        
            | 
            | 
           3035 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3036 | 
                   $this->assertCount(1, $result['courses']);
  | 
        
        
            | 
            | 
           3037 | 
                   $this->assertEquals($course1->id, $result['courses'][0]['id']);
  | 
        
        
            | 
            | 
           3038 | 
                   // Expect to receive all the files that a authenticated can see.
  | 
        
        
            | 
            | 
           3039 | 
                   $this->assertCount(17, $result['courses'][0]);
  | 
        
        
            | 
            | 
           3040 | 
              | 
        
        
            | 
            | 
           3041 | 
                   // Course 2 is not visible.
  | 
        
        
            | 
            | 
           3042 | 
                   $result = core_course_external::get_courses_by_field('id', $course2->id);
  | 
        
        
            | 
            | 
           3043 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3044 | 
                   $this->assertCount(0, $result['courses']);
  | 
        
        
            | 
            | 
           3045 | 
              | 
        
        
            | 
            | 
           3046 | 
                   $result = core_course_external::get_courses_by_field('ids', "$course1->id,$course2->id");
  | 
        
        
            | 
            | 
           3047 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3048 | 
                   $this->assertCount(1, $result['courses']);
  | 
        
        
            | 
            | 
           3049 | 
              | 
        
        
            | 
            | 
           3050 | 
                   $result = core_course_external::get_courses_by_field('category', $category1->id);
  | 
        
        
            | 
            | 
           3051 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3052 | 
                   $this->assertCount(1, $result['courses']);
  | 
        
        
            | 
            | 
           3053 | 
                   $this->assertEquals($course1->id, $result['courses'][0]['id']);
  | 
        
        
            | 
            | 
           3054 | 
              | 
        
        
            | 
            | 
           3055 | 
                   $result = core_course_external::get_courses_by_field('shortname', 'c1');
  | 
        
        
            | 
            | 
           3056 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3057 | 
                   $this->assertCount(1, $result['courses']);
  | 
        
        
            | 
            | 
           3058 | 
                   $this->assertEquals($course1->id, $result['courses'][0]['id']);
  | 
        
        
            | 
            | 
           3059 | 
              | 
        
        
            | 
            | 
           3060 | 
                   $result = core_course_external::get_courses_by_field('idnumber', 'i2');
  | 
        
        
            | 
            | 
           3061 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3062 | 
                   $this->assertCount(0, $result['courses']);
  | 
        
        
            | 
            | 
           3063 | 
              | 
        
        
            | 
            | 
           3064 | 
                   $result = core_course_external::get_courses_by_field('idnumber', 'x');
  | 
        
        
            | 
            | 
           3065 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3066 | 
                   $this->assertCount(0, $result['courses']);
  | 
        
        
            | 
            | 
           3067 | 
               }
  | 
        
        
            | 
            | 
           3068 | 
              | 
        
        
            | 
            | 
           3069 | 
               /**
  | 
        
        
            | 
            | 
           3070 | 
                * Test retrieving courses by field returns custom field data
  | 
        
        
            | 
            | 
           3071 | 
                */
  | 
        
        
            | 
            | 
           3072 | 
               public function test_get_courses_by_field_customfields(): void {
  | 
        
        
            | 
            | 
           3073 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           3074 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           3075 | 
              | 
        
        
            | 
            | 
           3076 | 
                   $fieldcategory = $this->getDataGenerator()->create_custom_field_category([]);
  | 
        
        
            | 
            | 
           3077 | 
                   $datefield = $this->getDataGenerator()->create_custom_field([
  | 
        
        
            | 
            | 
           3078 | 
                       'categoryid' => $fieldcategory->get('id'),
  | 
        
        
            | 
            | 
           3079 | 
                       'shortname' => 'mydate',
  | 
        
        
            | 
            | 
           3080 | 
                       'name' => 'My date',
  | 
        
        
            | 
            | 
           3081 | 
                       'type' => 'date',
  | 
        
        
            | 
            | 
           3082 | 
                   ]);
  | 
        
        
            | 
            | 
           3083 | 
              | 
        
        
            | 
            | 
           3084 | 
                   $newcourse = $this->getDataGenerator()->create_course(['customfields' => [
  | 
        
        
            | 
            | 
           3085 | 
                       [
  | 
        
        
            | 
            | 
           3086 | 
                           'shortname' => $datefield->get('shortname'),
  | 
        
        
            | 
            | 
           3087 | 
                           'value' => 1580389200, // 30/01/2020 13:00 GMT.
  | 
        
        
            | 
            | 
           3088 | 
                       ],
  | 
        
        
            | 
            | 
           3089 | 
                   ]]);
  | 
        
        
            | 
            | 
           3090 | 
              | 
        
        
            | 
            | 
           3091 | 
                   $result = external_api::clean_returnvalue(
  | 
        
        
            | 
            | 
           3092 | 
                       core_course_external::get_courses_by_field_returns(),
  | 
        
        
            | 
            | 
           3093 | 
                       core_course_external::get_courses_by_field('id', $newcourse->id)
  | 
        
        
            | 
            | 
           3094 | 
                   );
  | 
        
        
            | 
            | 
           3095 | 
              | 
        
        
            | 
            | 
           3096 | 
                   $this->assertCount(1, $result['courses']);
  | 
        
        
            | 
            | 
           3097 | 
                   $course = reset($result['courses']);
  | 
        
        
            | 
            | 
           3098 | 
              | 
        
        
            | 
            | 
           3099 | 
                   $this->assertArrayHasKey('customfields', $course);
  | 
        
        
            | 
            | 
           3100 | 
                   $this->assertCount(1, $course['customfields']);
  | 
        
        
            | 
            | 
           3101 | 
              | 
        
        
            | 
            | 
           3102 | 
                   // Assert the received custom field, "value" containing a human-readable version and "valueraw" the unmodified version.
  | 
        
        
            | 
            | 
           3103 | 
                   $this->assertEquals([
  | 
        
        
            | 
            | 
           3104 | 
                       'name' => $datefield->get('name'),
  | 
        
        
            | 
            | 
           3105 | 
                       'shortname' => $datefield->get('shortname'),
  | 
        
        
            | 
            | 
           3106 | 
                       'type' => $datefield->get('type'),
  | 
        
        
            | 
            | 
           3107 | 
                       'value' => userdate(1580389200),
  | 
        
        
            | 
            | 
           3108 | 
                       'valueraw' => 1580389200,
  | 
        
        
            | 
            | 
           3109 | 
                   ], reset($course['customfields']));
  | 
        
        
            | 
            | 
           3110 | 
               }
  | 
        
        
            | 
            | 
           3111 | 
              | 
        
        
            | 
            | 
           3112 | 
               /**
  | 
        
        
            | 
            | 
           3113 | 
                * Test retrieving courses by field returning communication tools.
  | 
        
        
            | 
            | 
           3114 | 
                * @covers \core_course_external::get_courses_by_field
  | 
        
        
            | 
            | 
           3115 | 
                */
  | 
        
        
            | 
            | 
           3116 | 
               public function test_get_courses_by_field_communication(): void {
  | 
        
        
            | 
            | 
           3117 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           3118 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           3119 | 
              | 
        
        
            | 
            | 
           3120 | 
                   // Create communication tool in course.
  | 
        
        
            | 
            | 
           3121 | 
                   set_config('enablecommunicationsubsystem', 1);
  | 
        
        
            | 
            | 
           3122 | 
              | 
        
        
            | 
            | 
           3123 | 
                   $roomname = 'Course chat';
  | 
        
        
            | 
            | 
           3124 | 
                   $telegramlink = 'https://my.telegram.chat/120';
  | 
        
        
            | 
            | 
           3125 | 
                   $record = [
  | 
        
        
            | 
            | 
           3126 | 
                       'selectedcommunication' => 'communication_customlink',
  | 
        
        
            | 
            | 
           3127 | 
                       'communicationroomname' => $roomname,
  | 
        
        
            | 
            | 
           3128 | 
                       'customlinkurl' => $telegramlink,
  | 
        
        
            | 
            | 
           3129 | 
                   ];
  | 
        
        
            | 
            | 
           3130 | 
                   $course = $this->getDataGenerator()->create_course($record);
  | 
        
        
            | 
            | 
           3131 | 
                   $communication = \core_communication\api::load_by_instance(
  | 
        
        
            | 
            | 
           3132 | 
                       context: \core\context\course::instance($course->id),
  | 
        
        
            | 
            | 
           3133 | 
                       component: 'core_course',
  | 
        
        
            | 
            | 
           3134 | 
                       instancetype: 'coursecommunication',
  | 
        
        
            | 
            | 
           3135 | 
                       instanceid: $course->id,
  | 
        
        
            | 
            | 
           3136 | 
                   );
  | 
        
        
            | 
            | 
           3137 | 
              | 
        
        
            | 
            | 
           3138 | 
                   $result = external_api::clean_returnvalue(
  | 
        
        
            | 
            | 
           3139 | 
                       core_course_external::get_courses_by_field_returns(),
  | 
        
        
            | 
            | 
           3140 | 
                       core_course_external::get_courses_by_field('id', $course->id)
  | 
        
        
            | 
            | 
           3141 | 
                   );
  | 
        
        
            | 
            | 
           3142 | 
              | 
        
        
            | 
            | 
           3143 | 
                   $course = reset($result['courses']);
  | 
        
        
            | 
            | 
           3144 | 
                   $this->assertEquals($roomname, $course['communicationroomname']);
  | 
        
        
            | 
            | 
           3145 | 
                   $this->assertEquals($telegramlink, $course['communicationroomurl']);
  | 
        
        
            | 
            | 
           3146 | 
              | 
        
        
            | 
            | 
           3147 | 
                   // Course without comm tools.
  | 
        
        
            | 
            | 
           3148 | 
                   $course = $this->getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           3149 | 
                   $result = external_api::clean_returnvalue(
  | 
        
        
            | 
            | 
           3150 | 
                       core_course_external::get_courses_by_field_returns(),
  | 
        
        
            | 
            | 
           3151 | 
                       core_course_external::get_courses_by_field('id', $course->id)
  | 
        
        
            | 
            | 
           3152 | 
                   );
  | 
        
        
            | 
            | 
           3153 | 
              | 
        
        
            | 
            | 
           3154 | 
                   $course = reset($result['courses']);
  | 
        
        
            | 
            | 
           3155 | 
                   $this->assertNotContains('communicationroomname', $course);
  | 
        
        
            | 
            | 
           3156 | 
                   $this->assertNotContains('communicationroomurl', $course);
  | 
        
        
            | 
            | 
           3157 | 
               }
  | 
        
        
            | 
            | 
           3158 | 
              | 
        
        
           | 11 | 
           efrain | 
           3159 | 
               public function test_get_courses_by_field_invalid_field(): void {
  | 
        
        
           | 1 | 
           efrain | 
           3160 | 
                   $this->expectException('invalid_parameter_exception');
  | 
        
        
            | 
            | 
           3161 | 
                   $result = core_course_external::get_courses_by_field('zyx', 'x');
  | 
        
        
            | 
            | 
           3162 | 
               }
  | 
        
        
            | 
            | 
           3163 | 
              | 
        
        
           | 11 | 
           efrain | 
           3164 | 
               public function test_get_courses_by_field_invalid_courses(): void {
  | 
        
        
           | 1 | 
           efrain | 
           3165 | 
                   $result = core_course_external::get_courses_by_field('id', '-1');
  | 
        
        
            | 
            | 
           3166 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3167 | 
                   $this->assertCount(0, $result['courses']);
  | 
        
        
            | 
            | 
           3168 | 
               }
  | 
        
        
            | 
            | 
           3169 | 
              | 
        
        
            | 
            | 
           3170 | 
               /**
  | 
        
        
            | 
            | 
           3171 | 
                * Test get_courses_by_field_invalid_theme_and_lang
  | 
        
        
            | 
            | 
           3172 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           3173 | 
               public function test_get_courses_by_field_invalid_theme_and_lang(): void {
  | 
        
        
           | 1 | 
           efrain | 
           3174 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           3175 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           3176 | 
              | 
        
        
            | 
            | 
           3177 | 
                   $course = self::getDataGenerator()->create_course(array('theme' => 'kkt', 'lang' => 'kkl'));
  | 
        
        
            | 
            | 
           3178 | 
                   $result = core_course_external::get_courses_by_field('id', $course->id);
  | 
        
        
            | 
            | 
           3179 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
  | 
        
        
            | 
            | 
           3180 | 
                   $this->assertEmpty($result['courses']['0']['theme']);
  | 
        
        
            | 
            | 
           3181 | 
                   $this->assertEmpty($result['courses']['0']['lang']);
  | 
        
        
            | 
            | 
           3182 | 
               }
  | 
        
        
            | 
            | 
           3183 | 
              | 
        
        
            | 
            | 
           3184 | 
              | 
        
        
           | 11 | 
           efrain | 
           3185 | 
               public function test_check_updates(): void {
  | 
        
        
           | 1 | 
           efrain | 
           3186 | 
                   global $DB;
  | 
        
        
            | 
            | 
           3187 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           3188 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           3189 | 
              | 
        
        
            | 
            | 
           3190 | 
                   // Create different types of activities.
  | 
        
        
            | 
            | 
           3191 | 
                   $course  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           3192 | 
                   $tocreate = [
  | 
        
        
            | 
            | 
           3193 | 
                       'assign',
  | 
        
        
            | 
            | 
           3194 | 
                       'book',
  | 
        
        
            | 
            | 
           3195 | 
                       'choice',
  | 
        
        
            | 
            | 
           3196 | 
                       'folder',
  | 
        
        
            | 
            | 
           3197 | 
                       'forum',
  | 
        
        
            | 
            | 
           3198 | 
                       'glossary',
  | 
        
        
            | 
            | 
           3199 | 
                       'imscp',
  | 
        
        
            | 
            | 
           3200 | 
                       'label',
  | 
        
        
            | 
            | 
           3201 | 
                       'lesson',
  | 
        
        
            | 
            | 
           3202 | 
                       'lti',
  | 
        
        
            | 
            | 
           3203 | 
                       'page',
  | 
        
        
            | 
            | 
           3204 | 
                       'quiz',
  | 
        
        
            | 
            | 
           3205 | 
                       'resource',
  | 
        
        
            | 
            | 
           3206 | 
                       'scorm',
  | 
        
        
            | 
            | 
           3207 | 
                       'url',
  | 
        
        
            | 
            | 
           3208 | 
                       'wiki',
  | 
        
        
            | 
            | 
           3209 | 
                   ];
  | 
        
        
            | 
            | 
           3210 | 
              | 
        
        
            | 
            | 
           3211 | 
                   $modules = array();
  | 
        
        
            | 
            | 
           3212 | 
                   foreach ($tocreate as $modname) {
  | 
        
        
            | 
            | 
           3213 | 
                       $modules[$modname]['instance'] = $this->getDataGenerator()->create_module($modname, array('course' => $course->id));
  | 
        
        
            | 
            | 
           3214 | 
                       $modules[$modname]['cm'] = get_coursemodule_from_id(false, $modules[$modname]['instance']->cmid);
  | 
        
        
            | 
            | 
           3215 | 
                       $modules[$modname]['context'] = context_module::instance($modules[$modname]['instance']->cmid);
  | 
        
        
            | 
            | 
           3216 | 
                   }
  | 
        
        
            | 
            | 
           3217 | 
              | 
        
        
            | 
            | 
           3218 | 
                   $student = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           3219 | 
                   $studentrole = $DB->get_record('role', array('shortname' => 'student'));
  | 
        
        
            | 
            | 
           3220 | 
                   self::getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id);
  | 
        
        
            | 
            | 
           3221 | 
                   $this->setUser($student);
  | 
        
        
            | 
            | 
           3222 | 
              | 
        
        
            | 
            | 
           3223 | 
                   $since = time();
  | 
        
        
            | 
            | 
           3224 | 
                   $this->waitForSecond();
  | 
        
        
            | 
            | 
           3225 | 
                   $params = array();
  | 
        
        
            | 
            | 
           3226 | 
                   foreach ($modules as $modname => $data) {
  | 
        
        
            | 
            | 
           3227 | 
                       $params[$data['cm']->id] = array(
  | 
        
        
            | 
            | 
           3228 | 
                           'contextlevel' => 'module',
  | 
        
        
            | 
            | 
           3229 | 
                           'id' => $data['cm']->id,
  | 
        
        
            | 
            | 
           3230 | 
                           'since' => $since
  | 
        
        
            | 
            | 
           3231 | 
                       );
  | 
        
        
            | 
            | 
           3232 | 
                   }
  | 
        
        
            | 
            | 
           3233 | 
              | 
        
        
            | 
            | 
           3234 | 
                   // Check there is nothing updated because modules are fresh new.
  | 
        
        
            | 
            | 
           3235 | 
                   $result = core_course_external::check_updates($course->id, $params);
  | 
        
        
            | 
            | 
           3236 | 
                   $result = external_api::clean_returnvalue(core_course_external::check_updates_returns(), $result);
  | 
        
        
            | 
            | 
           3237 | 
                   $this->assertCount(0, $result['instances']);
  | 
        
        
            | 
            | 
           3238 | 
                   $this->assertCount(0, $result['warnings']);
  | 
        
        
            | 
            | 
           3239 | 
              | 
        
        
            | 
            | 
           3240 | 
                   // Test with get_updates_since the same data.
  | 
        
        
            | 
            | 
           3241 | 
                   $result = core_course_external::get_updates_since($course->id, $since);
  | 
        
        
            | 
            | 
           3242 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_updates_since_returns(), $result);
  | 
        
        
            | 
            | 
           3243 | 
                   $this->assertCount(0, $result['instances']);
  | 
        
        
            | 
            | 
           3244 | 
                   $this->assertCount(0, $result['warnings']);
  | 
        
        
            | 
            | 
           3245 | 
              | 
        
        
            | 
            | 
           3246 | 
                   // Update a module after a second.
  | 
        
        
            | 
            | 
           3247 | 
                   $this->waitForSecond();
  | 
        
        
            | 
            | 
           3248 | 
                   set_coursemodule_name($modules['forum']['cm']->id, 'New forum name');
  | 
        
        
            | 
            | 
           3249 | 
              | 
        
        
            | 
            | 
           3250 | 
                   $found = false;
  | 
        
        
            | 
            | 
           3251 | 
                   $result = core_course_external::check_updates($course->id, $params);
  | 
        
        
            | 
            | 
           3252 | 
                   $result = external_api::clean_returnvalue(core_course_external::check_updates_returns(), $result);
  | 
        
        
            | 
            | 
           3253 | 
                   $this->assertCount(1, $result['instances']);
  | 
        
        
            | 
            | 
           3254 | 
                   $this->assertCount(0, $result['warnings']);
  | 
        
        
            | 
            | 
           3255 | 
                   foreach ($result['instances'] as $module) {
  | 
        
        
            | 
            | 
           3256 | 
                       foreach ($module['updates'] as $update) {
  | 
        
        
            | 
            | 
           3257 | 
                           if ($module['id'] == $modules['forum']['cm']->id and $update['name'] == 'configuration') {
  | 
        
        
            | 
            | 
           3258 | 
                               $found = true;
  | 
        
        
            | 
            | 
           3259 | 
                           }
  | 
        
        
            | 
            | 
           3260 | 
                       }
  | 
        
        
            | 
            | 
           3261 | 
                   }
  | 
        
        
            | 
            | 
           3262 | 
                   $this->assertTrue($found);
  | 
        
        
            | 
            | 
           3263 | 
              | 
        
        
            | 
            | 
           3264 | 
                   // Test with get_updates_since the same data.
  | 
        
        
            | 
            | 
           3265 | 
                   $result = core_course_external::get_updates_since($course->id, $since);
  | 
        
        
            | 
            | 
           3266 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_updates_since_returns(), $result);
  | 
        
        
            | 
            | 
           3267 | 
                   $this->assertCount(1, $result['instances']);
  | 
        
        
            | 
            | 
           3268 | 
                   $this->assertCount(0, $result['warnings']);
  | 
        
        
            | 
            | 
           3269 | 
                   $found = false;
  | 
        
        
            | 
            | 
           3270 | 
                   $this->assertCount(1, $result['instances']);
  | 
        
        
            | 
            | 
           3271 | 
                   $this->assertCount(0, $result['warnings']);
  | 
        
        
            | 
            | 
           3272 | 
                   foreach ($result['instances'] as $module) {
  | 
        
        
            | 
            | 
           3273 | 
                       foreach ($module['updates'] as $update) {
  | 
        
        
            | 
            | 
           3274 | 
                           if ($module['id'] == $modules['forum']['cm']->id and $update['name'] == 'configuration') {
  | 
        
        
            | 
            | 
           3275 | 
                               $found = true;
  | 
        
        
            | 
            | 
           3276 | 
                           }
  | 
        
        
            | 
            | 
           3277 | 
                       }
  | 
        
        
            | 
            | 
           3278 | 
                   }
  | 
        
        
            | 
            | 
           3279 | 
                   $this->assertTrue($found);
  | 
        
        
            | 
            | 
           3280 | 
              | 
        
        
            | 
            | 
           3281 | 
                   // Do not retrieve the configuration field.
  | 
        
        
            | 
            | 
           3282 | 
                   $filter = array('files');
  | 
        
        
            | 
            | 
           3283 | 
                   $found = false;
  | 
        
        
            | 
            | 
           3284 | 
                   $result = core_course_external::check_updates($course->id, $params, $filter);
  | 
        
        
            | 
            | 
           3285 | 
                   $result = external_api::clean_returnvalue(core_course_external::check_updates_returns(), $result);
  | 
        
        
            | 
            | 
           3286 | 
                   $this->assertCount(0, $result['instances']);
  | 
        
        
            | 
            | 
           3287 | 
                   $this->assertCount(0, $result['warnings']);
  | 
        
        
            | 
            | 
           3288 | 
                   $this->assertFalse($found);
  | 
        
        
            | 
            | 
           3289 | 
              | 
        
        
            | 
            | 
           3290 | 
                   // Add invalid cmid.
  | 
        
        
            | 
            | 
           3291 | 
                   $params[] = array(
  | 
        
        
            | 
            | 
           3292 | 
                       'contextlevel' => 'module',
  | 
        
        
            | 
            | 
           3293 | 
                       'id' => -2,
  | 
        
        
            | 
            | 
           3294 | 
                       'since' => $since
  | 
        
        
            | 
            | 
           3295 | 
                   );
  | 
        
        
            | 
            | 
           3296 | 
                   $result = core_course_external::check_updates($course->id, $params);
  | 
        
        
            | 
            | 
           3297 | 
                   $result = external_api::clean_returnvalue(core_course_external::check_updates_returns(), $result);
  | 
        
        
            | 
            | 
           3298 | 
                   $this->assertCount(1, $result['warnings']);
  | 
        
        
            | 
            | 
           3299 | 
                   $this->assertEquals(-2, $result['warnings'][0]['itemid']);
  | 
        
        
            | 
            | 
           3300 | 
               }
  | 
        
        
            | 
            | 
           3301 | 
              | 
        
        
            | 
            | 
           3302 | 
               /**
  | 
        
        
            | 
            | 
           3303 | 
                * Test cases for the get_enrolled_courses_by_timeline_classification test.
  | 
        
        
            | 
            | 
           3304 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           3305 | 
               public static function get_get_enrolled_courses_by_timeline_classification_test_cases(): array {
  | 
        
        
           | 1 | 
           efrain | 
           3306 | 
                   $now = time();
  | 
        
        
            | 
            | 
           3307 | 
                   $day = 86400;
  | 
        
        
            | 
            | 
           3308 | 
              | 
        
        
            | 
            | 
           3309 | 
                   $coursedata = [
  | 
        
        
            | 
            | 
           3310 | 
                       [
  | 
        
        
            | 
            | 
           3311 | 
                           'shortname' => 'apast',
  | 
        
        
            | 
            | 
           3312 | 
                           'startdate' => $now - ($day * 2),
  | 
        
        
            | 
            | 
           3313 | 
                           'enddate' => $now - $day
  | 
        
        
            | 
            | 
           3314 | 
                       ],
  | 
        
        
            | 
            | 
           3315 | 
                       [
  | 
        
        
            | 
            | 
           3316 | 
                           'shortname' => 'bpast',
  | 
        
        
            | 
            | 
           3317 | 
                           'startdate' => $now - ($day * 2),
  | 
        
        
            | 
            | 
           3318 | 
                           'enddate' => $now - $day
  | 
        
        
            | 
            | 
           3319 | 
                       ],
  | 
        
        
            | 
            | 
           3320 | 
                       [
  | 
        
        
            | 
            | 
           3321 | 
                           'shortname' => 'cpast',
  | 
        
        
            | 
            | 
           3322 | 
                           'startdate' => $now - ($day * 2),
  | 
        
        
            | 
            | 
           3323 | 
                           'enddate' => $now - $day
  | 
        
        
            | 
            | 
           3324 | 
                       ],
  | 
        
        
            | 
            | 
           3325 | 
                       [
  | 
        
        
            | 
            | 
           3326 | 
                           'shortname' => 'dpast',
  | 
        
        
            | 
            | 
           3327 | 
                           'startdate' => $now - ($day * 2),
  | 
        
        
            | 
            | 
           3328 | 
                           'enddate' => $now - $day
  | 
        
        
            | 
            | 
           3329 | 
                       ],
  | 
        
        
            | 
            | 
           3330 | 
                       [
  | 
        
        
            | 
            | 
           3331 | 
                           'shortname' => 'epast',
  | 
        
        
            | 
            | 
           3332 | 
                           'startdate' => $now - ($day * 2),
  | 
        
        
            | 
            | 
           3333 | 
                           'enddate' => $now - $day
  | 
        
        
            | 
            | 
           3334 | 
                       ],
  | 
        
        
            | 
            | 
           3335 | 
                       [
  | 
        
        
            | 
            | 
           3336 | 
                           'shortname' => 'ainprogress',
  | 
        
        
            | 
            | 
           3337 | 
                           'startdate' => $now - $day,
  | 
        
        
            | 
            | 
           3338 | 
                           'enddate' => $now + $day
  | 
        
        
            | 
            | 
           3339 | 
                       ],
  | 
        
        
            | 
            | 
           3340 | 
                       [
  | 
        
        
            | 
            | 
           3341 | 
                           'shortname' => 'binprogress',
  | 
        
        
            | 
            | 
           3342 | 
                           'startdate' => $now - $day,
  | 
        
        
            | 
            | 
           3343 | 
                           'enddate' => $now + $day
  | 
        
        
            | 
            | 
           3344 | 
                       ],
  | 
        
        
            | 
            | 
           3345 | 
                       [
  | 
        
        
            | 
            | 
           3346 | 
                           'shortname' => 'cinprogress',
  | 
        
        
            | 
            | 
           3347 | 
                           'startdate' => $now - $day,
  | 
        
        
            | 
            | 
           3348 | 
                           'enddate' => $now + $day
  | 
        
        
            | 
            | 
           3349 | 
                       ],
  | 
        
        
            | 
            | 
           3350 | 
                       [
  | 
        
        
            | 
            | 
           3351 | 
                           'shortname' => 'dinprogress',
  | 
        
        
            | 
            | 
           3352 | 
                           'startdate' => $now - $day,
  | 
        
        
            | 
            | 
           3353 | 
                           'enddate' => $now + $day
  | 
        
        
            | 
            | 
           3354 | 
                       ],
  | 
        
        
            | 
            | 
           3355 | 
                       [
  | 
        
        
            | 
            | 
           3356 | 
                           'shortname' => 'einprogress',
  | 
        
        
            | 
            | 
           3357 | 
                           'startdate' => $now - $day,
  | 
        
        
            | 
            | 
           3358 | 
                           'enddate' => $now + $day
  | 
        
        
            | 
            | 
           3359 | 
                       ],
  | 
        
        
            | 
            | 
           3360 | 
                       [
  | 
        
        
            | 
            | 
           3361 | 
                           'shortname' => 'afuture',
  | 
        
        
            | 
            | 
           3362 | 
                           'startdate' => $now + $day
  | 
        
        
            | 
            | 
           3363 | 
                       ],
  | 
        
        
            | 
            | 
           3364 | 
                       [
  | 
        
        
            | 
            | 
           3365 | 
                           'shortname' => 'bfuture',
  | 
        
        
            | 
            | 
           3366 | 
                           'startdate' => $now + $day
  | 
        
        
            | 
            | 
           3367 | 
                       ],
  | 
        
        
            | 
            | 
           3368 | 
                       [
  | 
        
        
            | 
            | 
           3369 | 
                           'shortname' => 'cfuture',
  | 
        
        
            | 
            | 
           3370 | 
                           'startdate' => $now + $day
  | 
        
        
            | 
            | 
           3371 | 
                       ],
  | 
        
        
            | 
            | 
           3372 | 
                       [
  | 
        
        
            | 
            | 
           3373 | 
                           'shortname' => 'dfuture',
  | 
        
        
            | 
            | 
           3374 | 
                           'startdate' => $now + $day
  | 
        
        
            | 
            | 
           3375 | 
                       ],
  | 
        
        
            | 
            | 
           3376 | 
                       [
  | 
        
        
            | 
            | 
           3377 | 
                           'shortname' => 'efuture',
  | 
        
        
            | 
            | 
           3378 | 
                           'startdate' => $now + $day
  | 
        
        
            | 
            | 
           3379 | 
                       ]
  | 
        
        
            | 
            | 
           3380 | 
                   ];
  | 
        
        
            | 
            | 
           3381 | 
              | 
        
        
            | 
            | 
           3382 | 
                   // Raw enrolled courses result set should be returned in this order:
  | 
        
        
            | 
            | 
           3383 | 
                   // afuture, ainprogress, apast, bfuture, binprogress, bpast, cfuture, cinprogress, cpast,
  | 
        
        
            | 
            | 
           3384 | 
                   // dfuture, dinprogress, dpast, efuture, einprogress, epast
  | 
        
        
            | 
            | 
           3385 | 
                   //
  | 
        
        
            | 
            | 
           3386 | 
                   // By classification the offset values for each record should be:
  | 
        
        
            | 
            | 
           3387 | 
                   // COURSE_TIMELINE_FUTURE
  | 
        
        
            | 
            | 
           3388 | 
                   // 0 (afuture), 3 (bfuture), 6 (cfuture), 9 (dfuture), 12 (efuture)
  | 
        
        
            | 
            | 
           3389 | 
                   // COURSE_TIMELINE_INPROGRESS
  | 
        
        
            | 
            | 
           3390 | 
                   // 1 (ainprogress), 4 (binprogress), 7 (cinprogress), 10 (dinprogress), 13 (einprogress)
  | 
        
        
            | 
            | 
           3391 | 
                   // COURSE_TIMELINE_PAST
  | 
        
        
            | 
            | 
           3392 | 
                   // 2 (apast), 5 (bpast), 8 (cpast), 11 (dpast), 14 (epast).
  | 
        
        
            | 
            | 
           3393 | 
                   //
  | 
        
        
            | 
            | 
           3394 | 
                   // NOTE: The offset applies to the unfiltered full set of courses before the classification
  | 
        
        
            | 
            | 
           3395 | 
                   // filtering is done.
  | 
        
        
            | 
            | 
           3396 | 
                   // E.g. In our example if an offset of 2 is given then it would mean the first
  | 
        
        
            | 
            | 
           3397 | 
                   // two courses (afuture, ainprogress) are ignored.
  | 
        
        
            | 
            | 
           3398 | 
                   return [
  | 
        
        
            | 
            | 
           3399 | 
                       'empty set' => [
  | 
        
        
            | 
            | 
           3400 | 
                           'coursedata' => [],
  | 
        
        
            | 
            | 
           3401 | 
                           'classification' => 'future',
  | 
        
        
            | 
            | 
           3402 | 
                           'limit' => 2,
  | 
        
        
            | 
            | 
           3403 | 
                           'offset' => 0,
  | 
        
        
            | 
            | 
           3404 | 
                           'sort' => 'shortname ASC',
  | 
        
        
            | 
            | 
           3405 | 
                           'expectedcourses' => [],
  | 
        
        
            | 
            | 
           3406 | 
                           'expectednextoffset' => 0,
  | 
        
        
            | 
            | 
           3407 | 
                       ],
  | 
        
        
            | 
            | 
           3408 | 
                       // COURSE_TIMELINE_FUTURE.
  | 
        
        
            | 
            | 
           3409 | 
                       'future not limit no offset' => [
  | 
        
        
            | 
            | 
           3410 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3411 | 
                           'classification' => 'future',
  | 
        
        
            | 
            | 
           3412 | 
                           'limit' => 0,
  | 
        
        
            | 
            | 
           3413 | 
                           'offset' => 0,
  | 
        
        
            | 
            | 
           3414 | 
                           'sort' => 'shortname ASC',
  | 
        
        
            | 
            | 
           3415 | 
                           'expectedcourses' => ['afuture', 'bfuture', 'cfuture', 'dfuture', 'efuture'],
  | 
        
        
            | 
            | 
           3416 | 
                           'expectednextoffset' => 15,
  | 
        
        
            | 
            | 
           3417 | 
                       ],
  | 
        
        
            | 
            | 
           3418 | 
                       'future no offset' => [
  | 
        
        
            | 
            | 
           3419 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3420 | 
                           'classification' => 'future',
  | 
        
        
            | 
            | 
           3421 | 
                           'limit' => 2,
  | 
        
        
            | 
            | 
           3422 | 
                           'offset' => 0,
  | 
        
        
            | 
            | 
           3423 | 
                           'sort' => 'shortname ASC',
  | 
        
        
            | 
            | 
           3424 | 
                           'expectedcourses' => ['afuture', 'bfuture'],
  | 
        
        
            | 
            | 
           3425 | 
                           'expectednextoffset' => 4,
  | 
        
        
            | 
            | 
           3426 | 
                       ],
  | 
        
        
            | 
            | 
           3427 | 
                       'future offset' => [
  | 
        
        
            | 
            | 
           3428 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3429 | 
                           'classification' => 'future',
  | 
        
        
            | 
            | 
           3430 | 
                           'limit' => 2,
  | 
        
        
            | 
            | 
           3431 | 
                           'offset' => 2,
  | 
        
        
            | 
            | 
           3432 | 
                           'sort' => 'shortname ASC',
  | 
        
        
            | 
            | 
           3433 | 
                           'expectedcourses' => ['bfuture', 'cfuture'],
  | 
        
        
            | 
            | 
           3434 | 
                           'expectednextoffset' => 7,
  | 
        
        
            | 
            | 
           3435 | 
                       ],
  | 
        
        
            | 
            | 
           3436 | 
                       'future exact limit' => [
  | 
        
        
            | 
            | 
           3437 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3438 | 
                           'classification' => 'future',
  | 
        
        
            | 
            | 
           3439 | 
                           'limit' => 5,
  | 
        
        
            | 
            | 
           3440 | 
                           'offset' => 0,
  | 
        
        
            | 
            | 
           3441 | 
                           'sort' => 'shortname ASC',
  | 
        
        
            | 
            | 
           3442 | 
                           'expectedcourses' => ['afuture', 'bfuture', 'cfuture', 'dfuture', 'efuture'],
  | 
        
        
            | 
            | 
           3443 | 
                           'expectednextoffset' => 13,
  | 
        
        
            | 
            | 
           3444 | 
                       ],
  | 
        
        
            | 
            | 
           3445 | 
                       'future limit less results' => [
  | 
        
        
            | 
            | 
           3446 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3447 | 
                           'classification' => 'future',
  | 
        
        
            | 
            | 
           3448 | 
                           'limit' => 10,
  | 
        
        
            | 
            | 
           3449 | 
                           'offset' => 0,
  | 
        
        
            | 
            | 
           3450 | 
                           'sort' => 'shortname ASC',
  | 
        
        
            | 
            | 
           3451 | 
                           'expectedcourses' => ['afuture', 'bfuture', 'cfuture', 'dfuture', 'efuture'],
  | 
        
        
            | 
            | 
           3452 | 
                           'expectednextoffset' => 15,
  | 
        
        
            | 
            | 
           3453 | 
                       ],
  | 
        
        
            | 
            | 
           3454 | 
                       'future limit less results with offset' => [
  | 
        
        
            | 
            | 
           3455 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3456 | 
                           'classification' => 'future',
  | 
        
        
            | 
            | 
           3457 | 
                           'limit' => 10,
  | 
        
        
            | 
            | 
           3458 | 
                           'offset' => 5,
  | 
        
        
            | 
            | 
           3459 | 
                           'sort' => 'shortname ASC',
  | 
        
        
            | 
            | 
           3460 | 
                           'expectedcourses' => ['cfuture', 'dfuture', 'efuture'],
  | 
        
        
            | 
            | 
           3461 | 
                           'expectednextoffset' => 15,
  | 
        
        
            | 
            | 
           3462 | 
                       ],
  | 
        
        
            | 
            | 
           3463 | 
                       'all no limit or offset' => [
  | 
        
        
            | 
            | 
           3464 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3465 | 
                           'classification' => 'all',
  | 
        
        
            | 
            | 
           3466 | 
                           'limit' => 0,
  | 
        
        
            | 
            | 
           3467 | 
                           'offset' => 0,
  | 
        
        
            | 
            | 
           3468 | 
                           'sort' => 'shortname ASC',
  | 
        
        
            | 
            | 
           3469 | 
                           'expectedcourses' => [
  | 
        
        
            | 
            | 
           3470 | 
                               'afuture',
  | 
        
        
            | 
            | 
           3471 | 
                               'ainprogress',
  | 
        
        
            | 
            | 
           3472 | 
                               'apast',
  | 
        
        
            | 
            | 
           3473 | 
                               'bfuture',
  | 
        
        
            | 
            | 
           3474 | 
                               'binprogress',
  | 
        
        
            | 
            | 
           3475 | 
                               'bpast',
  | 
        
        
            | 
            | 
           3476 | 
                               'cfuture',
  | 
        
        
            | 
            | 
           3477 | 
                               'cinprogress',
  | 
        
        
            | 
            | 
           3478 | 
                               'cpast',
  | 
        
        
            | 
            | 
           3479 | 
                               'dfuture',
  | 
        
        
            | 
            | 
           3480 | 
                               'dinprogress',
  | 
        
        
            | 
            | 
           3481 | 
                               'dpast',
  | 
        
        
            | 
            | 
           3482 | 
                               'efuture',
  | 
        
        
            | 
            | 
           3483 | 
                               'einprogress',
  | 
        
        
            | 
            | 
           3484 | 
                               'epast'
  | 
        
        
            | 
            | 
           3485 | 
                           ],
  | 
        
        
            | 
            | 
           3486 | 
                           'expectednextoffset' => 15,
  | 
        
        
            | 
            | 
           3487 | 
                       ],
  | 
        
        
            | 
            | 
           3488 | 
                       'all limit no offset' => [
  | 
        
        
            | 
            | 
           3489 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3490 | 
                           'classification' => 'all',
  | 
        
        
            | 
            | 
           3491 | 
                           'limit' => 5,
  | 
        
        
            | 
            | 
           3492 | 
                           'offset' => 0,
  | 
        
        
            | 
            | 
           3493 | 
                           'sort' => 'shortname ASC',
  | 
        
        
            | 
            | 
           3494 | 
                           'expectedcourses' => [
  | 
        
        
            | 
            | 
           3495 | 
                               'afuture',
  | 
        
        
            | 
            | 
           3496 | 
                               'ainprogress',
  | 
        
        
            | 
            | 
           3497 | 
                               'apast',
  | 
        
        
            | 
            | 
           3498 | 
                               'bfuture',
  | 
        
        
            | 
            | 
           3499 | 
                               'binprogress'
  | 
        
        
            | 
            | 
           3500 | 
                           ],
  | 
        
        
            | 
            | 
           3501 | 
                           'expectednextoffset' => 5,
  | 
        
        
            | 
            | 
           3502 | 
                       ],
  | 
        
        
            | 
            | 
           3503 | 
                       'all limit and offset' => [
  | 
        
        
            | 
            | 
           3504 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3505 | 
                           'classification' => 'all',
  | 
        
        
            | 
            | 
           3506 | 
                           'limit' => 5,
  | 
        
        
            | 
            | 
           3507 | 
                           'offset' => 5,
  | 
        
        
            | 
            | 
           3508 | 
                           'sort' => 'shortname ASC',
  | 
        
        
            | 
            | 
           3509 | 
                           'expectedcourses' => [
  | 
        
        
            | 
            | 
           3510 | 
                               'bpast',
  | 
        
        
            | 
            | 
           3511 | 
                               'cfuture',
  | 
        
        
            | 
            | 
           3512 | 
                               'cinprogress',
  | 
        
        
            | 
            | 
           3513 | 
                               'cpast',
  | 
        
        
            | 
            | 
           3514 | 
                               'dfuture'
  | 
        
        
            | 
            | 
           3515 | 
                           ],
  | 
        
        
            | 
            | 
           3516 | 
                           'expectednextoffset' => 10,
  | 
        
        
            | 
            | 
           3517 | 
                       ],
  | 
        
        
            | 
            | 
           3518 | 
                       'all offset past result set' => [
  | 
        
        
            | 
            | 
           3519 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3520 | 
                           'classification' => 'all',
  | 
        
        
            | 
            | 
           3521 | 
                           'limit' => 5,
  | 
        
        
            | 
            | 
           3522 | 
                           'offset' => 50,
  | 
        
        
            | 
            | 
           3523 | 
                           'sort' => 'shortname ASC',
  | 
        
        
            | 
            | 
           3524 | 
                           'expectedcourses' => [],
  | 
        
        
            | 
            | 
           3525 | 
                           'expectednextoffset' => 50,
  | 
        
        
            | 
            | 
           3526 | 
                       ],
  | 
        
        
            | 
            | 
           3527 | 
                       'all limit and offset with sort ul.timeaccess desc' => [
  | 
        
        
            | 
            | 
           3528 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3529 | 
                           'classification' => 'inprogress',
  | 
        
        
            | 
            | 
           3530 | 
                           'limit' => 0,
  | 
        
        
            | 
            | 
           3531 | 
                           'offset' => 0,
  | 
        
        
            | 
            | 
           3532 | 
                           'sort' => 'ul.timeaccess desc',
  | 
        
        
            | 
            | 
           3533 | 
                           'expectedcourses' => [
  | 
        
        
            | 
            | 
           3534 | 
                               'ainprogress',
  | 
        
        
            | 
            | 
           3535 | 
                               'binprogress',
  | 
        
        
            | 
            | 
           3536 | 
                               'cinprogress',
  | 
        
        
            | 
            | 
           3537 | 
                               'dinprogress',
  | 
        
        
            | 
            | 
           3538 | 
                               'einprogress'
  | 
        
        
            | 
            | 
           3539 | 
                           ],
  | 
        
        
            | 
            | 
           3540 | 
                           'expectednextoffset' => 15,
  | 
        
        
            | 
            | 
           3541 | 
                       ],
  | 
        
        
            | 
            | 
           3542 | 
                       'all limit and offset with sort sql injection for sort or 1==1' => [
  | 
        
        
            | 
            | 
           3543 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3544 | 
                           'classification' => 'all',
  | 
        
        
            | 
            | 
           3545 | 
                           'limit' => 5,
  | 
        
        
            | 
            | 
           3546 | 
                           'offset' => 5,
  | 
        
        
            | 
            | 
           3547 | 
                           'sort' => 'ul.timeaccess desc or 1==1',
  | 
        
        
            | 
            | 
           3548 | 
                           'expectedcourses' => [],
  | 
        
        
            | 
            | 
           3549 | 
                           'expectednextoffset' => 0,
  | 
        
        
            | 
            | 
           3550 | 
                           'expectedexception' => 'Invalid $sort parameter in enrol_get_my_courses()',
  | 
        
        
            | 
            | 
           3551 | 
                       ],
  | 
        
        
            | 
            | 
           3552 | 
                       'all limit and offset with sql injection of sort a custom one' => [
  | 
        
        
            | 
            | 
           3553 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3554 | 
                           'classification' => 'all',
  | 
        
        
            | 
            | 
           3555 | 
                           'limit' => 5,
  | 
        
        
            | 
            | 
           3556 | 
                           'offset' => 5,
  | 
        
        
            | 
            | 
           3557 | 
                           'sort' => "ul.timeaccess LIMIT 1--",
  | 
        
        
            | 
            | 
           3558 | 
                           'expectedcourses' => [],
  | 
        
        
            | 
            | 
           3559 | 
                           'expectednextoffset' => 0,
  | 
        
        
            | 
            | 
           3560 | 
                           'expectedexception' => 'Invalid $sort parameter in enrol_get_my_courses()',
  | 
        
        
            | 
            | 
           3561 | 
                       ],
  | 
        
        
            | 
            | 
           3562 | 
                       'all limit and offset with wrong sort direction' => [
  | 
        
        
            | 
            | 
           3563 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3564 | 
                           'classification' => 'all',
  | 
        
        
            | 
            | 
           3565 | 
                           'limit' => 5,
  | 
        
        
            | 
            | 
           3566 | 
                           'offset' => 5,
  | 
        
        
            | 
            | 
           3567 | 
                           'sort' => "ul.timeaccess.foo ascd",
  | 
        
        
            | 
            | 
           3568 | 
                           'expectedcourses' => [],
  | 
        
        
            | 
            | 
           3569 | 
                           'expectednextoffset' => 0,
  | 
        
        
            | 
            | 
           3570 | 
                           'expectedexception' => 'Invalid sort direction in $sort parameter in enrol_get_my_courses()',
  | 
        
        
            | 
            | 
           3571 | 
                       ],
  | 
        
        
            | 
            | 
           3572 | 
                       'all limit and offset with wrong sort param' => [
  | 
        
        
            | 
            | 
           3573 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3574 | 
                           'classification' => 'all',
  | 
        
        
            | 
            | 
           3575 | 
                           'limit' => 5,
  | 
        
        
            | 
            | 
           3576 | 
                           'offset' => 5,
  | 
        
        
            | 
            | 
           3577 | 
                           'sort' => "foobar",
  | 
        
        
            | 
            | 
           3578 | 
                           'expectedcourses' => [],
  | 
        
        
            | 
            | 
           3579 | 
                           'expectednextoffset' => 0,
  | 
        
        
            | 
            | 
           3580 | 
                           'expectedexception' => 'Invalid $sort parameter in enrol_get_my_courses()',
  | 
        
        
            | 
            | 
           3581 | 
                       ],
  | 
        
        
            | 
            | 
           3582 | 
                       'all limit and offset with wrong field separator' => [
  | 
        
        
            | 
            | 
           3583 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3584 | 
                           'classification' => 'all',
  | 
        
        
            | 
            | 
           3585 | 
                           'limit' => 5,
  | 
        
        
            | 
            | 
           3586 | 
                           'offset' => 5,
  | 
        
        
            | 
            | 
           3587 | 
                           'sort' => "ul.timeaccess.foo",
  | 
        
        
            | 
            | 
           3588 | 
                           'expectedcourses' => [],
  | 
        
        
            | 
            | 
           3589 | 
                           'expectednextoffset' => 0,
  | 
        
        
            | 
            | 
           3590 | 
                           'expectedexception' => 'Invalid $sort parameter in enrol_get_my_courses()',
  | 
        
        
            | 
            | 
           3591 | 
                       ],
  | 
        
        
            | 
            | 
           3592 | 
                       'all limit and offset with wrong field separator #' => [
  | 
        
        
            | 
            | 
           3593 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3594 | 
                           'classification' => 'all',
  | 
        
        
            | 
            | 
           3595 | 
                           'limit' => 5,
  | 
        
        
            | 
            | 
           3596 | 
                           'offset' => 5,
  | 
        
        
            | 
            | 
           3597 | 
                           'sort' => "ul#timeaccess",
  | 
        
        
            | 
            | 
           3598 | 
                           'expectedcourses' => [],
  | 
        
        
            | 
            | 
           3599 | 
                           'expectednextoffset' => 0,
  | 
        
        
            | 
            | 
           3600 | 
                           'expectedexception' => 'Invalid $sort parameter in enrol_get_my_courses()',
  | 
        
        
            | 
            | 
           3601 | 
                       ],
  | 
        
        
            | 
            | 
           3602 | 
                       'all limit and offset with wrong field separator $' => [
  | 
        
        
            | 
            | 
           3603 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3604 | 
                           'classification' => 'all',
  | 
        
        
            | 
            | 
           3605 | 
                           'limit' => 5,
  | 
        
        
            | 
            | 
           3606 | 
                           'offset' => 5,
  | 
        
        
            | 
            | 
           3607 | 
                           'sort' => 'ul$timeaccess',
  | 
        
        
            | 
            | 
           3608 | 
                           'expectedcourses' => [],
  | 
        
        
            | 
            | 
           3609 | 
                           'expectednextoffset' => 0,
  | 
        
        
            | 
            | 
           3610 | 
                           'expectedexception' => 'Invalid $sort parameter in enrol_get_my_courses()',
  | 
        
        
            | 
            | 
           3611 | 
                       ],
  | 
        
        
            | 
            | 
           3612 | 
                       'all limit and offset with wrong field name' => [
  | 
        
        
            | 
            | 
           3613 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3614 | 
                           'classification' => 'all',
  | 
        
        
            | 
            | 
           3615 | 
                           'limit' => 5,
  | 
        
        
            | 
            | 
           3616 | 
                           'offset' => 5,
  | 
        
        
            | 
            | 
           3617 | 
                           'sort' => 'timeaccess123',
  | 
        
        
            | 
            | 
           3618 | 
                           'expectedcourses' => [],
  | 
        
        
            | 
            | 
           3619 | 
                           'expectednextoffset' => 0,
  | 
        
        
            | 
            | 
           3620 | 
                           'expectedexception' => 'Invalid $sort parameter in enrol_get_my_courses()',
  | 
        
        
            | 
            | 
           3621 | 
                       ],
  | 
        
        
            | 
            | 
           3622 | 
                       'all limit and offset with no sort direction for ul' => [
  | 
        
        
            | 
            | 
           3623 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3624 | 
                           'classification' => 'inprogress',
  | 
        
        
            | 
            | 
           3625 | 
                           'limit' => 0,
  | 
        
        
            | 
            | 
           3626 | 
                           'offset' => 0,
  | 
        
        
            | 
            | 
           3627 | 
                           'sort' => "ul.timeaccess",
  | 
        
        
            | 
            | 
           3628 | 
                           'expectedcourses' => ['ainprogress', 'binprogress', 'cinprogress', 'dinprogress', 'einprogress'],
  | 
        
        
            | 
            | 
           3629 | 
                           'expectednextoffset' => 15,
  | 
        
        
            | 
            | 
           3630 | 
                       ],
  | 
        
        
            | 
            | 
           3631 | 
                       'all limit and offset with valid field name and no prefix, test for ul' => [
  | 
        
        
            | 
            | 
           3632 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3633 | 
                           'classification' => 'inprogress',
  | 
        
        
            | 
            | 
           3634 | 
                           'limit' => 0,
  | 
        
        
            | 
            | 
           3635 | 
                           'offset' => 0,
  | 
        
        
            | 
            | 
           3636 | 
                           'sort' => "timeaccess",
  | 
        
        
            | 
            | 
           3637 | 
                           'expectedcourses' => ['ainprogress', 'binprogress', 'cinprogress', 'dinprogress', 'einprogress'],
  | 
        
        
            | 
            | 
           3638 | 
                           'expectednextoffset' => 15,
  | 
        
        
            | 
            | 
           3639 | 
                       ],
  | 
        
        
            | 
            | 
           3640 | 
                       'all limit and offset with valid field name and no prefix' => [
  | 
        
        
            | 
            | 
           3641 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3642 | 
                           'classification' => 'all',
  | 
        
        
            | 
            | 
           3643 | 
                           'limit' => 5,
  | 
        
        
            | 
            | 
           3644 | 
                           'offset' => 5,
  | 
        
        
            | 
            | 
           3645 | 
                           'sort' => "fullname",
  | 
        
        
            | 
            | 
           3646 | 
                           'expectedcourses' => ['bpast', 'cpast', 'dfuture', 'dpast', 'efuture'],
  | 
        
        
            | 
            | 
           3647 | 
                           'expectednextoffset' => 10,
  | 
        
        
            | 
            | 
           3648 | 
                       ],
  | 
        
        
            | 
            | 
           3649 | 
                       'all limit and offset with valid field name and no prefix and with sort direction' => [
  | 
        
        
            | 
            | 
           3650 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3651 | 
                           'classification' => 'all',
  | 
        
        
            | 
            | 
           3652 | 
                           'limit' => 5,
  | 
        
        
            | 
            | 
           3653 | 
                           'offset' => 5,
  | 
        
        
            | 
            | 
           3654 | 
                           'sort' => "fullname desc",
  | 
        
        
            | 
            | 
           3655 | 
                           'expectedcourses' => ['bpast', 'cpast', 'dfuture', 'dpast', 'efuture'],
  | 
        
        
            | 
            | 
           3656 | 
                           'expectednextoffset' => 10,
  | 
        
        
            | 
            | 
           3657 | 
                       ],
  | 
        
        
            | 
            | 
           3658 | 
                       'Search courses for courses containing bfut' => [
  | 
        
        
            | 
            | 
           3659 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3660 | 
                           'classification' => 'search',
  | 
        
        
            | 
            | 
           3661 | 
                           'limit' => 0,
  | 
        
        
            | 
            | 
           3662 | 
                           'offset' => 0,
  | 
        
        
            | 
            | 
           3663 | 
                           'sort' => null,
  | 
        
        
            | 
            | 
           3664 | 
                           'expectedcourses' => ['bfuture'],
  | 
        
        
            | 
            | 
           3665 | 
                           'expectednextoffset' => 1,
  | 
        
        
            | 
            | 
           3666 | 
                           'expectedexception' => null,
  | 
        
        
            | 
            | 
           3667 | 
                           'searchvalue' => 'bfut',
  | 
        
        
            | 
            | 
           3668 | 
                       ],
  | 
        
        
            | 
            | 
           3669 | 
                       'Search courses for courses containing inp' => [
  | 
        
        
            | 
            | 
           3670 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3671 | 
                           'classification' => 'search',
  | 
        
        
            | 
            | 
           3672 | 
                           'limit' => 0,
  | 
        
        
            | 
            | 
           3673 | 
                           'offset' => 0,
  | 
        
        
            | 
            | 
           3674 | 
                           'sort' => null,
  | 
        
        
            | 
            | 
           3675 | 
                           'expectedcourses' => ['ainprogress', 'binprogress', 'cinprogress', 'dinprogress', 'einprogress'],
  | 
        
        
            | 
            | 
           3676 | 
                           'expectednextoffset' => 5,
  | 
        
        
            | 
            | 
           3677 | 
                           'expectedexception' => null,
  | 
        
        
            | 
            | 
           3678 | 
                           'searchvalue' => 'inp',
  | 
        
        
            | 
            | 
           3679 | 
                       ],
  | 
        
        
            | 
            | 
           3680 | 
                       'Search courses for courses containing fail' => [
  | 
        
        
            | 
            | 
           3681 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3682 | 
                           'classification' => 'search',
  | 
        
        
            | 
            | 
           3683 | 
                           'limit' => 0,
  | 
        
        
            | 
            | 
           3684 | 
                           'offset' => 0,
  | 
        
        
            | 
            | 
           3685 | 
                           'sort' => null,
  | 
        
        
            | 
            | 
           3686 | 
                           'expectedcourses' => [],
  | 
        
        
            | 
            | 
           3687 | 
                           'expectednextoffset' => 0,
  | 
        
        
            | 
            | 
           3688 | 
                           'expectedexception' => null,
  | 
        
        
            | 
            | 
           3689 | 
                           'searchvalue' => 'fail',
  | 
        
        
            | 
            | 
           3690 | 
                       ],
  | 
        
        
            | 
            | 
           3691 | 
                       'Search courses for courses containing !`~[]C' => [
  | 
        
        
            | 
            | 
           3692 | 
                           'coursedata' => $coursedata,
  | 
        
        
            | 
            | 
           3693 | 
                           'classification' => 'search',
  | 
        
        
            | 
            | 
           3694 | 
                           'limit' => 0,
  | 
        
        
            | 
            | 
           3695 | 
                           'offset' => 0,
  | 
        
        
            | 
            | 
           3696 | 
                           'sort' => null,
  | 
        
        
            | 
            | 
           3697 | 
                           'expectedcourses' => [],
  | 
        
        
            | 
            | 
           3698 | 
                           'expectednextoffset' => 0,
  | 
        
        
            | 
            | 
           3699 | 
                           'expectedexception' => null,
  | 
        
        
            | 
            | 
           3700 | 
                           'searchvalue' => '!`~[]C',
  | 
        
        
            | 
            | 
           3701 | 
                       ],
  | 
        
        
            | 
            | 
           3702 | 
                   ];
  | 
        
        
            | 
            | 
           3703 | 
               }
  | 
        
        
            | 
            | 
           3704 | 
              | 
        
        
            | 
            | 
           3705 | 
               /**
  | 
        
        
            | 
            | 
           3706 | 
                * Test the get_enrolled_courses_by_timeline_classification function.
  | 
        
        
            | 
            | 
           3707 | 
                *
  | 
        
        
            | 
            | 
           3708 | 
                * @dataProvider get_get_enrolled_courses_by_timeline_classification_test_cases()
  | 
        
        
            | 
            | 
           3709 | 
                * @param array $coursedata Courses to create
  | 
        
        
            | 
            | 
           3710 | 
                * @param string $classification Timeline classification
  | 
        
        
            | 
            | 
           3711 | 
                * @param int $limit Maximum number of results
  | 
        
        
            | 
            | 
           3712 | 
                * @param int $offset Offset the unfiltered courses result set by this amount
  | 
        
        
            | 
            | 
           3713 | 
                * @param string $sort sort the courses
  | 
        
        
            | 
            | 
           3714 | 
                * @param array $expectedcourses Expected courses in result
  | 
        
        
            | 
            | 
           3715 | 
                * @param int $expectednextoffset Expected next offset value in result
  | 
        
        
            | 
            | 
           3716 | 
                * @param string|null $expectedexception Expected exception string
  | 
        
        
            | 
            | 
           3717 | 
                * @param string|null $searchvalue If we are searching, what do we need to look for?
  | 
        
        
            | 
            | 
           3718 | 
                */
  | 
        
        
            | 
            | 
           3719 | 
               public function test_get_enrolled_courses_by_timeline_classification(
  | 
        
        
            | 
            | 
           3720 | 
                   $coursedata,
  | 
        
        
            | 
            | 
           3721 | 
                   $classification,
  | 
        
        
            | 
            | 
           3722 | 
                   $limit,
  | 
        
        
            | 
            | 
           3723 | 
                   $offset,
  | 
        
        
            | 
            | 
           3724 | 
                   $sort,
  | 
        
        
            | 
            | 
           3725 | 
                   $expectedcourses,
  | 
        
        
            | 
            | 
           3726 | 
                   $expectednextoffset,
  | 
        
        
            | 
            | 
           3727 | 
                   $expectedexception = null,
  | 
        
        
            | 
            | 
           3728 | 
                   $searchvalue = null
  | 
        
        
           | 11 | 
           efrain | 
           3729 | 
               ): void {
  | 
        
        
           | 1 | 
           efrain | 
           3730 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           3731 | 
                   $generator = $this->getDataGenerator();
  | 
        
        
            | 
            | 
           3732 | 
              | 
        
        
            | 
            | 
           3733 | 
                   $courses = array_map(function($coursedata) use ($generator) {
  | 
        
        
            | 
            | 
           3734 | 
                       return $generator->create_course($coursedata);
  | 
        
        
            | 
            | 
           3735 | 
                   }, $coursedata);
  | 
        
        
            | 
            | 
           3736 | 
              | 
        
        
            | 
            | 
           3737 | 
                   $student = $generator->create_user();
  | 
        
        
            | 
            | 
           3738 | 
              | 
        
        
            | 
            | 
           3739 | 
                   foreach ($courses as $course) {
  | 
        
        
            | 
            | 
           3740 | 
                       $generator->enrol_user($student->id, $course->id, 'student');
  | 
        
        
            | 
            | 
           3741 | 
                   }
  | 
        
        
            | 
            | 
           3742 | 
              | 
        
        
            | 
            | 
           3743 | 
                   $this->setUser($student);
  | 
        
        
            | 
            | 
           3744 | 
              | 
        
        
            | 
            | 
           3745 | 
                   if (isset($expectedexception)) {
  | 
        
        
            | 
            | 
           3746 | 
                       $this->expectException('coding_exception');
  | 
        
        
            | 
            | 
           3747 | 
                       $this->expectExceptionMessage($expectedexception);
  | 
        
        
            | 
            | 
           3748 | 
                   }
  | 
        
        
            | 
            | 
           3749 | 
              | 
        
        
            | 
            | 
           3750 | 
                   // NOTE: The offset applies to the unfiltered full set of courses before the classification
  | 
        
        
            | 
            | 
           3751 | 
                   // filtering is done.
  | 
        
        
            | 
            | 
           3752 | 
                   // E.g. In our example if an offset of 2 is given then it would mean the first
  | 
        
        
            | 
            | 
           3753 | 
                   // two courses (afuture, ainprogress) are ignored.
  | 
        
        
            | 
            | 
           3754 | 
                   $result = core_course_external::get_enrolled_courses_by_timeline_classification(
  | 
        
        
            | 
            | 
           3755 | 
                       $classification,
  | 
        
        
            | 
            | 
           3756 | 
                       $limit,
  | 
        
        
            | 
            | 
           3757 | 
                       $offset,
  | 
        
        
            | 
            | 
           3758 | 
                       $sort,
  | 
        
        
            | 
            | 
           3759 | 
                       null,
  | 
        
        
            | 
            | 
           3760 | 
                       null,
  | 
        
        
            | 
            | 
           3761 | 
                       $searchvalue
  | 
        
        
            | 
            | 
           3762 | 
                   );
  | 
        
        
            | 
            | 
           3763 | 
                   $result = external_api::clean_returnvalue(
  | 
        
        
            | 
            | 
           3764 | 
                       core_course_external::get_enrolled_courses_by_timeline_classification_returns(),
  | 
        
        
            | 
            | 
           3765 | 
                       $result
  | 
        
        
            | 
            | 
           3766 | 
                   );
  | 
        
        
            | 
            | 
           3767 | 
              | 
        
        
            | 
            | 
           3768 | 
                   $actual = array_map(function($course) {
  | 
        
        
            | 
            | 
           3769 | 
                       return $course['shortname'];
  | 
        
        
            | 
            | 
           3770 | 
                   }, $result['courses']);
  | 
        
        
            | 
            | 
           3771 | 
              | 
        
        
            | 
            | 
           3772 | 
                   $this->assertEqualsCanonicalizing($expectedcourses, $actual);
  | 
        
        
            | 
            | 
           3773 | 
                   $this->assertEquals($expectednextoffset, $result['nextoffset']);
  | 
        
        
            | 
            | 
           3774 | 
               }
  | 
        
        
            | 
            | 
           3775 | 
              | 
        
        
            | 
            | 
           3776 | 
               /**
  | 
        
        
            | 
            | 
           3777 | 
                * Test the get_recent_courses function.
  | 
        
        
            | 
            | 
           3778 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           3779 | 
               public function test_get_recent_courses(): void {
  | 
        
        
           | 1 | 
           efrain | 
           3780 | 
                   global $USER, $DB;
  | 
        
        
            | 
            | 
           3781 | 
              | 
        
        
            | 
            | 
           3782 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           3783 | 
                   $generator = $this->getDataGenerator();
  | 
        
        
            | 
            | 
           3784 | 
              | 
        
        
            | 
            | 
           3785 | 
                   set_config('hiddenuserfields', 'lastaccess');
  | 
        
        
            | 
            | 
           3786 | 
              | 
        
        
            | 
            | 
           3787 | 
                   $courses = array();
  | 
        
        
            | 
            | 
           3788 | 
                   for ($i = 1; $i < 12; $i++) {
  | 
        
        
            | 
            | 
           3789 | 
                       $courses[]  = $generator->create_course();
  | 
        
        
            | 
            | 
           3790 | 
                   };
  | 
        
        
            | 
            | 
           3791 | 
              | 
        
        
            | 
            | 
           3792 | 
                   $student = $generator->create_user();
  | 
        
        
            | 
            | 
           3793 | 
                   $teacher = $generator->create_user();
  | 
        
        
            | 
            | 
           3794 | 
              | 
        
        
            | 
            | 
           3795 | 
                   foreach ($courses as $course) {
  | 
        
        
            | 
            | 
           3796 | 
                       $generator->enrol_user($student->id, $course->id, 'student');
  | 
        
        
            | 
            | 
           3797 | 
                   }
  | 
        
        
            | 
            | 
           3798 | 
              | 
        
        
            | 
            | 
           3799 | 
                   $generator->enrol_user($teacher->id, $courses[0]->id, 'teacher');
  | 
        
        
            | 
            | 
           3800 | 
              | 
        
        
            | 
            | 
           3801 | 
                   $this->setUser($student);
  | 
        
        
            | 
            | 
           3802 | 
              | 
        
        
            | 
            | 
           3803 | 
                   $result = core_course_external::get_recent_courses($USER->id);
  | 
        
        
            | 
            | 
           3804 | 
              | 
        
        
            | 
            | 
           3805 | 
                   // No course accessed.
  | 
        
        
            | 
            | 
           3806 | 
                   $this->assertCount(0, $result);
  | 
        
        
            | 
            | 
           3807 | 
              | 
        
        
            | 
            | 
           3808 | 
                   foreach ($courses as $course) {
  | 
        
        
            | 
            | 
           3809 | 
                       core_course_external::view_course($course->id);
  | 
        
        
            | 
            | 
           3810 | 
                   }
  | 
        
        
            | 
            | 
           3811 | 
              | 
        
        
            | 
            | 
           3812 | 
                   // Every course accessed.
  | 
        
        
            | 
            | 
           3813 | 
                   $result = core_course_external::get_recent_courses($USER->id);
  | 
        
        
            | 
            | 
           3814 | 
                   $this->assertCount( 11, $result);
  | 
        
        
            | 
            | 
           3815 | 
              | 
        
        
            | 
            | 
           3816 | 
                   // Every course accessed, result limited to 10 courses.
  | 
        
        
            | 
            | 
           3817 | 
                   $result = core_course_external::get_recent_courses($USER->id, 10);
  | 
        
        
            | 
            | 
           3818 | 
                   $this->assertCount(10, $result);
  | 
        
        
            | 
            | 
           3819 | 
              | 
        
        
            | 
            | 
           3820 | 
                   $guestcourse = $generator->create_course(
  | 
        
        
            | 
            | 
           3821 | 
                           (object)array('shortname' => 'guestcourse',
  | 
        
        
            | 
            | 
           3822 | 
                           'enrol_guest_status_0' => ENROL_INSTANCE_ENABLED,
  | 
        
        
            | 
            | 
           3823 | 
                           'enrol_guest_password_0' => ''));
  | 
        
        
            | 
            | 
           3824 | 
                   core_course_external::view_course($guestcourse->id);
  | 
        
        
            | 
            | 
           3825 | 
              | 
        
        
            | 
            | 
           3826 | 
                   // Every course accessed, even the not enrolled one.
  | 
        
        
            | 
            | 
           3827 | 
                   $result = core_course_external::get_recent_courses($USER->id);
  | 
        
        
            | 
            | 
           3828 | 
                   $this->assertCount(12, $result);
  | 
        
        
            | 
            | 
           3829 | 
              | 
        
        
            | 
            | 
           3830 | 
                   // Offset 5, return 7 out of 12.
  | 
        
        
            | 
            | 
           3831 | 
                   $result = core_course_external::get_recent_courses($USER->id, 0, 5);
  | 
        
        
            | 
            | 
           3832 | 
                   $this->assertCount(7, $result);
  | 
        
        
            | 
            | 
           3833 | 
              | 
        
        
            | 
            | 
           3834 | 
                   // Offset 5 and limit 3, return 3 out of 12.
  | 
        
        
            | 
            | 
           3835 | 
                   $result = core_course_external::get_recent_courses($USER->id, 3, 5);
  | 
        
        
            | 
            | 
           3836 | 
                   $this->assertCount(3, $result);
  | 
        
        
            | 
            | 
           3837 | 
              | 
        
        
            | 
            | 
           3838 | 
                   // Sorted by course id ASC.
  | 
        
        
            | 
            | 
           3839 | 
                   $result = core_course_external::get_recent_courses($USER->id, 0, 0, 'id ASC');
  | 
        
        
            | 
            | 
           3840 | 
                   $this->assertEquals($courses[0]->id, array_shift($result)->id);
  | 
        
        
            | 
            | 
           3841 | 
              | 
        
        
            | 
            | 
           3842 | 
                   // Sorted by course id DESC.
  | 
        
        
            | 
            | 
           3843 | 
                   $result = core_course_external::get_recent_courses($USER->id, 0, 0, 'id DESC');
  | 
        
        
            | 
            | 
           3844 | 
                   $this->assertEquals($guestcourse->id, array_shift($result)->id);
  | 
        
        
            | 
            | 
           3845 | 
              | 
        
        
            | 
            | 
           3846 | 
                   // If last access is hidden, only get the courses where has viewhiddenuserfields capability.
  | 
        
        
            | 
            | 
           3847 | 
                   $this->setUser($teacher);
  | 
        
        
            | 
            | 
           3848 | 
                   $teacherroleid = $DB->get_field('role', 'id', array('shortname' => 'editingteacher'));
  | 
        
        
            | 
            | 
           3849 | 
                   $usercontext = context_user::instance($student->id);
  | 
        
        
            | 
            | 
           3850 | 
                   $this->assignUserCapability('moodle/user:viewdetails', $usercontext, $teacherroleid);
  | 
        
        
            | 
            | 
           3851 | 
              | 
        
        
            | 
            | 
           3852 | 
                   // Sorted by course id DESC.
  | 
        
        
            | 
            | 
           3853 | 
                   $result = core_course_external::get_recent_courses($student->id);
  | 
        
        
            | 
            | 
           3854 | 
                   $this->assertCount(1, $result);
  | 
        
        
            | 
            | 
           3855 | 
                   $this->assertEquals($courses[0]->id, array_shift($result)->id);
  | 
        
        
            | 
            | 
           3856 | 
               }
  | 
        
        
            | 
            | 
           3857 | 
              | 
        
        
            | 
            | 
           3858 | 
               /**
  | 
        
        
            | 
            | 
           3859 | 
                * Test get enrolled users by cmid function.
  | 
        
        
            | 
            | 
           3860 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           3861 | 
               public function test_get_enrolled_users_by_cmid(): void {
  | 
        
        
           | 1 | 
           efrain | 
           3862 | 
                   global $PAGE;
  | 
        
        
            | 
            | 
           3863 | 
                   $this->resetAfterTest(true);
  | 
        
        
            | 
            | 
           3864 | 
              | 
        
        
            | 
            | 
           3865 | 
                   $user1 = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           3866 | 
                   $user2 = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           3867 | 
                   $user3 = self::getDataGenerator()->create_user();
  | 
        
        
            | 
            | 
           3868 | 
              | 
        
        
            | 
            | 
           3869 | 
                   $user1picture = new user_picture($user1);
  | 
        
        
            | 
            | 
           3870 | 
                   $user1picture->size = 1;
  | 
        
        
            | 
            | 
           3871 | 
                   $user1->profileimage = $user1picture->get_url($PAGE)->out(false);
  | 
        
        
            | 
            | 
           3872 | 
              | 
        
        
            | 
            | 
           3873 | 
                   $user2picture = new user_picture($user2);
  | 
        
        
            | 
            | 
           3874 | 
                   $user2picture->size = 1;
  | 
        
        
            | 
            | 
           3875 | 
                   $user2->profileimage = $user2picture->get_url($PAGE)->out(false);
  | 
        
        
            | 
            | 
           3876 | 
              | 
        
        
            | 
            | 
           3877 | 
                   $user3picture = new user_picture($user3);
  | 
        
        
            | 
            | 
           3878 | 
                   $user3picture->size = 1;
  | 
        
        
            | 
            | 
           3879 | 
                   $user3->profileimage = $user3picture->get_url($PAGE)->out(false);
  | 
        
        
            | 
            | 
           3880 | 
              | 
        
        
            | 
            | 
           3881 | 
                   // Set the first created user to the test user.
  | 
        
        
            | 
            | 
           3882 | 
                   self::setUser($user1);
  | 
        
        
            | 
            | 
           3883 | 
              | 
        
        
            | 
            | 
           3884 | 
                   // Create course to add the module.
  | 
        
        
            | 
            | 
           3885 | 
                   $course1 = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           3886 | 
              | 
        
        
            | 
            | 
           3887 | 
                   // Forum with tracking off.
  | 
        
        
            | 
            | 
           3888 | 
                   $record = new stdClass();
  | 
        
        
            | 
            | 
           3889 | 
                   $record->course = $course1->id;
  | 
        
        
            | 
            | 
           3890 | 
                   $forum1 = self::getDataGenerator()->create_module('forum', $record);
  | 
        
        
            | 
            | 
           3891 | 
              | 
        
        
            | 
            | 
           3892 | 
                   // Following lines enrol and assign default role id to the users.
  | 
        
        
            | 
            | 
           3893 | 
                   $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
  | 
        
        
            | 
            | 
           3894 | 
                   $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
  | 
        
        
            | 
            | 
           3895 | 
                   // Enrol a suspended user in the course.
  | 
        
        
            | 
            | 
           3896 | 
                   $this->getDataGenerator()->enrol_user($user3->id, $course1->id, null, 'manual', 0, 0, ENROL_USER_SUSPENDED);
  | 
        
        
            | 
            | 
           3897 | 
              | 
        
        
            | 
            | 
           3898 | 
                   // Create what we expect to be returned when querying the course module.
  | 
        
        
            | 
            | 
           3899 | 
                   $expectedusers = array(
  | 
        
        
            | 
            | 
           3900 | 
                       'users' => array(),
  | 
        
        
            | 
            | 
           3901 | 
                       'warnings' => array(),
  | 
        
        
            | 
            | 
           3902 | 
                   );
  | 
        
        
            | 
            | 
           3903 | 
              | 
        
        
            | 
            | 
           3904 | 
                   $expectedusers['users'][0] = [
  | 
        
        
            | 
            | 
           3905 | 
                       'id' => $user1->id,
  | 
        
        
            | 
            | 
           3906 | 
                       'fullname' => fullname($user1),
  | 
        
        
            | 
            | 
           3907 | 
                       'firstname' => $user1->firstname,
  | 
        
        
            | 
            | 
           3908 | 
                       'lastname' => $user1->lastname,
  | 
        
        
            | 
            | 
           3909 | 
                       'profileimage' => $user1->profileimage,
  | 
        
        
            | 
            | 
           3910 | 
                   ];
  | 
        
        
            | 
            | 
           3911 | 
                   $expectedusers['users'][1] = [
  | 
        
        
            | 
            | 
           3912 | 
                       'id' => $user2->id,
  | 
        
        
            | 
            | 
           3913 | 
                       'fullname' => fullname($user2),
  | 
        
        
            | 
            | 
           3914 | 
                       'firstname' => $user2->firstname,
  | 
        
        
            | 
            | 
           3915 | 
                       'lastname' => $user2->lastname,
  | 
        
        
            | 
            | 
           3916 | 
                       'profileimage' => $user2->profileimage,
  | 
        
        
            | 
            | 
           3917 | 
                   ];
  | 
        
        
            | 
            | 
           3918 | 
                   $expectedusers['users'][2] = [
  | 
        
        
            | 
            | 
           3919 | 
                       'id' => $user3->id,
  | 
        
        
            | 
            | 
           3920 | 
                       'fullname' => fullname($user3),
  | 
        
        
            | 
            | 
           3921 | 
                       'firstname' => $user3->firstname,
  | 
        
        
            | 
            | 
           3922 | 
                       'lastname' => $user3->lastname,
  | 
        
        
            | 
            | 
           3923 | 
                       'profileimage' => $user3->profileimage,
  | 
        
        
            | 
            | 
           3924 | 
                   ];
  | 
        
        
            | 
            | 
           3925 | 
              | 
        
        
            | 
            | 
           3926 | 
                   // Test getting the users in a given context.
  | 
        
        
            | 
            | 
           3927 | 
                   $users = core_course_external::get_enrolled_users_by_cmid($forum1->cmid);
  | 
        
        
            | 
            | 
           3928 | 
                   $users = external_api::clean_returnvalue(core_course_external::get_enrolled_users_by_cmid_returns(), $users);
  | 
        
        
            | 
            | 
           3929 | 
              | 
        
        
            | 
            | 
           3930 | 
                   $this->assertEquals(3, count($users['users']));
  | 
        
        
            | 
            | 
           3931 | 
                   $this->assertEquals($expectedusers, $users);
  | 
        
        
            | 
            | 
           3932 | 
              | 
        
        
            | 
            | 
           3933 | 
                   // Test getting only the active users in a given context.
  | 
        
        
            | 
            | 
           3934 | 
                   $users = core_course_external::get_enrolled_users_by_cmid($forum1->cmid, 0, true);
  | 
        
        
            | 
            | 
           3935 | 
                   $users = external_api::clean_returnvalue(core_course_external::get_enrolled_users_by_cmid_returns(), $users);
  | 
        
        
            | 
            | 
           3936 | 
              | 
        
        
            | 
            | 
           3937 | 
                   $expectedusers['users'] = [
  | 
        
        
            | 
            | 
           3938 | 
                       [
  | 
        
        
            | 
            | 
           3939 | 
                           'id' => $user1->id,
  | 
        
        
            | 
            | 
           3940 | 
                           'fullname' => fullname($user1),
  | 
        
        
            | 
            | 
           3941 | 
                           'firstname' => $user1->firstname,
  | 
        
        
            | 
            | 
           3942 | 
                           'lastname' => $user1->lastname,
  | 
        
        
            | 
            | 
           3943 | 
                           'profileimage' => $user1->profileimage,
  | 
        
        
            | 
            | 
           3944 | 
                       ],
  | 
        
        
            | 
            | 
           3945 | 
                       [
  | 
        
        
            | 
            | 
           3946 | 
                           'id' => $user2->id,
  | 
        
        
            | 
            | 
           3947 | 
                           'fullname' => fullname($user2),
  | 
        
        
            | 
            | 
           3948 | 
                           'firstname' => $user2->firstname,
  | 
        
        
            | 
            | 
           3949 | 
                           'lastname' => $user2->lastname,
  | 
        
        
            | 
            | 
           3950 | 
                           'profileimage' => $user2->profileimage,
  | 
        
        
            | 
            | 
           3951 | 
                       ]
  | 
        
        
            | 
            | 
           3952 | 
                   ];
  | 
        
        
            | 
            | 
           3953 | 
              | 
        
        
            | 
            | 
           3954 | 
                   $this->assertEquals(2, count($users['users']));
  | 
        
        
            | 
            | 
           3955 | 
                   $this->assertEquals($expectedusers, $users);
  | 
        
        
            | 
            | 
           3956 | 
               }
  | 
        
        
            | 
            | 
           3957 | 
              | 
        
        
            | 
            | 
           3958 | 
               /**
  | 
        
        
            | 
            | 
           3959 | 
                * Verify that content items can be added to user favourites.
  | 
        
        
            | 
            | 
           3960 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           3961 | 
               public function test_add_content_item_to_user_favourites(): void {
  | 
        
        
           | 1 | 
           efrain | 
           3962 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           3963 | 
              | 
        
        
            | 
            | 
           3964 | 
                   $course = $this->getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           3965 | 
                   $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
  | 
        
        
            | 
            | 
           3966 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           3967 | 
              | 
        
        
            | 
            | 
           3968 | 
                   // Using the internal API, confirm that no items are set as favourites for the user.
  | 
        
        
            | 
            | 
           3969 | 
                   $contentitemservice = new \core_course\local\service\content_item_service(
  | 
        
        
            | 
            | 
           3970 | 
                       new \core_course\local\repository\content_item_readonly_repository()
  | 
        
        
            | 
            | 
           3971 | 
                   );
  | 
        
        
            | 
            | 
           3972 | 
                   $contentitems = $contentitemservice->get_all_content_items($user);
  | 
        
        
            | 
            | 
           3973 | 
                   $favourited = array_filter($contentitems, function($contentitem) {
  | 
        
        
            | 
            | 
           3974 | 
                       return $contentitem->favourite == true;
  | 
        
        
            | 
            | 
           3975 | 
                   });
  | 
        
        
            | 
            | 
           3976 | 
                   $this->assertCount(0, $favourited);
  | 
        
        
            | 
            | 
           3977 | 
              | 
        
        
            | 
            | 
           3978 | 
                   // Using the external API, favourite a content item for the user.
  | 
        
        
            | 
            | 
           3979 | 
                   $assign = $contentitems[array_search('assign', array_column($contentitems, 'name'))];
  | 
        
        
            | 
            | 
           3980 | 
                   $contentitem = core_course_external::add_content_item_to_user_favourites('mod_assign', $assign->id, $user->id);
  | 
        
        
            | 
            | 
           3981 | 
                   $contentitem = external_api::clean_returnvalue(core_course_external::add_content_item_to_user_favourites_returns(),
  | 
        
        
            | 
            | 
           3982 | 
                       $contentitem);
  | 
        
        
            | 
            | 
           3983 | 
              | 
        
        
            | 
            | 
           3984 | 
                   // Verify the returned item is a favourite.
  | 
        
        
            | 
            | 
           3985 | 
                   $this->assertTrue($contentitem['favourite']);
  | 
        
        
            | 
            | 
           3986 | 
              | 
        
        
            | 
            | 
           3987 | 
                   // Using the internal API, confirm we see a single favourite item.
  | 
        
        
            | 
            | 
           3988 | 
                   $contentitems = $contentitemservice->get_all_content_items($user);
  | 
        
        
            | 
            | 
           3989 | 
                   $favourited = array_values(array_filter($contentitems, function($contentitem) {
  | 
        
        
            | 
            | 
           3990 | 
                       return $contentitem->favourite == true;
  | 
        
        
            | 
            | 
           3991 | 
                   }));
  | 
        
        
            | 
            | 
           3992 | 
                   $this->assertCount(1, $favourited);
  | 
        
        
            | 
            | 
           3993 | 
                   $this->assertEquals('assign', $favourited[0]->name);
  | 
        
        
            | 
            | 
           3994 | 
               }
  | 
        
        
            | 
            | 
           3995 | 
              | 
        
        
            | 
            | 
           3996 | 
               /**
  | 
        
        
            | 
            | 
           3997 | 
                * Verify that content items can be removed from user favourites.
  | 
        
        
            | 
            | 
           3998 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           3999 | 
               public function test_remove_content_item_from_user_favourites(): void {
  | 
        
        
           | 1 | 
           efrain | 
           4000 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           4001 | 
              | 
        
        
            | 
            | 
           4002 | 
                   $course = $this->getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           4003 | 
                   $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
  | 
        
        
            | 
            | 
           4004 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           4005 | 
              | 
        
        
            | 
            | 
           4006 | 
                   // Using the internal API, set a favourite for the user.
  | 
        
        
            | 
            | 
           4007 | 
                   $contentitemservice = new \core_course\local\service\content_item_service(
  | 
        
        
            | 
            | 
           4008 | 
                       new \core_course\local\repository\content_item_readonly_repository()
  | 
        
        
            | 
            | 
           4009 | 
                   );
  | 
        
        
            | 
            | 
           4010 | 
                   $contentitems = $contentitemservice->get_all_content_items($user);
  | 
        
        
            | 
            | 
           4011 | 
                   $assign = $contentitems[array_search('assign', array_column($contentitems, 'name'))];
  | 
        
        
            | 
            | 
           4012 | 
                   $contentitemservice->add_to_user_favourites($user, $assign->componentname, $assign->id);
  | 
        
        
            | 
            | 
           4013 | 
              | 
        
        
            | 
            | 
           4014 | 
                   $contentitems = $contentitemservice->get_all_content_items($user);
  | 
        
        
            | 
            | 
           4015 | 
                   $favourited = array_filter($contentitems, function($contentitem) {
  | 
        
        
            | 
            | 
           4016 | 
                       return $contentitem->favourite == true;
  | 
        
        
            | 
            | 
           4017 | 
                   });
  | 
        
        
            | 
            | 
           4018 | 
                   $this->assertCount(1, $favourited);
  | 
        
        
            | 
            | 
           4019 | 
              | 
        
        
            | 
            | 
           4020 | 
                   // Now, verify the external API can remove the favourite.
  | 
        
        
            | 
            | 
           4021 | 
                   $contentitem = core_course_external::remove_content_item_from_user_favourites('mod_assign', $assign->id);
  | 
        
        
            | 
            | 
           4022 | 
                   $contentitem = external_api::clean_returnvalue(core_course_external::remove_content_item_from_user_favourites_returns(),
  | 
        
        
            | 
            | 
           4023 | 
                       $contentitem);
  | 
        
        
            | 
            | 
           4024 | 
              | 
        
        
            | 
            | 
           4025 | 
                   // Verify the returned item is a favourite.
  | 
        
        
            | 
            | 
           4026 | 
                   $this->assertFalse($contentitem['favourite']);
  | 
        
        
            | 
            | 
           4027 | 
              | 
        
        
            | 
            | 
           4028 | 
                   // Using the internal API, confirm we see no favourite items.
  | 
        
        
            | 
            | 
           4029 | 
                   $contentitems = $contentitemservice->get_all_content_items($user);
  | 
        
        
            | 
            | 
           4030 | 
                   $favourited = array_filter($contentitems, function($contentitem) {
  | 
        
        
            | 
            | 
           4031 | 
                       return $contentitem->favourite == true;
  | 
        
        
            | 
            | 
           4032 | 
                   });
  | 
        
        
            | 
            | 
           4033 | 
                   $this->assertCount(0, $favourited);
  | 
        
        
            | 
            | 
           4034 | 
               }
  | 
        
        
            | 
            | 
           4035 | 
              | 
        
        
            | 
            | 
           4036 | 
               /**
  | 
        
        
            | 
            | 
           4037 | 
                * Test the web service returning course content items for inclusion in activity choosers, etc.
  | 
        
        
            | 
            | 
           4038 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           4039 | 
               public function test_get_course_content_items(): void {
  | 
        
        
           | 1 | 
           efrain | 
           4040 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           4041 | 
              | 
        
        
            | 
            | 
           4042 | 
                   $course  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           4043 | 
                   $user = self::getDataGenerator()->create_and_enrol($course, 'editingteacher');
  | 
        
        
            | 
            | 
           4044 | 
              | 
        
        
            | 
            | 
           4045 | 
                   // Fetch available content items as the editing teacher.
  | 
        
        
            | 
            | 
           4046 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           4047 | 
                   $result = core_course_external::get_course_content_items($course->id);
  | 
        
        
            | 
            | 
           4048 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_course_content_items_returns(), $result);
  | 
        
        
            | 
            | 
           4049 | 
              | 
        
        
            | 
            | 
           4050 | 
                   $contentitemservice = new \core_course\local\service\content_item_service(
  | 
        
        
            | 
            | 
           4051 | 
                       new \core_course\local\repository\content_item_readonly_repository()
  | 
        
        
            | 
            | 
           4052 | 
                   );
  | 
        
        
            | 
            | 
           4053 | 
              | 
        
        
            | 
            | 
           4054 | 
                   // Check if the webservice returns exactly what the service defines, albeit in array form.
  | 
        
        
            | 
            | 
           4055 | 
                   $serviceitemsasarray = array_map(function($item) {
  | 
        
        
            | 
            | 
           4056 | 
                       return (array) $item;
  | 
        
        
            | 
            | 
           4057 | 
                   }, $contentitemservice->get_content_items_for_user_in_course($user, $course));
  | 
        
        
            | 
            | 
           4058 | 
              | 
        
        
            | 
            | 
           4059 | 
                   $this->assertEquals($serviceitemsasarray, $result['content_items']);
  | 
        
        
            | 
            | 
           4060 | 
               }
  | 
        
        
            | 
            | 
           4061 | 
              | 
        
        
            | 
            | 
           4062 | 
               /**
  | 
        
        
            | 
            | 
           4063 | 
                * Test the web service returning course content items, specifically in case where the user can't manage activities.
  | 
        
        
            | 
            | 
           4064 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           4065 | 
               public function test_get_course_content_items_no_permission_to_manage(): void {
  | 
        
        
           | 1 | 
           efrain | 
           4066 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           4067 | 
              | 
        
        
            | 
            | 
           4068 | 
                   $course  = self::getDataGenerator()->create_course();
  | 
        
        
            | 
            | 
           4069 | 
                   $user = self::getDataGenerator()->create_and_enrol($course, 'student');
  | 
        
        
            | 
            | 
           4070 | 
              | 
        
        
            | 
            | 
           4071 | 
                   // Fetch available content items as a student, who won't have the permission to manage activities.
  | 
        
        
            | 
            | 
           4072 | 
                   $this->setUser($user);
  | 
        
        
            | 
            | 
           4073 | 
                   $result = core_course_external::get_course_content_items($course->id);
  | 
        
        
            | 
            | 
           4074 | 
                   $result = external_api::clean_returnvalue(core_course_external::get_course_content_items_returns(), $result);
  | 
        
        
            | 
            | 
           4075 | 
              | 
        
        
            | 
            | 
           4076 | 
                   $this->assertEmpty($result['content_items']);
  | 
        
        
            | 
            | 
           4077 | 
               }
  | 
        
        
            | 
            | 
           4078 | 
              | 
        
        
            | 
            | 
           4079 | 
               /**
  | 
        
        
            | 
            | 
           4080 | 
                * Test toggling the recommendation of an activity.
  | 
        
        
            | 
            | 
           4081 | 
                */
  | 
        
        
           | 11 | 
           efrain | 
           4082 | 
               public function test_toggle_activity_recommendation(): void {
  | 
        
        
           | 1 | 
           efrain | 
           4083 | 
                   global $CFG;
  | 
        
        
            | 
            | 
           4084 | 
              | 
        
        
            | 
            | 
           4085 | 
                   $this->resetAfterTest();
  | 
        
        
            | 
            | 
           4086 | 
              | 
        
        
            | 
            | 
           4087 | 
                   $context = context_system::instance();
  | 
        
        
            | 
            | 
           4088 | 
                   $usercontext = context_user::instance($CFG->siteguest);
  | 
        
        
            | 
            | 
           4089 | 
                   $component = 'core_course';
  | 
        
        
            | 
            | 
           4090 | 
                   $favouritefactory = \core_favourites\service_factory::get_service_for_user_context($usercontext);
  | 
        
        
            | 
            | 
           4091 | 
              | 
        
        
            | 
            | 
           4092 | 
                   $areaname = 'test_core';
  | 
        
        
            | 
            | 
           4093 | 
                   $areaid = 3;
  | 
        
        
            | 
            | 
           4094 | 
              | 
        
        
            | 
            | 
           4095 | 
                   // Test we have the favourite.
  | 
        
        
            | 
            | 
           4096 | 
                   $this->setAdminUser();
  | 
        
        
            | 
            | 
           4097 | 
                   $result = core_course_external::toggle_activity_recommendation($areaname, $areaid);
  | 
        
        
            | 
            | 
           4098 | 
                   $this->assertTrue($favouritefactory->favourite_exists($component,
  | 
        
        
            | 
            | 
           4099 | 
                           \core_course\local\service\content_item_service::RECOMMENDATION_PREFIX . $areaname, $areaid, $context));
  | 
        
        
            | 
            | 
           4100 | 
                   $this->assertTrue($result['status']);
  | 
        
        
            | 
            | 
           4101 | 
                   // Test that it is now gone.
  | 
        
        
            | 
            | 
           4102 | 
                   $result = core_course_external::toggle_activity_recommendation($areaname, $areaid);
  | 
        
        
            | 
            | 
           4103 | 
                   $this->assertFalse($favouritefactory->favourite_exists($component, $areaname, $areaid, $context));
  | 
        
        
            | 
            | 
           4104 | 
                   $this->assertFalse($result['status']);
  | 
        
        
            | 
            | 
           4105 | 
               }
  | 
        
        
            | 
            | 
           4106 | 
              | 
        
        
            | 
            | 
           4107 | 
           }
  |