Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403]

   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  namespace format_weeks;
  18  
  19  use core_external\external_api;
  20  
  21  defined('MOODLE_INTERNAL') || die();
  22  
  23  global $CFG;
  24  require_once($CFG->dirroot . '/course/lib.php');
  25  
  26  /**
  27   * format_weeks related unit tests
  28   *
  29   * @package    format_weeks
  30   * @copyright  2015 Marina Glancy
  31   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  32   */
  33  class format_weeks_test extends \advanced_testcase {
  34  
  35      /**
  36       * Tests for format_weeks::get_section_name method with default section names.
  37       */
  38      public function test_get_section_name() {
  39          global $DB;
  40          $this->resetAfterTest(true);
  41  
  42          // Generate a course with 5 sections.
  43          $generator = $this->getDataGenerator();
  44          $numsections = 5;
  45          $course = $generator->create_course(array('numsections' => $numsections, 'format' => 'weeks'),
  46              array('createsections' => true));
  47  
  48          // Get section names for course.
  49          $coursesections = $DB->get_records('course_sections', array('course' => $course->id));
  50  
  51          // Test get_section_name with default section names.
  52          $courseformat = course_get_format($course);
  53          foreach ($coursesections as $section) {
  54              // Assert that with unmodified section names, get_section_name returns the same result as get_default_section_name.
  55              $this->assertEquals($courseformat->get_default_section_name($section), $courseformat->get_section_name($section));
  56          }
  57      }
  58  
  59      /**
  60       * Tests for format_weeks::get_section_name method with modified section names.
  61       */
  62      public function test_get_section_name_customised() {
  63          global $DB;
  64          $this->resetAfterTest(true);
  65  
  66          // Generate a course with 5 sections.
  67          $generator = $this->getDataGenerator();
  68          $numsections = 5;
  69          $course = $generator->create_course(array('numsections' => $numsections, 'format' => 'weeks'),
  70              array('createsections' => true));
  71  
  72          // Get section names for course.
  73          $coursesections = $DB->get_records('course_sections', array('course' => $course->id));
  74  
  75          // Modify section names.
  76          $customname = "Custom Section";
  77          foreach ($coursesections as $section) {
  78              $section->name = "$customname $section->section";
  79              $DB->update_record('course_sections', $section);
  80          }
  81  
  82          // Requery updated section names then test get_section_name.
  83          $coursesections = $DB->get_records('course_sections', array('course' => $course->id));
  84          $courseformat = course_get_format($course);
  85          foreach ($coursesections as $section) {
  86              // Assert that with modified section names, get_section_name returns the modified section name.
  87              $this->assertEquals($section->name, $courseformat->get_section_name($section));
  88          }
  89      }
  90  
  91      /**
  92       * Tests for format_weeks::get_default_section_name.
  93       */
  94      public function test_get_default_section_name() {
  95          global $DB;
  96          $this->resetAfterTest(true);
  97  
  98          // Generate a course with 5 sections.
  99          $generator = $this->getDataGenerator();
 100          $numsections = 5;
 101          $course = $generator->create_course(array('numsections' => $numsections, 'format' => 'weeks'),
 102              array('createsections' => true));
 103  
 104          // Get section names for course.
 105          $coursesections = $DB->get_records('course_sections', array('course' => $course->id));
 106  
 107          // Test get_default_section_name with default section names.
 108          $courseformat = course_get_format($course);
 109          foreach ($coursesections as $section) {
 110              if ($section->section == 0) {
 111                  $sectionname = get_string('section0name', 'format_weeks');
 112                  $this->assertEquals($sectionname, $courseformat->get_default_section_name($section));
 113              } else {
 114                  $dates = $courseformat->get_section_dates($section);
 115                  $dates->end = ($dates->end - 86400);
 116                  $dateformat = get_string('strftimedateshort');
 117                  $weekday = userdate($dates->start, $dateformat);
 118                  $endweekday = userdate($dates->end, $dateformat);
 119                  $sectionname = $weekday.' - '.$endweekday;
 120  
 121                  $this->assertEquals($sectionname, $courseformat->get_default_section_name($section));
 122              }
 123          }
 124      }
 125  
 126      /**
 127       * Test web service updating section name
 128       */
 129      public function test_update_inplace_editable() {
 130          global $CFG, $DB, $PAGE;
 131          require_once($CFG->dirroot . '/lib/external/externallib.php');
 132  
 133          $this->resetAfterTest();
 134          $user = $this->getDataGenerator()->create_user();
 135          $this->setUser($user);
 136          $course = $this->getDataGenerator()->create_course(array('numsections' => 5, 'format' => 'weeks'),
 137              array('createsections' => true));
 138          $section = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 2));
 139  
 140          // Call webservice without necessary permissions.
 141          try {
 142              \core_external::update_inplace_editable('format_weeks', 'sectionname', $section->id, 'New section name');
 143              $this->fail('Exception expected');
 144          } catch (\moodle_exception $e) {
 145              $this->assertEquals('Course or activity not accessible. (Not enrolled)',
 146                      $e->getMessage());
 147          }
 148  
 149          // Change to teacher and make sure that section name can be updated using web service update_inplace_editable().
 150          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
 151          $this->getDataGenerator()->enrol_user($user->id, $course->id, $teacherrole->id);
 152  
 153          $res = \core_external::update_inplace_editable('format_weeks', 'sectionname', $section->id, 'New section name');
 154          $res = external_api::clean_returnvalue(\core_external::update_inplace_editable_returns(), $res);
 155          $this->assertEquals('New section name', $res['value']);
 156          $this->assertEquals('New section name', $DB->get_field('course_sections', 'name', array('id' => $section->id)));
 157      }
 158  
 159      /**
 160       * Test callback updating section name
 161       */
 162      public function test_inplace_editable() {
 163          global $CFG, $DB, $PAGE;
 164  
 165          $this->resetAfterTest();
 166          $user = $this->getDataGenerator()->create_user();
 167          $course = $this->getDataGenerator()->create_course(array('numsections' => 5, 'format' => 'weeks'),
 168              array('createsections' => true));
 169          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
 170          $this->getDataGenerator()->enrol_user($user->id, $course->id, $teacherrole->id);
 171          $this->setUser($user);
 172  
 173          $section = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 2));
 174  
 175          // Call callback format_weeks_inplace_editable() directly.
 176          $tmpl = component_callback('format_weeks', 'inplace_editable', array('sectionname', $section->id, 'Rename me again'));
 177          $this->assertInstanceOf('core\output\inplace_editable', $tmpl);
 178          $res = $tmpl->export_for_template($PAGE->get_renderer('core'));
 179          $this->assertEquals('Rename me again', $res['value']);
 180          $this->assertEquals('Rename me again', $DB->get_field('course_sections', 'name', array('id' => $section->id)));
 181  
 182          // Try updating using callback from mismatching course format.
 183          try {
 184              $tmpl = component_callback('format_topics', 'inplace_editable', array('sectionname', $section->id, 'New name'));
 185              $this->fail('Exception expected');
 186          } catch (\moodle_exception $e) {
 187              $this->assertEquals(1, preg_match('/^Can\'t find data record in database/', $e->getMessage()));
 188          }
 189      }
 190  
 191      /**
 192       * Test get_default_course_enddate.
 193       *
 194       * @return void
 195       */
 196      public function test_default_course_enddate() {
 197          global $CFG, $DB, $PAGE;
 198  
 199          $this->resetAfterTest(true);
 200  
 201          require_once($CFG->dirroot . '/course/tests/fixtures/testable_course_edit_form.php');
 202  
 203          $this->setTimezone('UTC');
 204  
 205          $params = array('format' => 'weeks', 'numsections' => 5, 'startdate' => 1445644800);
 206          $course = $this->getDataGenerator()->create_course($params);
 207          $category = $DB->get_record('course_categories', array('id' => $course->category));
 208  
 209          $args = [
 210              'course' => $course,
 211              'category' => $category,
 212              'editoroptions' => [
 213                  'context' => \context_course::instance($course->id),
 214                  'subdirs' => 0
 215              ],
 216              'returnto' => new \moodle_url('/'),
 217              'returnurl' => new \moodle_url('/'),
 218          ];
 219  
 220          $PAGE->set_course($course);
 221          $courseform = new \testable_course_edit_form(null, $args);
 222          $courseform->definition_after_data();
 223  
 224          // Calculate the expected end date.
 225          $enddate = $params['startdate'] + (WEEKSECS * $params['numsections']);
 226  
 227          $weeksformat = course_get_format($course->id);
 228          $this->assertEquals($enddate, $weeksformat->get_default_course_enddate($courseform->get_quick_form()));
 229      }
 230  
 231      /**
 232       * Test for get_view_url() to ensure that the url is only given for the correct cases
 233       */
 234      public function test_get_view_url() {
 235          global $CFG;
 236          $this->resetAfterTest();
 237  
 238          $linkcoursesections = $CFG->linkcoursesections;
 239  
 240          // Generate a course with two sections (0 and 1) and two modules.
 241          $generator = $this->getDataGenerator();
 242          $course1 = $generator->create_course(array('format' => 'weeks'));
 243          course_create_sections_if_missing($course1, array(0, 1));
 244  
 245          $data = (object)['id' => $course1->id];
 246          $format = course_get_format($course1);
 247          $format->update_course_format_options($data);
 248  
 249          // In page.
 250          $CFG->linkcoursesections = 0;
 251          $this->assertNotEmpty($format->get_view_url(null));
 252          $this->assertNotEmpty($format->get_view_url(0));
 253          $this->assertNotEmpty($format->get_view_url(1));
 254          $CFG->linkcoursesections = 1;
 255          $this->assertNotEmpty($format->get_view_url(null));
 256          $this->assertNotEmpty($format->get_view_url(0));
 257          $this->assertNotEmpty($format->get_view_url(1));
 258  
 259          // Navigation.
 260          $CFG->linkcoursesections = 0;
 261          $this->assertNull($format->get_view_url(1, ['navigation' => 1]));
 262          $this->assertNull($format->get_view_url(0, ['navigation' => 1]));
 263          $CFG->linkcoursesections = 1;
 264          $this->assertNotEmpty($format->get_view_url(1, ['navigation' => 1]));
 265          $this->assertNotEmpty($format->get_view_url(0, ['navigation' => 1]));
 266      }
 267  
 268  }