Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

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

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