[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/mod/lesson/ -> lib.php (source)

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  /**
  19   * Standard library of functions and constants for lesson
  20   *
  21   * @package mod_lesson
  22   * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   **/
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  /* Do not include any libraries here! */
  29  
  30  /**
  31   * Given an object containing all the necessary data,
  32   * (defined by the form in mod_form.php) this function
  33   * will create a new instance and return the id number
  34   * of the new instance.
  35   *
  36   * @global object
  37   * @global object
  38   * @param object $lesson Lesson post data from the form
  39   * @return int
  40   **/
  41  function lesson_add_instance($data, $mform) {
  42      global $DB;
  43  
  44      $cmid = $data->coursemodule;
  45      $draftitemid = $data->mediafile;
  46      $context = context_module::instance($cmid);
  47  
  48      lesson_process_pre_save($data);
  49  
  50      unset($data->mediafile);
  51      $lessonid = $DB->insert_record("lesson", $data);
  52      $data->id = $lessonid;
  53  
  54      $lesson = $DB->get_record('lesson', array('id'=>$lessonid), '*', MUST_EXIST);
  55  
  56      lesson_update_media_file($lessonid, $context, $draftitemid);
  57  
  58      lesson_process_post_save($data);
  59  
  60      lesson_grade_item_update($data);
  61  
  62      return $lesson->id;
  63  }
  64  
  65  /**
  66   * Given an object containing all the necessary data,
  67   * (defined by the form in mod_form.php) this function
  68   * will update an existing instance with new data.
  69   *
  70   * @global object
  71   * @param object $lesson Lesson post data from the form
  72   * @return boolean
  73   **/
  74  function lesson_update_instance($data, $mform) {
  75      global $DB;
  76  
  77      $data->id = $data->instance;
  78      $cmid = $data->coursemodule;
  79      $draftitemid = $data->mediafile;
  80      $context = context_module::instance($cmid);
  81  
  82      lesson_process_pre_save($data);
  83  
  84      unset($data->mediafile);
  85      $DB->update_record("lesson", $data);
  86  
  87      lesson_update_media_file($data->id, $context, $draftitemid);
  88  
  89      lesson_process_post_save($data);
  90  
  91      // update grade item definition
  92      lesson_grade_item_update($data);
  93  
  94      // update grades - TODO: do it only when grading style changes
  95      lesson_update_grades($data, 0, false);
  96  
  97      return true;
  98  }
  99  
 100  
 101  /**
 102   * Given an ID of an instance of this module,
 103   * this function will permanently delete the instance
 104   * and any data that depends on it.
 105   *
 106   * @global object
 107   * @param int $id
 108   * @return bool
 109   */
 110  function lesson_delete_instance($id) {
 111      global $DB, $CFG;
 112      require_once($CFG->dirroot . '/mod/lesson/locallib.php');
 113  
 114      $lesson = $DB->get_record("lesson", array("id"=>$id), '*', MUST_EXIST);
 115      $lesson = new lesson($lesson);
 116      return $lesson->delete();
 117  }
 118  
 119  /**
 120   * Given a course object, this function will clean up anything that
 121   * would be leftover after all the instances were deleted
 122   *
 123   * @global object
 124   * @param object $course an object representing the course that is being deleted
 125   * @param boolean $feedback to specify if the process must output a summary of its work
 126   * @return boolean
 127   */
 128  function lesson_delete_course($course, $feedback=true) {
 129      return true;
 130  }
 131  
 132  /**
 133   * Return a small object with summary information about what a
 134   * user has done with a given particular instance of this module
 135   * Used for user activity reports.
 136   * $return->time = the time they did it
 137   * $return->info = a short text description
 138   *
 139   * @global object
 140   * @param object $course
 141   * @param object $user
 142   * @param object $mod
 143   * @param object $lesson
 144   * @return object
 145   */
 146  function lesson_user_outline($course, $user, $mod, $lesson) {
 147      global $CFG;
 148  
 149      require_once("$CFG->libdir/gradelib.php");
 150      $grades = grade_get_grades($course->id, 'mod', 'lesson', $lesson->id, $user->id);
 151  
 152      $return = new stdClass();
 153      if (empty($grades->items[0]->grades)) {
 154          $return->info = get_string("no")." ".get_string("attempts", "lesson");
 155      } else {
 156          $grade = reset($grades->items[0]->grades);
 157          $return->info = get_string("grade") . ': ' . $grade->str_long_grade;
 158  
 159          //datesubmitted == time created. dategraded == time modified or time overridden
 160          //if grade was last modified by the user themselves use date graded. Otherwise use date submitted
 161          //TODO: move this copied & pasted code somewhere in the grades API. See MDL-26704
 162          if ($grade->usermodified == $user->id || empty($grade->datesubmitted)) {
 163              $return->time = $grade->dategraded;
 164          } else {
 165              $return->time = $grade->datesubmitted;
 166          }
 167      }
 168      return $return;
 169  }
 170  
 171  /**
 172   * Print a detailed representation of what a  user has done with
 173   * a given particular instance of this module, for user activity reports.
 174   *
 175   * @global object
 176   * @param object $course
 177   * @param object $user
 178   * @param object $mod
 179   * @param object $lesson
 180   * @return bool
 181   */
 182  function lesson_user_complete($course, $user, $mod, $lesson) {
 183      global $DB, $OUTPUT, $CFG;
 184  
 185      require_once("$CFG->libdir/gradelib.php");
 186  
 187      $grades = grade_get_grades($course->id, 'mod', 'lesson', $lesson->id, $user->id);
 188      if (!empty($grades->items[0]->grades)) {
 189          $grade = reset($grades->items[0]->grades);
 190          echo $OUTPUT->container(get_string('grade').': '.$grade->str_long_grade);
 191          if ($grade->str_feedback) {
 192              echo $OUTPUT->container(get_string('feedback').': '.$grade->str_feedback);
 193          }
 194      }
 195  
 196      $params = array ("lessonid" => $lesson->id, "userid" => $user->id);
 197      if ($attempts = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND userid = :userid", $params,
 198                  "retry, timeseen")) {
 199          echo $OUTPUT->box_start();
 200          $table = new html_table();
 201          $table->head = array (get_string("attempt", "lesson"),  get_string("numberofpagesviewed", "lesson"),
 202              get_string("numberofcorrectanswers", "lesson"), get_string("time"));
 203          $table->width = "100%";
 204          $table->align = array ("center", "center", "center", "center");
 205          $table->size = array ("*", "*", "*", "*");
 206          $table->cellpadding = 2;
 207          $table->cellspacing = 0;
 208  
 209          $retry = 0;
 210          $npages = 0;
 211          $ncorrect = 0;
 212  
 213          foreach ($attempts as $attempt) {
 214              if ($attempt->retry == $retry) {
 215                  $npages++;
 216                  if ($attempt->correct) {
 217                      $ncorrect++;
 218                  }
 219                  $timeseen = $attempt->timeseen;
 220              } else {
 221                  $table->data[] = array($retry + 1, $npages, $ncorrect, userdate($timeseen));
 222                  $retry++;
 223                  $npages = 1;
 224                  if ($attempt->correct) {
 225                      $ncorrect = 1;
 226                  } else {
 227                      $ncorrect = 0;
 228                  }
 229              }
 230          }
 231          if ($npages) {
 232                  $table->data[] = array($retry + 1, $npages, $ncorrect, userdate($timeseen));
 233          }
 234          echo html_writer::table($table);
 235          echo $OUTPUT->box_end();
 236      }
 237  
 238      return true;
 239  }
 240  
 241  /**
 242   * Prints lesson summaries on MyMoodle Page
 243   *
 244   * Prints lesson name, due date and attempt information on
 245   * lessons that have a deadline that has not already passed
 246   * and it is available for taking.
 247   *
 248   * @global object
 249   * @global stdClass
 250   * @global object
 251   * @uses CONTEXT_MODULE
 252   * @param array $courses An array of course objects to get lesson instances from
 253   * @param array $htmlarray Store overview output array( course ID => 'lesson' => HTML output )
 254   * @return void
 255   */
 256  function lesson_print_overview($courses, &$htmlarray) {
 257      global $USER, $CFG, $DB, $OUTPUT;
 258  
 259      if (!$lessons = get_all_instances_in_courses('lesson', $courses)) {
 260          return;
 261      }
 262  
 263  /// Get Necessary Strings
 264      $strlesson       = get_string('modulename', 'lesson');
 265      $strnotattempted = get_string('nolessonattempts', 'lesson');
 266      $strattempted    = get_string('lessonattempted', 'lesson');
 267  
 268      $now = time();
 269      foreach ($lessons as $lesson) {
 270          if ($lesson->deadline != 0                                         // The lesson has a deadline
 271              and $lesson->deadline >= $now                                  // And it is before the deadline has been met
 272              and ($lesson->available == 0 or $lesson->available <= $now)) { // And the lesson is available
 273  
 274              // Lesson name
 275              if (!$lesson->visible) {
 276                  $class = ' class="dimmed"';
 277              } else {
 278                  $class = '';
 279              }
 280              $str = $OUTPUT->box("$strlesson: <a$class href=\"$CFG->wwwroot/mod/lesson/view.php?id=$lesson->coursemodule\">".
 281                               format_string($lesson->name).'</a>', 'name');
 282  
 283              // Deadline
 284              $str .= $OUTPUT->box(get_string('lessoncloseson', 'lesson', userdate($lesson->deadline)), 'info');
 285  
 286              // Attempt information
 287              if (has_capability('mod/lesson:manage', context_module::instance($lesson->coursemodule))) {
 288                  // Number of user attempts
 289                  $attempts = $DB->count_records('lesson_attempts', array('lessonid'=>$lesson->id));
 290                  $str     .= $OUTPUT->box(get_string('xattempts', 'lesson', $attempts), 'info');
 291              } else {
 292                  // Determine if the user has attempted the lesson or not
 293                  if ($DB->count_records('lesson_attempts', array('lessonid'=>$lesson->id, 'userid'=>$USER->id))) {
 294                      $str .= $OUTPUT->box($strattempted, 'info');
 295                  } else {
 296                      $str .= $OUTPUT->box($strnotattempted, 'info');
 297                  }
 298              }
 299              $str = $OUTPUT->box($str, 'lesson overview');
 300  
 301              if (empty($htmlarray[$lesson->course]['lesson'])) {
 302                  $htmlarray[$lesson->course]['lesson'] = $str;
 303              } else {
 304                  $htmlarray[$lesson->course]['lesson'] .= $str;
 305              }
 306          }
 307      }
 308  }
 309  
 310  /**
 311   * Function to be run periodically according to the moodle cron
 312   * This function searches for things that need to be done, such
 313   * as sending out mail, toggling flags etc ...
 314   * @global stdClass
 315   * @return bool true
 316   */
 317  function lesson_cron () {
 318      global $CFG;
 319  
 320      return true;
 321  }
 322  
 323  /**
 324   * Return grade for given user or all users.
 325   *
 326   * @global stdClass
 327   * @global object
 328   * @param int $lessonid id of lesson
 329   * @param int $userid optional user id, 0 means all users
 330   * @return array array of grades, false if none
 331   */
 332  function lesson_get_user_grades($lesson, $userid=0) {
 333      global $CFG, $DB;
 334  
 335      $params = array("lessonid" => $lesson->id,"lessonid2" => $lesson->id);
 336  
 337      if (!empty($userid)) {
 338          $params["userid"] = $userid;
 339          $params["userid2"] = $userid;
 340          $user = "AND u.id = :userid";
 341          $fuser = "AND uu.id = :userid2";
 342      }
 343      else {
 344          $user="";
 345          $fuser="";
 346      }
 347  
 348      if ($lesson->retake) {
 349          if ($lesson->usemaxgrade) {
 350              $sql = "SELECT u.id, u.id AS userid, MAX(g.grade) AS rawgrade
 351                        FROM {user} u, {lesson_grades} g
 352                       WHERE u.id = g.userid AND g.lessonid = :lessonid
 353                             $user
 354                    GROUP BY u.id";
 355          } else {
 356              $sql = "SELECT u.id, u.id AS userid, AVG(g.grade) AS rawgrade
 357                        FROM {user} u, {lesson_grades} g
 358                       WHERE u.id = g.userid AND g.lessonid = :lessonid
 359                             $user
 360                    GROUP BY u.id";
 361          }
 362          unset($params['lessonid2']);
 363          unset($params['userid2']);
 364      } else {
 365          // use only first attempts (with lowest id in lesson_grades table)
 366          $firstonly = "SELECT uu.id AS userid, MIN(gg.id) AS firstcompleted
 367                          FROM {user} uu, {lesson_grades} gg
 368                         WHERE uu.id = gg.userid AND gg.lessonid = :lessonid2
 369                               $fuser
 370                         GROUP BY uu.id";
 371  
 372          $sql = "SELECT u.id, u.id AS userid, g.grade AS rawgrade
 373                    FROM {user} u, {lesson_grades} g, ($firstonly) f
 374                   WHERE u.id = g.userid AND g.lessonid = :lessonid
 375                         AND g.id = f.firstcompleted AND g.userid=f.userid
 376                         $user";
 377      }
 378  
 379      return $DB->get_records_sql($sql, $params);
 380  }
 381  
 382  /**
 383   * Update grades in central gradebook
 384   *
 385   * @category grade
 386   * @param object $lesson
 387   * @param int $userid specific user only, 0 means all
 388   * @param bool $nullifnone
 389   */
 390  function lesson_update_grades($lesson, $userid=0, $nullifnone=true) {
 391      global $CFG, $DB;
 392      require_once($CFG->libdir.'/gradelib.php');
 393  
 394      if ($lesson->grade == 0) {
 395          lesson_grade_item_update($lesson);
 396  
 397      } else if ($grades = lesson_get_user_grades($lesson, $userid)) {
 398          lesson_grade_item_update($lesson, $grades);
 399  
 400      } else if ($userid and $nullifnone) {
 401          $grade = new stdClass();
 402          $grade->userid   = $userid;
 403          $grade->rawgrade = null;
 404          lesson_grade_item_update($lesson, $grade);
 405  
 406      } else {
 407          lesson_grade_item_update($lesson);
 408      }
 409  }
 410  
 411  /**
 412   * Create grade item for given lesson
 413   *
 414   * @category grade
 415   * @uses GRADE_TYPE_VALUE
 416   * @uses GRADE_TYPE_NONE
 417   * @param object $lesson object with extra cmidnumber
 418   * @param array|object $grades optional array/object of grade(s); 'reset' means reset grades in gradebook
 419   * @return int 0 if ok, error code otherwise
 420   */
 421  function lesson_grade_item_update($lesson, $grades=null) {
 422      global $CFG;
 423      if (!function_exists('grade_update')) { //workaround for buggy PHP versions
 424          require_once($CFG->libdir.'/gradelib.php');
 425      }
 426  
 427      if (array_key_exists('cmidnumber', $lesson)) { //it may not be always present
 428          $params = array('itemname'=>$lesson->name, 'idnumber'=>$lesson->cmidnumber);
 429      } else {
 430          $params = array('itemname'=>$lesson->name);
 431      }
 432  
 433      if ($lesson->grade > 0) {
 434          $params['gradetype']  = GRADE_TYPE_VALUE;
 435          $params['grademax']   = $lesson->grade;
 436          $params['grademin']   = 0;
 437      } else if ($lesson->grade < 0) {
 438          $params['gradetype']  = GRADE_TYPE_SCALE;
 439          $params['scaleid']   = -$lesson->grade;
 440  
 441          // Make sure current grade fetched correctly from $grades
 442          $currentgrade = null;
 443          if (!empty($grades)) {
 444              if (is_array($grades)) {
 445                  $currentgrade = reset($grades);
 446              } else {
 447                  $currentgrade = $grades;
 448              }
 449          }
 450  
 451          // When converting a score to a scale, use scale's grade maximum to calculate it.
 452          if (!empty($currentgrade) && $currentgrade->rawgrade !== null) {
 453              $grade = grade_get_grades($lesson->course, 'mod', 'lesson', $lesson->id, $currentgrade->userid);
 454              $params['grademax']   = reset($grade->items)->grademax;
 455          }
 456      } else {
 457          $params['gradetype']  = GRADE_TYPE_NONE;
 458      }
 459  
 460      if ($grades  === 'reset') {
 461          $params['reset'] = true;
 462          $grades = null;
 463      } else if (!empty($grades)) {
 464          // Need to calculate raw grade (Note: $grades has many forms)
 465          if (is_object($grades)) {
 466              $grades = array($grades->userid => $grades);
 467          } else if (array_key_exists('userid', $grades)) {
 468              $grades = array($grades['userid'] => $grades);
 469          }
 470          foreach ($grades as $key => $grade) {
 471              if (!is_array($grade)) {
 472                  $grades[$key] = $grade = (array) $grade;
 473              }
 474              //check raw grade isnt null otherwise we erroneously insert a grade of 0
 475              if ($grade['rawgrade'] !== null) {
 476                  $grades[$key]['rawgrade'] = ($grade['rawgrade'] * $params['grademax'] / 100);
 477              } else {
 478                  //setting rawgrade to null just in case user is deleting a grade
 479                  $grades[$key]['rawgrade'] = null;
 480              }
 481          }
 482      }
 483  
 484      return grade_update('mod/lesson', $lesson->course, 'mod', 'lesson', $lesson->id, 0, $grades, $params);
 485  }
 486  
 487  /**
 488   * Delete grade item for given lesson
 489   *
 490   * @category grade
 491   * @param object $lesson object
 492   * @return object lesson
 493   */
 494  function lesson_grade_item_delete($lesson) {
 495      global $CFG;
 496  
 497  }
 498  
 499  /**
 500   * List the actions that correspond to a view of this module.
 501   * This is used by the participation report.
 502   *
 503   * Note: This is not used by new logging system. Event with
 504   *       crud = 'r' and edulevel = LEVEL_PARTICIPATING will
 505   *       be considered as view action.
 506   *
 507   * @return array
 508   */
 509  function lesson_get_view_actions() {
 510      return array('view','view all');
 511  }
 512  
 513  /**
 514   * List the actions that correspond to a post of this module.
 515   * This is used by the participation report.
 516   *
 517   * Note: This is not used by new logging system. Event with
 518   *       crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING
 519   *       will be considered as post action.
 520   *
 521   * @return array
 522   */
 523  function lesson_get_post_actions() {
 524      return array('end','start');
 525  }
 526  
 527  /**
 528   * Runs any processes that must run before
 529   * a lesson insert/update
 530   *
 531   * @global object
 532   * @param object $lesson Lesson form data
 533   * @return void
 534   **/
 535  function lesson_process_pre_save(&$lesson) {
 536      global $DB;
 537  
 538      $lesson->timemodified = time();
 539  
 540      if (empty($lesson->timed)) {
 541          $lesson->timed = 0;
 542      }
 543      if (empty($lesson->timespent) or !is_numeric($lesson->timespent) or $lesson->timespent < 0) {
 544          $lesson->timespent = 0;
 545      }
 546      if (!isset($lesson->completed)) {
 547          $lesson->completed = 0;
 548      }
 549      if (empty($lesson->gradebetterthan) or !is_numeric($lesson->gradebetterthan) or $lesson->gradebetterthan < 0) {
 550          $lesson->gradebetterthan = 0;
 551      } else if ($lesson->gradebetterthan > 100) {
 552          $lesson->gradebetterthan = 100;
 553      }
 554  
 555      if (empty($lesson->width)) {
 556          $lesson->width = 640;
 557      }
 558      if (empty($lesson->height)) {
 559          $lesson->height = 480;
 560      }
 561      if (empty($lesson->bgcolor)) {
 562          $lesson->bgcolor = '#FFFFFF';
 563      }
 564  
 565      // Conditions for dependency
 566      $conditions = new stdClass;
 567      $conditions->timespent = $lesson->timespent;
 568      $conditions->completed = $lesson->completed;
 569      $conditions->gradebetterthan = $lesson->gradebetterthan;
 570      $lesson->conditions = serialize($conditions);
 571      unset($lesson->timespent);
 572      unset($lesson->completed);
 573      unset($lesson->gradebetterthan);
 574  
 575      if (empty($lesson->password)) {
 576          unset($lesson->password);
 577      }
 578  }
 579  
 580  /**
 581   * Runs any processes that must be run
 582   * after a lesson insert/update
 583   *
 584   * @global object
 585   * @param object $lesson Lesson form data
 586   * @return void
 587   **/
 588  function lesson_process_post_save(&$lesson) {
 589      global $DB, $CFG;
 590      require_once($CFG->dirroot.'/calendar/lib.php');
 591      require_once($CFG->dirroot . '/mod/lesson/locallib.php');
 592  
 593      if ($events = $DB->get_records('event', array('modulename'=>'lesson', 'instance'=>$lesson->id))) {
 594          foreach($events as $event) {
 595              $event = calendar_event::load($event->id);
 596              $event->delete();
 597          }
 598      }
 599  
 600      $event = new stdClass;
 601      $event->description = $lesson->name;
 602      $event->courseid    = $lesson->course;
 603      $event->groupid     = 0;
 604      $event->userid      = 0;
 605      $event->modulename  = 'lesson';
 606      $event->instance    = $lesson->id;
 607      $event->eventtype   = 'open';
 608      $event->timestart   = $lesson->available;
 609  
 610      $event->visible     = instance_is_visible('lesson', $lesson);
 611  
 612      $event->timeduration = ($lesson->deadline - $lesson->available);
 613  
 614      if ($lesson->deadline and $lesson->available and $event->timeduration <= LESSON_MAX_EVENT_LENGTH) {
 615          // Single event for the whole lesson.
 616          $event->name = $lesson->name;
 617          calendar_event::create(clone($event));
 618      } else {
 619          // Separate start and end events.
 620          $event->timeduration  = 0;
 621          if ($lesson->available) {
 622              $event->name = $lesson->name.' ('.get_string('lessonopens', 'lesson').')';
 623              calendar_event::create(clone($event));
 624          }
 625  
 626          if ($lesson->deadline) {
 627              $event->name      = $lesson->name.' ('.get_string('lessoncloses', 'lesson').')';
 628              $event->timestart = $lesson->deadline;
 629              $event->eventtype = 'close';
 630              calendar_event::create(clone($event));
 631          }
 632      }
 633  }
 634  
 635  
 636  /**
 637   * Implementation of the function for printing the form elements that control
 638   * whether the course reset functionality affects the lesson.
 639   *
 640   * @param $mform form passed by reference
 641   */
 642  function lesson_reset_course_form_definition(&$mform) {
 643      $mform->addElement('header', 'lessonheader', get_string('modulenameplural', 'lesson'));
 644      $mform->addElement('advcheckbox', 'reset_lesson', get_string('deleteallattempts','lesson'));
 645  }
 646  
 647  /**
 648   * Course reset form defaults.
 649   * @param object $course
 650   * @return array
 651   */
 652  function lesson_reset_course_form_defaults($course) {
 653      return array('reset_lesson'=>1);
 654  }
 655  
 656  /**
 657   * Removes all grades from gradebook
 658   *
 659   * @global stdClass
 660   * @global object
 661   * @param int $courseid
 662   * @param string optional type
 663   */
 664  function lesson_reset_gradebook($courseid, $type='') {
 665      global $CFG, $DB;
 666  
 667      $sql = "SELECT l.*, cm.idnumber as cmidnumber, l.course as courseid
 668                FROM {lesson} l, {course_modules} cm, {modules} m
 669               WHERE m.name='lesson' AND m.id=cm.module AND cm.instance=l.id AND l.course=:course";
 670      $params = array ("course" => $courseid);
 671      if ($lessons = $DB->get_records_sql($sql,$params)) {
 672          foreach ($lessons as $lesson) {
 673              lesson_grade_item_update($lesson, 'reset');
 674          }
 675      }
 676  }
 677  
 678  /**
 679   * Actual implementation of the reset course functionality, delete all the
 680   * lesson attempts for course $data->courseid.
 681   *
 682   * @global stdClass
 683   * @global object
 684   * @param object $data the data submitted from the reset course.
 685   * @return array status array
 686   */
 687  function lesson_reset_userdata($data) {
 688      global $CFG, $DB;
 689  
 690      $componentstr = get_string('modulenameplural', 'lesson');
 691      $status = array();
 692  
 693      if (!empty($data->reset_lesson)) {
 694          $lessonssql = "SELECT l.id
 695                           FROM {lesson} l
 696                          WHERE l.course=:course";
 697  
 698          $params = array ("course" => $data->courseid);
 699          $DB->delete_records_select('lesson_timer', "lessonid IN ($lessonssql)", $params);
 700          $DB->delete_records_select('lesson_high_scores', "lessonid IN ($lessonssql)", $params);
 701          $DB->delete_records_select('lesson_grades', "lessonid IN ($lessonssql)", $params);
 702          $DB->delete_records_select('lesson_attempts', "lessonid IN ($lessonssql)", $params);
 703  
 704          // remove all grades from gradebook
 705          if (empty($data->reset_gradebook_grades)) {
 706              lesson_reset_gradebook($data->courseid);
 707          }
 708  
 709          $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallattempts', 'lesson'), 'error'=>false);
 710      }
 711  
 712      /// updating dates - shift may be negative too
 713      if ($data->timeshift) {
 714          shift_course_mod_dates('lesson', array('available', 'deadline'), $data->timeshift, $data->courseid);
 715          $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged'), 'error'=>false);
 716      }
 717  
 718      return $status;
 719  }
 720  
 721  /**
 722   * Returns all other caps used in module
 723   * @return array
 724   */
 725  function lesson_get_extra_capabilities() {
 726      return array('moodle/site:accessallgroups');
 727  }
 728  
 729  /**
 730   * @uses FEATURE_GROUPS
 731   * @uses FEATURE_GROUPINGS
 732   * @uses FEATURE_MOD_INTRO
 733   * @uses FEATURE_COMPLETION_TRACKS_VIEWS
 734   * @uses FEATURE_GRADE_HAS_GRADE
 735   * @uses FEATURE_GRADE_OUTCOMES
 736   * @param string $feature FEATURE_xx constant for requested feature
 737   * @return mixed True if module supports feature, false if not, null if doesn't know
 738   */
 739  function lesson_supports($feature) {
 740      switch($feature) {
 741          case FEATURE_GROUPS:
 742              return false;
 743          case FEATURE_GROUPINGS:
 744              return false;
 745          case FEATURE_GROUPMEMBERSONLY:
 746              return true;
 747          case FEATURE_MOD_INTRO:
 748              return true;
 749          case FEATURE_COMPLETION_TRACKS_VIEWS:
 750              return true;
 751          case FEATURE_GRADE_HAS_GRADE:
 752              return true;
 753          case FEATURE_GRADE_OUTCOMES:
 754              return true;
 755          case FEATURE_BACKUP_MOODLE2:
 756              return true;
 757          case FEATURE_SHOW_DESCRIPTION:
 758              return true;
 759          default:
 760              return null;
 761      }
 762  }
 763  
 764  /**
 765   * This function extends the settings navigation block for the site.
 766   *
 767   * It is safe to rely on PAGE here as we will only ever be within the module
 768   * context when this is called
 769   *
 770   * @param settings_navigation $settings
 771   * @param navigation_node $lessonnode
 772   */
 773  function lesson_extend_settings_navigation($settings, $lessonnode) {
 774      global $PAGE, $DB;
 775  
 776      $url = new moodle_url('/mod/lesson/view.php', array('id'=>$PAGE->cm->id));
 777      $lessonnode->add(get_string('preview', 'lesson'), $url);
 778  
 779      if (has_capability('mod/lesson:edit', $PAGE->cm->context)) {
 780          $url = new moodle_url('/mod/lesson/edit.php', array('id'=>$PAGE->cm->id));
 781          $lessonnode->add(get_string('edit', 'lesson'), $url);
 782      }
 783  
 784      if (has_capability('mod/lesson:manage', $PAGE->cm->context)) {
 785          $reportsnode = $lessonnode->add(get_string('reports', 'lesson'));
 786          $url = new moodle_url('/mod/lesson/report.php', array('id'=>$PAGE->cm->id, 'action'=>'reportoverview'));
 787          $reportsnode->add(get_string('overview', 'lesson'), $url);
 788          $url = new moodle_url('/mod/lesson/report.php', array('id'=>$PAGE->cm->id, 'action'=>'reportdetail'));
 789          $reportsnode->add(get_string('detailedstats', 'lesson'), $url);
 790      }
 791  
 792      if (has_capability('mod/lesson:grade', $PAGE->cm->context)) {
 793          $url = new moodle_url('/mod/lesson/essay.php', array('id'=>$PAGE->cm->id));
 794          $lessonnode->add(get_string('manualgrading', 'lesson'), $url);
 795      }
 796  
 797      if ($PAGE->activityrecord->highscores) {
 798          $url = new moodle_url('/mod/lesson/highscores.php', array('id'=>$PAGE->cm->id));
 799          $lessonnode->add(get_string('highscores', 'lesson'), $url);
 800      }
 801  }
 802  
 803  /**
 804   * Get list of available import or export formats
 805   *
 806   * Copied and modified from lib/questionlib.php
 807   *
 808   * @param string $type 'import' if import list, otherwise export list assumed
 809   * @return array sorted list of import/export formats available
 810   */
 811  function lesson_get_import_export_formats($type) {
 812      global $CFG;
 813      $fileformats = core_component::get_plugin_list("qformat");
 814  
 815      $fileformatname=array();
 816      foreach ($fileformats as $fileformat=>$fdir) {
 817          $format_file = "$fdir/format.php";
 818          if (file_exists($format_file) ) {
 819              require_once($format_file);
 820          } else {
 821              continue;
 822          }
 823          $classname = "qformat_$fileformat";
 824          $format_class = new $classname();
 825          if ($type=='import') {
 826              $provided = $format_class->provide_import();
 827          } else {
 828              $provided = $format_class->provide_export();
 829          }
 830          if ($provided) {
 831              $fileformatnames[$fileformat] = get_string('pluginname', 'qformat_'.$fileformat);
 832          }
 833      }
 834      natcasesort($fileformatnames);
 835  
 836      return $fileformatnames;
 837  }
 838  
 839  /**
 840   * Serves the lesson attachments. Implements needed access control ;-)
 841   *
 842   * @package mod_lesson
 843   * @category files
 844   * @param stdClass $course course object
 845   * @param stdClass $cm course module object
 846   * @param stdClass $context context object
 847   * @param string $filearea file area
 848   * @param array $args extra arguments
 849   * @param bool $forcedownload whether or not force download
 850   * @param array $options additional options affecting the file serving
 851   * @return bool false if file not found, does not return if found - justsend the file
 852   */
 853  function lesson_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
 854      global $CFG, $DB;
 855  
 856      if ($context->contextlevel != CONTEXT_MODULE) {
 857          return false;
 858      }
 859  
 860      $fileareas = lesson_get_file_areas();
 861      if (!array_key_exists($filearea, $fileareas)) {
 862          return false;
 863      }
 864  
 865      if (!$lesson = $DB->get_record('lesson', array('id'=>$cm->instance))) {
 866          return false;
 867      }
 868  
 869      require_course_login($course, true, $cm);
 870  
 871      if ($filearea === 'page_contents') {
 872          $pageid = (int)array_shift($args);
 873          if (!$page = $DB->get_record('lesson_pages', array('id'=>$pageid))) {
 874              return false;
 875          }
 876          $fullpath = "/$context->id/mod_lesson/$filearea/$pageid/".implode('/', $args);
 877  
 878      } else if ($filearea === 'page_answers' || $filearea === 'page_responses') {
 879          $itemid = (int)array_shift($args);
 880          if (!$pageanswers = $DB->get_record('lesson_answers', array('id' => $itemid))) {
 881              return false;
 882          }
 883          $fullpath = "/$context->id/mod_lesson/$filearea/$itemid/".implode('/', $args);
 884  
 885      } else if ($filearea === 'mediafile') {
 886          if (count($args) > 1) {
 887              // Remove the itemid when it appears to be part of the arguments. If there is only one argument
 888              // then it is surely the file name. The itemid is sometimes used to prevent browser caching.
 889              array_shift($args);
 890          }
 891          $fullpath = "/$context->id/mod_lesson/$filearea/0/".implode('/', $args);
 892  
 893      } else {
 894          return false;
 895      }
 896  
 897      $fs = get_file_storage();
 898      if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
 899          return false;
 900      }
 901  
 902      // finally send the file
 903      send_stored_file($file, 0, 0, $forcedownload, $options); // download MUST be forced - security!
 904  }
 905  
 906  /**
 907   * Returns an array of file areas
 908   *
 909   * @package  mod_lesson
 910   * @category files
 911   * @return array a list of available file areas
 912   */
 913  function lesson_get_file_areas() {
 914      $areas = array();
 915      $areas['page_contents'] = get_string('pagecontents', 'mod_lesson');
 916      $areas['mediafile'] = get_string('mediafile', 'mod_lesson');
 917      $areas['page_answers'] = get_string('pageanswers', 'mod_lesson');
 918      $areas['page_responses'] = get_string('pageresponses', 'mod_lesson');
 919      return $areas;
 920  }
 921  
 922  /**
 923   * Returns a file_info_stored object for the file being requested here
 924   *
 925   * @package  mod_lesson
 926   * @category files
 927   * @global stdClass $CFG
 928   * @param file_browse $browser file browser instance
 929   * @param array $areas file areas
 930   * @param stdClass $course course object
 931   * @param stdClass $cm course module object
 932   * @param stdClass $context context object
 933   * @param string $filearea file area
 934   * @param int $itemid item ID
 935   * @param string $filepath file path
 936   * @param string $filename file name
 937   * @return file_info_stored
 938   */
 939  function lesson_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) {
 940      global $CFG, $DB;
 941  
 942      if (!has_capability('moodle/course:managefiles', $context)) {
 943          // No peaking here for students!
 944          return null;
 945      }
 946  
 947      // Mediafile area does not have sub directories, so let's select the default itemid to prevent
 948      // the user from selecting a directory to access the mediafile content.
 949      if ($filearea == 'mediafile' && is_null($itemid)) {
 950          $itemid = 0;
 951      }
 952  
 953      if (is_null($itemid)) {
 954          return new mod_lesson_file_info($browser, $course, $cm, $context, $areas, $filearea);
 955      }
 956  
 957      $fs = get_file_storage();
 958      $filepath = is_null($filepath) ? '/' : $filepath;
 959      $filename = is_null($filename) ? '.' : $filename;
 960      if (!$storedfile = $fs->get_file($context->id, 'mod_lesson', $filearea, $itemid, $filepath, $filename)) {
 961          return null;
 962      }
 963  
 964      $itemname = $filearea;
 965      if ($filearea == 'page_contents') {
 966          $itemname = $DB->get_field('lesson_pages', 'title', array('lessonid' => $cm->instance, 'id' => $itemid));
 967          $itemname = format_string($itemname, true, array('context' => $context));
 968      } else {
 969          $areas = lesson_get_file_areas();
 970          if (isset($areas[$filearea])) {
 971              $itemname = $areas[$filearea];
 972          }
 973      }
 974  
 975      $urlbase = $CFG->wwwroot . '/pluginfile.php';
 976      return new file_info_stored($browser, $context, $storedfile, $urlbase, $itemname, $itemid, true, true, false);
 977  }
 978  
 979  
 980  /**
 981   * Return a list of page types
 982   * @param string $pagetype current page type
 983   * @param stdClass $parentcontext Block's parent context
 984   * @param stdClass $currentcontext Current context of block
 985   */
 986  function lesson_page_type_list($pagetype, $parentcontext, $currentcontext) {
 987      $module_pagetype = array(
 988          'mod-lesson-*'=>get_string('page-mod-lesson-x', 'lesson'),
 989          'mod-lesson-view'=>get_string('page-mod-lesson-view', 'lesson'),
 990          'mod-lesson-edit'=>get_string('page-mod-lesson-edit', 'lesson'));
 991      return $module_pagetype;
 992  }
 993  
 994  /**
 995   * Update the lesson activity to include any file
 996   * that was uploaded, or if there is none, set the
 997   * mediafile field to blank.
 998   *
 999   * @param int $lessonid the lesson id
1000   * @param stdClass $context the context
1001   * @param int $draftitemid the draft item
1002   */
1003  function lesson_update_media_file($lessonid, $context, $draftitemid) {
1004      global $DB;
1005  
1006      // Set the filestorage object.
1007      $fs = get_file_storage();
1008      // Save the file if it exists that is currently in the draft area.
1009      file_save_draft_area_files($draftitemid, $context->id, 'mod_lesson', 'mediafile', 0);
1010      // Get the file if it exists.
1011      $files = $fs->get_area_files($context->id, 'mod_lesson', 'mediafile', 0, 'itemid, filepath, filename', false);
1012      // Check that there is a file to process.
1013      if (count($files) == 1) {
1014          // Get the first (and only) file.
1015          $file = reset($files);
1016          // Set the mediafile column in the lessons table.
1017          $DB->set_field('lesson', 'mediafile', '/' . $file->get_filename(), array('id' => $lessonid));
1018      } else {
1019          // Set the mediafile column in the lessons table.
1020          $DB->set_field('lesson', 'mediafile', '', array('id' => $lessonid));
1021      }
1022  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1