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.
   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   * Unit tests for activities completed by classification.
  19   *
  20   * @package   core_analytics
  21   * @copyright 2017 David MonllaĆ³ {@link http://www.davidmonllao.com}
  22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  /**
  28   * Unit tests for activities completed by classification.
  29   *
  30   * @package   core_analytics
  31   * @copyright 2017 David MonllaĆ³ {@link http://www.davidmonllao.com}
  32   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  33   */
  34  class community_of_inquiry_activities_completed_by_testcase extends advanced_testcase {
  35  
  36      /**
  37       * availability_levels
  38       *
  39       * @return array
  40       */
  41      public function availability_levels() {
  42          return array(
  43              'activity' => array('activity'),
  44              'section' => array('section'),
  45          );
  46      }
  47  
  48      /**
  49       * test_get_activities_with_availability
  50       *
  51       * @dataProvider availability_levels
  52       * @param string $availabilitylevel
  53       * @return void
  54       */
  55      public function test_get_activities_with_availability($availabilitylevel) {
  56  
  57          list($course, $stu1) = $this->setup_course();
  58  
  59          // Forum1 is ignored as section 0 does not count.
  60          $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id));
  61  
  62          $modinfo = get_fast_modinfo($course, $stu1->id);
  63          $cm = $modinfo->get_cm($forum->cmid);
  64  
  65          if ($availabilitylevel === 'activity') {
  66              $availabilityinfo = new \core_availability\info_module($cm);
  67          } else if ($availabilitylevel === 'section') {
  68              $availabilityinfo = new \core_availability\info_section($cm->get_modinfo()->get_section_info($cm->sectionnum));
  69          } else {
  70              $this->fail('Unsupported availability level');
  71          }
  72  
  73          $fromtime = strtotime('2015-10-22 00:00:00 GMT');
  74          $untiltime = strtotime('2015-10-24 00:00:00 GMT');
  75          $structure = (object)array('op' => '|', 'show' => true, 'c' => array(
  76                  (object)array('type' => 'date', 'd' => '<', 't' => $untiltime),
  77                  (object)array('type' => 'date', 'd' => '>=', 't' => $fromtime)
  78          ));
  79  
  80          $method = new ReflectionMethod($availabilityinfo, 'set_in_database');
  81          $method->setAccessible(true);
  82          $method->invoke($availabilityinfo, json_encode($structure));
  83  
  84          $this->setUser($stu1);
  85  
  86          // Reset modinfo we also want coursemodinfo cache definition to be cleared.
  87          get_fast_modinfo($course, $stu1->id, true);
  88          rebuild_course_cache($course->id, true);
  89  
  90          $modinfo = get_fast_modinfo($course, $stu1->id);
  91  
  92          $cm = $modinfo->get_cm($forum->cmid);
  93  
  94          $course = new \core_analytics\course($course);
  95          list($indicator, $method) = $this->instantiate_indicator('mod_forum', $course);
  96  
  97          // Condition from after provided end time.
  98          $this->assertCount(0, $method->invoke($indicator, strtotime('2015-10-20 00:00:00 GMT'),
  99              strtotime('2015-10-21 00:00:00 GMT'), $stu1));
 100  
 101          // Condition until before provided start time
 102          $this->assertCount(0, $method->invoke($indicator, strtotime('2015-10-25 00:00:00 GMT'),
 103              strtotime('2015-10-26 00:00:00 GMT'), $stu1));
 104  
 105          // Condition until after provided end time.
 106          $this->assertCount(0, $method->invoke($indicator, strtotime('2015-10-22 00:00:00 GMT'),
 107              strtotime('2015-10-23 00:00:00 GMT'), $stu1));
 108  
 109          // Condition until after provided start time and before provided end time.
 110          $this->assertCount(1, $method->invoke($indicator, strtotime('2015-10-22 00:00:00 GMT'),
 111              strtotime('2015-10-25 00:00:00 GMT'), $stu1));
 112      }
 113  
 114      /**
 115       * test_get_activities_with_weeks
 116       *
 117       * @return void
 118       */
 119      public function test_get_activities_with_weeks() {
 120  
 121          $startdate = gmmktime('0', '0', '0', 10, 24, 2015);
 122          $record = array(
 123              'format' => 'weeks',
 124              'numsections' => 4,
 125              'startdate' => $startdate,
 126          );
 127  
 128          list($course, $stu1) = $this->setup_course($record);
 129  
 130          // Forum1 is ignored as section 0 does not count.
 131          $forum1 = $this->getDataGenerator()->create_module('forum', array('course' => $course->id),
 132              array('section' => 0));
 133          $forum2 = $this->getDataGenerator()->create_module('forum', array('course' => $course->id),
 134              array('section' => 1));
 135          $forum3 = $this->getDataGenerator()->create_module('forum', array('course' => $course->id),
 136              array('section' => 2));
 137          $forum4 = $this->getDataGenerator()->create_module('forum', array('course' => $course->id),
 138              array('section' => 4));
 139          $forum5 = $this->getDataGenerator()->create_module('forum', array('course' => $course->id),
 140              array('section' => 4));
 141  
 142          $course = new \core_analytics\course($course);
 143          list($indicator, $method) = $this->instantiate_indicator('mod_forum', $course);
 144  
 145          $this->setUser($stu1);
 146  
 147          $first = $startdate;
 148          $second = $startdate + WEEKSECS;
 149          $third = $startdate + (WEEKSECS * 2);
 150          $forth = $startdate + (WEEKSECS * 3);
 151          $this->assertCount(1, $method->invoke($indicator, $first, $first + WEEKSECS, $stu1));
 152          $this->assertCount(1, $method->invoke($indicator, $second, $second + WEEKSECS, $stu1));
 153          $this->assertCount(0, $method->invoke($indicator, $third, $third + WEEKSECS, $stu1));
 154          $this->assertCount(2, $method->invoke($indicator, $forth, $forth + WEEKSECS, $stu1));
 155      }
 156  
 157      /**
 158       * test_get_activities_by_section
 159       *
 160       * @return void
 161       */
 162      public function test_get_activities_by_section() {
 163  
 164          // This makes debugging easier, sorry WA's +8 :).
 165          $this->setTimezone('UTC');
 166  
 167          // 1 year.
 168          $startdate = gmmktime('0', '0', '0', 10, 24, 2015);
 169          $enddate = gmmktime('0', '0', '0', 10, 24, 2016);
 170          $numsections = 12;
 171          $record = array(
 172              'format' => 'topics',
 173              'numsections' => $numsections,
 174              'startdate' => $startdate,
 175              'enddate' => $enddate
 176          );
 177  
 178          list($course, $stu1) = $this->setup_course($record);
 179  
 180          // Forum1 is ignored as section 0 does not count.
 181          $forum1 = $this->getDataGenerator()->create_module('forum', array('course' => $course->id),
 182              array('section' => 0));
 183          $forum2 = $this->getDataGenerator()->create_module('forum', array('course' => $course->id),
 184              array('section' => 1));
 185          $forum3 = $this->getDataGenerator()->create_module('forum', array('course' => $course->id),
 186              array('section' => 4));
 187          $forum4 = $this->getDataGenerator()->create_module('forum', array('course' => $course->id),
 188              array('section' => 8));
 189          $forum5 = $this->getDataGenerator()->create_module('forum', array('course' => $course->id),
 190              array('section' => 10));
 191          $forum6 = $this->getDataGenerator()->create_module('forum', array('course' => $course->id),
 192              array('section' => 12));
 193  
 194          $course = new \core_analytics\course($course);
 195          list($indicator, $method) = $this->instantiate_indicator('mod_forum', $course);
 196  
 197          $this->setUser($stu1);
 198  
 199          // Split the course in quarters.
 200          $duration = ($enddate - $startdate) / 4;
 201          $first = $startdate;
 202          $second = $startdate + $duration;
 203          $third = $startdate + ($duration * 2);
 204          $forth = $startdate + ($duration * 3);
 205          $this->assertCount(1, $method->invoke($indicator, $first, $first + $duration, $stu1));
 206          $this->assertCount(1, $method->invoke($indicator, $second, $second + $duration, $stu1));
 207          $this->assertCount(1, $method->invoke($indicator, $third, $third + $duration, $stu1));
 208          $this->assertCount(2, $method->invoke($indicator, $forth, $forth + $duration, $stu1));
 209  
 210          // Split the course in as many parts as sections.
 211          $duration = ($enddate - $startdate) / $numsections;
 212          for ($i = 1; $i <= $numsections; $i++) {
 213              // The -1 because section 1 start represents the course start.
 214              $timeranges[$i] = $startdate + ($duration * ($i - 1));
 215          }
 216          $this->assertCount(1, $method->invoke($indicator, $timeranges[1], $timeranges[1] + $duration, $stu1));
 217          $this->assertCount(1, $method->invoke($indicator, $timeranges[4], $timeranges[4] + $duration, $stu1));
 218          $this->assertCount(1, $method->invoke($indicator, $timeranges[8], $timeranges[8] + $duration, $stu1));
 219          $this->assertCount(1, $method->invoke($indicator, $timeranges[10], $timeranges[10] + $duration, $stu1));
 220          $this->assertCount(1, $method->invoke($indicator, $timeranges[12], $timeranges[12] + $duration, $stu1));
 221  
 222          // Nothing here.
 223          $this->assertCount(0, $method->invoke($indicator, $timeranges[2], $timeranges[2] + $duration, $stu1));
 224          $this->assertCount(0, $method->invoke($indicator, $timeranges[3], $timeranges[3] + $duration, $stu1));
 225      }
 226  
 227      /**
 228       * test_get_activities_with_specific_restrictions
 229       *
 230       * @return void
 231       */
 232      public function test_get_activities_with_specific_restrictions() {
 233  
 234          list($course, $stu1) = $this->setup_course();
 235  
 236          $end = strtotime('2015-10-24 00:00:00 GMT');
 237  
 238          // 1 with time close, one without.
 239          $params = array('course' => $course->id);
 240          $assign1 = $this->getDataGenerator()->create_module('assign', $params);
 241          $params['duedate'] = $end;
 242          $assign2 = $this->getDataGenerator()->create_module('assign', $params);
 243  
 244          // 1 with time close, one without.
 245          $params = array('course' => $course->id);
 246          $choice1 = $this->getDataGenerator()->create_module('choice', $params);
 247          $params['timeclose'] = $end;
 248          $choice1 = $this->getDataGenerator()->create_module('choice', $params);
 249  
 250          // 1 with time close, one without.
 251          $params = array('course' => $course->id);
 252          $data1 = $this->getDataGenerator()->create_module('data', $params);
 253          $params['timeavailableto'] = $end;
 254          $data1 = $this->getDataGenerator()->create_module('data', $params);
 255  
 256          // 1 with time close, one without.
 257          $params = array('course' => $course->id);
 258          $feedback1 = $this->getDataGenerator()->create_module('feedback', $params);
 259          $params['timeclose'] = $end;
 260          $feedback1 = $this->getDataGenerator()->create_module('feedback', $params);
 261  
 262          // 1 with time close, one without.
 263          $params = array('course' => $course->id);
 264          $lesson1 = $this->getDataGenerator()->create_module('lesson', $params);
 265          $params['deadline'] = $end;
 266          $lesson1 = $this->getDataGenerator()->create_module('lesson', $params);
 267  
 268          // 1 with time close, one without.
 269          $params = array('course' => $course->id);
 270          $quiz1 = $this->getDataGenerator()->create_module('quiz', $params);
 271          $params['timeclose'] = $end;
 272          $quiz1 = $this->getDataGenerator()->create_module('quiz', $params);
 273  
 274          // 1 with time close, one without.
 275          $params = array('course' => $course->id);
 276          $scorm1 = $this->getDataGenerator()->create_module('scorm', $params);
 277          $params['timeclose'] = $end;
 278          $scorm1 = $this->getDataGenerator()->create_module('scorm', $params);
 279  
 280          // 1 with time close, one without.
 281          $params = array('course' => $course->id);
 282          $workshop1 = $this->getDataGenerator()->create_module('workshop', $params);
 283          $params['submissionend'] = $end;
 284          $workshop1 = $this->getDataGenerator()->create_module('workshop', $params);
 285  
 286          $course = new \core_analytics\course($course);
 287  
 288          $activitytypes = array('mod_assign', 'mod_choice', 'mod_data', 'mod_feedback', 'mod_lesson',
 289              'mod_quiz', 'mod_scorm', 'mod_workshop');
 290          foreach ($activitytypes as $activitytype) {
 291  
 292              list($indicator, $method) = $this->instantiate_indicator($activitytype, $course);
 293  
 294              $message = $activitytype . ' activity type returned activities do not match expected size';
 295              $this->assertCount(0, $method->invoke($indicator, strtotime('2015-10-20 00:00:00 GMT'),
 296                  strtotime('2015-10-21 00:00:00 GMT'), $stu1), $message);
 297  
 298              $this->assertCount(0, $method->invoke($indicator, strtotime('2015-10-25 00:00:00 GMT'),
 299                  strtotime('2015-10-26 00:00:00 GMT'), $stu1), $message);
 300  
 301              $this->assertCount(1, $method->invoke($indicator, strtotime('2015-10-22 00:00:00 GMT'),
 302                  strtotime('2015-10-25 00:00:00 GMT'), $stu1), $message);
 303          }
 304      }
 305  
 306      /**
 307       * setup_course
 308       *
 309       * @param stdClass $courserecord
 310       * @return array
 311       */
 312      protected function setup_course($courserecord = null) {
 313          global $CFG;
 314  
 315          $this->resetAfterTest(true);
 316  
 317          $this->setAdminUser();
 318  
 319          $CFG->enableavailability = true;
 320  
 321          $course = $this->getDataGenerator()->create_course($courserecord);
 322          $stu1 = $this->getDataGenerator()->create_user();
 323          $this->getDataGenerator()->enrol_user($stu1->id, $course->id, 'student');
 324  
 325          return array($course, $stu1);
 326      }
 327  
 328      /**
 329       * Returns the module cognitive depth indicator and the reflection method.
 330       *
 331       * @param string $modulename
 332       * @param \core_analytics\course $course
 333       * @return array
 334       */
 335      private function instantiate_indicator($modulename, \core_analytics\course $course) {
 336  
 337          $classname = '\\' . $modulename . '\analytics\indicator\cognitive_depth';
 338          $indicator = new $classname();
 339          $class = new ReflectionClass($indicator);
 340  
 341          $property = $class->getProperty('course');
 342          $property->setAccessible(true);
 343          $property->setValue($indicator, $course);
 344  
 345          $method = new ReflectionMethod($indicator, 'get_activities');
 346          $method->setAccessible(true);
 347  
 348          return array($indicator, $method);
 349      }
 350  
 351  }