[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

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

   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   * This file contains the moodle hooks for the assign module.
  19   *
  20   * It delegates most functions to the assignment class.
  21   *
  22   * @package   mod_assign
  23   * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
  24   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   */
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  /**
  29   * Adds an assignment instance
  30   *
  31   * This is done by calling the add_instance() method of the assignment type class
  32   * @param stdClass $data
  33   * @param mod_assign_mod_form $form
  34   * @return int The instance id of the new assignment
  35   */
  36  function assign_add_instance(stdClass $data, mod_assign_mod_form $form = null) {
  37      global $CFG;
  38      require_once($CFG->dirroot . '/mod/assign/locallib.php');
  39  
  40      $assignment = new assign(context_module::instance($data->coursemodule), null, null);
  41      return $assignment->add_instance($data, true);
  42  }
  43  
  44  /**
  45   * delete an assignment instance
  46   * @param int $id
  47   * @return bool
  48   */
  49  function assign_delete_instance($id) {
  50      global $CFG;
  51      require_once($CFG->dirroot . '/mod/assign/locallib.php');
  52      $cm = get_coursemodule_from_instance('assign', $id, 0, false, MUST_EXIST);
  53      $context = context_module::instance($cm->id);
  54  
  55      $assignment = new assign($context, null, null);
  56      return $assignment->delete_instance();
  57  }
  58  
  59  /**
  60   * This function is used by the reset_course_userdata function in moodlelib.
  61   * This function will remove all assignment submissions and feedbacks in the database
  62   * and clean up any related data.
  63   *
  64   * @param stdClass $data the data submitted from the reset course.
  65   * @return array
  66   */
  67  function assign_reset_userdata($data) {
  68      global $CFG, $DB;
  69      require_once($CFG->dirroot . '/mod/assign/locallib.php');
  70  
  71      $status = array();
  72      $params = array('courseid'=>$data->courseid);
  73      $sql = "SELECT a.id FROM {assign} a WHERE a.course=:courseid";
  74      $course = $DB->get_record('course', array('id'=>$data->courseid), '*', MUST_EXIST);
  75      if ($assigns = $DB->get_records_sql($sql, $params)) {
  76          foreach ($assigns as $assign) {
  77              $cm = get_coursemodule_from_instance('assign',
  78                                                   $assign->id,
  79                                                   $data->courseid,
  80                                                   false,
  81                                                   MUST_EXIST);
  82              $context = context_module::instance($cm->id);
  83              $assignment = new assign($context, $cm, $course);
  84              $status = array_merge($status, $assignment->reset_userdata($data));
  85          }
  86      }
  87      return $status;
  88  }
  89  
  90  /**
  91   * Removes all grades from gradebook
  92   *
  93   * @param int $courseid The ID of the course to reset
  94   * @param string $type Optional type of assignment to limit the reset to a particular assignment type
  95   */
  96  function assign_reset_gradebook($courseid, $type='') {
  97      global $CFG, $DB;
  98  
  99      $params = array('moduletype'=>'assign', 'courseid'=>$courseid);
 100      $sql = 'SELECT a.*, cm.idnumber as cmidnumber, a.course as courseid
 101              FROM {assign} a, {course_modules} cm, {modules} m
 102              WHERE m.name=:moduletype AND m.id=cm.module AND cm.instance=a.id AND a.course=:courseid';
 103  
 104      if ($assignments = $DB->get_records_sql($sql, $params)) {
 105          foreach ($assignments as $assignment) {
 106              assign_grade_item_update($assignment, 'reset');
 107          }
 108      }
 109  }
 110  
 111  /**
 112   * Implementation of the function for printing the form elements that control
 113   * whether the course reset functionality affects the assignment.
 114   * @param moodleform $mform form passed by reference
 115   */
 116  function assign_reset_course_form_definition(&$mform) {
 117      $mform->addElement('header', 'assignheader', get_string('modulenameplural', 'assign'));
 118      $name = get_string('deleteallsubmissions', 'assign');
 119      $mform->addElement('advcheckbox', 'reset_assign_submissions', $name);
 120  }
 121  
 122  /**
 123   * Course reset form defaults.
 124   * @param  object $course
 125   * @return array
 126   */
 127  function assign_reset_course_form_defaults($course) {
 128      return array('reset_assign_submissions'=>1);
 129  }
 130  
 131  /**
 132   * Update an assignment instance
 133   *
 134   * This is done by calling the update_instance() method of the assignment type class
 135   * @param stdClass $data
 136   * @param stdClass $form - unused
 137   * @return object
 138   */
 139  function assign_update_instance(stdClass $data, $form) {
 140      global $CFG;
 141      require_once($CFG->dirroot . '/mod/assign/locallib.php');
 142      $context = context_module::instance($data->coursemodule);
 143      $assignment = new assign($context, null, null);
 144      return $assignment->update_instance($data);
 145  }
 146  
 147  /**
 148   * Return the list if Moodle features this module supports
 149   *
 150   * @param string $feature FEATURE_xx constant for requested feature
 151   * @return mixed True if module supports feature, null if doesn't know
 152   */
 153  function assign_supports($feature) {
 154      switch($feature) {
 155          case FEATURE_GROUPS:
 156              return true;
 157          case FEATURE_GROUPINGS:
 158              return true;
 159          case FEATURE_MOD_INTRO:
 160              return true;
 161          case FEATURE_COMPLETION_TRACKS_VIEWS:
 162              return true;
 163          case FEATURE_COMPLETION_HAS_RULES:
 164              return true;
 165          case FEATURE_GRADE_HAS_GRADE:
 166              return true;
 167          case FEATURE_GRADE_OUTCOMES:
 168              return true;
 169          case FEATURE_BACKUP_MOODLE2:
 170              return true;
 171          case FEATURE_SHOW_DESCRIPTION:
 172              return true;
 173          case FEATURE_ADVANCED_GRADING:
 174              return true;
 175          case FEATURE_PLAGIARISM:
 176              return true;
 177  
 178          default:
 179              return null;
 180      }
 181  }
 182  
 183  /**
 184   * Lists all gradable areas for the advanced grading methods gramework
 185   *
 186   * @return array('string'=>'string') An array with area names as keys and descriptions as values
 187   */
 188  function assign_grading_areas_list() {
 189      return array('submissions'=>get_string('submissions', 'assign'));
 190  }
 191  
 192  
 193  /**
 194   * extend an assigment navigation settings
 195   *
 196   * @param settings_navigation $settings
 197   * @param navigation_node $navref
 198   * @return void
 199   */
 200  function assign_extend_settings_navigation(settings_navigation $settings, navigation_node $navref) {
 201      global $PAGE, $DB;
 202  
 203      $cm = $PAGE->cm;
 204      if (!$cm) {
 205          return;
 206      }
 207  
 208      $context = $cm->context;
 209      $course = $PAGE->course;
 210  
 211      if (!$course) {
 212          return;
 213      }
 214  
 215      // Link to gradebook.
 216      if (has_capability('gradereport/grader:view', $cm->context) &&
 217              has_capability('moodle/grade:viewall', $cm->context)) {
 218          $link = new moodle_url('/grade/report/grader/index.php', array('id' => $course->id));
 219          $linkname = get_string('viewgradebook', 'assign');
 220          $node = $navref->add($linkname, $link, navigation_node::TYPE_SETTING);
 221      }
 222  
 223      // Link to download all submissions.
 224      if (has_any_capability(array('mod/assign:grade', 'mod/assign:viewgrades'), $context)) {
 225          $link = new moodle_url('/mod/assign/view.php', array('id' => $cm->id, 'action'=>'grading'));
 226          $node = $navref->add(get_string('viewgrading', 'assign'), $link, navigation_node::TYPE_SETTING);
 227  
 228          $link = new moodle_url('/mod/assign/view.php', array('id' => $cm->id, 'action'=>'downloadall'));
 229          $node = $navref->add(get_string('downloadall', 'assign'), $link, navigation_node::TYPE_SETTING);
 230      }
 231  
 232      if (has_capability('mod/assign:revealidentities', $context)) {
 233          $dbparams = array('id'=>$cm->instance);
 234          $assignment = $DB->get_record('assign', $dbparams, 'blindmarking, revealidentities');
 235  
 236          if ($assignment && $assignment->blindmarking && !$assignment->revealidentities) {
 237              $urlparams = array('id' => $cm->id, 'action'=>'revealidentities');
 238              $url = new moodle_url('/mod/assign/view.php', $urlparams);
 239              $linkname = get_string('revealidentities', 'assign');
 240              $node = $navref->add($linkname, $url, navigation_node::TYPE_SETTING);
 241          }
 242      }
 243  }
 244  
 245  /**
 246   * Add a get_coursemodule_info function in case any assignment type wants to add 'extra' information
 247   * for the course (see resource).
 248   *
 249   * Given a course_module object, this function returns any "extra" information that may be needed
 250   * when printing this activity in a course listing.  See get_array_of_activities() in course/lib.php.
 251   *
 252   * @param stdClass $coursemodule The coursemodule object (record).
 253   * @return cached_cm_info An object on information that the courses
 254   *                        will know about (most noticeably, an icon).
 255   */
 256  function assign_get_coursemodule_info($coursemodule) {
 257      global $CFG, $DB;
 258  
 259      $dbparams = array('id'=>$coursemodule->instance);
 260      $fields = 'id, name, alwaysshowdescription, allowsubmissionsfromdate, intro, introformat';
 261      if (! $assignment = $DB->get_record('assign', $dbparams, $fields)) {
 262          return false;
 263      }
 264  
 265      $result = new cached_cm_info();
 266      $result->name = $assignment->name;
 267      if ($coursemodule->showdescription) {
 268          if ($assignment->alwaysshowdescription || time() > $assignment->allowsubmissionsfromdate) {
 269              // Convert intro to html. Do not filter cached version, filters run at display time.
 270              $result->content = format_module_intro('assign', $assignment, $coursemodule->id, false);
 271          }
 272      }
 273      return $result;
 274  }
 275  
 276  /**
 277   * Return a list of page types
 278   * @param string $pagetype current page type
 279   * @param stdClass $parentcontext Block's parent context
 280   * @param stdClass $currentcontext Current context of block
 281   */
 282  function assign_page_type_list($pagetype, $parentcontext, $currentcontext) {
 283      $modulepagetype = array(
 284          'mod-assign-*' => get_string('page-mod-assign-x', 'assign'),
 285          'mod-assign-view' => get_string('page-mod-assign-view', 'assign'),
 286      );
 287      return $modulepagetype;
 288  }
 289  
 290  /**
 291   * Print an overview of all assignments
 292   * for the courses.
 293   *
 294   * @param mixed $courses The list of courses to print the overview for
 295   * @param array $htmlarray The array of html to return
 296   */
 297  function assign_print_overview($courses, &$htmlarray) {
 298      global $USER, $CFG, $DB;
 299  
 300      if (empty($courses) || !is_array($courses) || count($courses) == 0) {
 301          return array();
 302      }
 303  
 304      if (!$assignments = get_all_instances_in_courses('assign', $courses)) {
 305          return;
 306      }
 307  
 308      $assignmentids = array();
 309  
 310      // Do assignment_base::isopen() here without loading the whole thing for speed.
 311      foreach ($assignments as $key => $assignment) {
 312          $time = time();
 313          $isopen = false;
 314          if ($assignment->duedate) {
 315              $duedate = false;
 316              if ($assignment->cutoffdate) {
 317                  $duedate = $assignment->cutoffdate;
 318              }
 319              if ($duedate) {
 320                  $isopen = ($assignment->allowsubmissionsfromdate <= $time && $time <= $duedate);
 321              } else {
 322                  $isopen = ($assignment->allowsubmissionsfromdate <= $time);
 323              }
 324          }
 325          if ($isopen) {
 326              $assignmentids[] = $assignment->id;
 327          }
 328      }
 329  
 330      if (empty($assignmentids)) {
 331          // No assignments to look at - we're done.
 332          return true;
 333      }
 334  
 335      // Definitely something to print, now include the constants we need.
 336      require_once($CFG->dirroot . '/mod/assign/locallib.php');
 337  
 338      $strduedate = get_string('duedate', 'assign');
 339      $strcutoffdate = get_string('nosubmissionsacceptedafter', 'assign');
 340      $strnolatesubmissions = get_string('nolatesubmissions', 'assign');
 341      $strduedateno = get_string('duedateno', 'assign');
 342      $strduedateno = get_string('duedateno', 'assign');
 343      $strgraded = get_string('graded', 'assign');
 344      $strnotgradedyet = get_string('notgradedyet', 'assign');
 345      $strnotsubmittedyet = get_string('notsubmittedyet', 'assign');
 346      $strsubmitted = get_string('submitted', 'assign');
 347      $strassignment = get_string('modulename', 'assign');
 348      $strreviewed = get_string('reviewed', 'assign');
 349  
 350      // We do all possible database work here *outside* of the loop to ensure this scales.
 351      list($sqlassignmentids, $assignmentidparams) = $DB->get_in_or_equal($assignmentids);
 352  
 353      $mysubmissions = null;
 354      $unmarkedsubmissions = null;
 355  
 356      foreach ($assignments as $assignment) {
 357          // Do not show assignments that are not open.
 358          if (!in_array($assignment->id, $assignmentids)) {
 359              continue;
 360          }
 361          $dimmedclass = '';
 362          if (!$assignment->visible) {
 363              $dimmedclass = ' class="dimmed"';
 364          }
 365          $href = $CFG->wwwroot . '/mod/assign/view.php?id=' . $assignment->coursemodule;
 366          $str = '<div class="assign overview">' .
 367                 '<div class="name">' .
 368                 $strassignment . ': '.
 369                 '<a ' . $dimmedclass .
 370                     'title="' . $strassignment . '" ' .
 371                     'href="' . $href . '">' .
 372                 format_string($assignment->name) .
 373                 '</a></div>';
 374          if ($assignment->duedate) {
 375              $userdate = userdate($assignment->duedate);
 376              $str .= '<div class="info">' . $strduedate . ': ' . $userdate . '</div>';
 377          } else {
 378              $str .= '<div class="info">' . $strduedateno . '</div>';
 379          }
 380          if ($assignment->cutoffdate) {
 381              if ($assignment->cutoffdate == $assignment->duedate) {
 382                  $str .= '<div class="info">' . $strnolatesubmissions . '</div>';
 383              } else {
 384                  $userdate = userdate($assignment->cutoffdate);
 385                  $str .= '<div class="info">' . $strcutoffdate . ': ' . $userdate . '</div>';
 386              }
 387          }
 388          $context = context_module::instance($assignment->coursemodule);
 389          if (has_capability('mod/assign:grade', $context)) {
 390              if (!isset($unmarkedsubmissions)) {
 391                  // Build up and array of unmarked submissions indexed by assignment id/ userid
 392                  // for use where the user has grading rights on assignment.
 393                  $dbparams = array_merge(array(ASSIGN_SUBMISSION_STATUS_SUBMITTED), $assignmentidparams);
 394                  $rs = $DB->get_recordset_sql('SELECT
 395                                                    s.assignment as assignment,
 396                                                    s.userid as userid,
 397                                                    s.id as id,
 398                                                    s.status as status,
 399                                                    g.timemodified as timegraded
 400                                                FROM {assign_submission} s
 401                                                LEFT JOIN {assign_grades} g ON
 402                                                    s.userid = g.userid AND
 403                                                    s.assignment = g.assignment AND
 404                                                    g.attemptnumber = s.attemptnumber
 405                                                WHERE
 406                                                    ( g.timemodified is NULL OR
 407                                                    s.timemodified > g.timemodified ) AND
 408                                                    s.timemodified IS NOT NULL AND
 409                                                    s.status = ? AND
 410                                                    s.latest = 1 AND
 411                                                    s.assignment ' . $sqlassignmentids, $dbparams);
 412  
 413                  $unmarkedsubmissions = array();
 414                  foreach ($rs as $rd) {
 415                      $unmarkedsubmissions[$rd->assignment][$rd->userid] = $rd->id;
 416                  }
 417                  $rs->close();
 418              }
 419  
 420              // Count how many people can submit.
 421              $submissions = 0;
 422              if ($students = get_enrolled_users($context, 'mod/assign:view', 0, 'u.id')) {
 423                  foreach ($students as $student) {
 424                      if (isset($unmarkedsubmissions[$assignment->id][$student->id])) {
 425                          $submissions++;
 426                      }
 427                  }
 428              }
 429  
 430              if ($submissions) {
 431                  $urlparams = array('id'=>$assignment->coursemodule, 'action'=>'grading');
 432                  $url = new moodle_url('/mod/assign/view.php', $urlparams);
 433                  $str .= '<div class="details">' .
 434                          '<a href="' . $url . '">' .
 435                          get_string('submissionsnotgraded', 'assign', $submissions) .
 436                          '</a></div>';
 437              }
 438          }
 439          if (has_capability('mod/assign:submit', $context)) {
 440              if (!isset($mysubmissions)) {
 441  
 442                  // Get all user submissions, indexed by assignment id.
 443                  $dbparams = array_merge(array($USER->id), $assignmentidparams, array($USER->id));
 444                  $mysubmissions = $DB->get_records_sql('SELECT
 445                                                             a.id AS assignment,
 446                                                             a.nosubmissions AS nosubmissions,
 447                                                             g.timemodified AS timemarked,
 448                                                             g.grader AS grader,
 449                                                             g.grade AS grade,
 450                                                             s.status AS status
 451                                                         FROM {assign} a, {assign_submission} s
 452                                                         LEFT JOIN {assign_grades} g ON
 453                                                             g.assignment = s.assignment AND
 454                                                             g.userid = ? AND
 455                                                             g.attemptnumber = s.attemptnumber
 456                                                         WHERE a.id ' . $sqlassignmentids . ' AND
 457                                                             s.latest = 1 AND
 458                                                             s.assignment = a.id AND
 459                                                             s.userid = ?', $dbparams);
 460              }
 461  
 462              $str .= '<div class="details">';
 463              $str .= get_string('mysubmission', 'assign');
 464              $submission = false;
 465              if (isset($mysubmissions[$assignment->id])) {
 466                  $submission = $mysubmissions[$assignment->id];
 467              }
 468              if ($submission && $submission->nosubmissions) {
 469                  $str .= get_string('offline', 'assign');
 470              } else if (!$submission ||
 471                      !$submission->status ||
 472                      $submission->status == 'draft' ||
 473                      $submission->status == 'new') {
 474                  $str .= $strnotsubmittedyet;
 475              } else {
 476                  $str .= get_string('submissionstatus_' . $submission->status, 'assign');
 477              }
 478              if (!$submission || !$submission->grade || $submission->grade < 0) {
 479                  $str .= ', ' . get_string('notgraded', 'assign');
 480              } else {
 481                  $str .= ', ' . get_string('graded', 'assign');
 482              }
 483              $str .= '</div>';
 484          }
 485          $str .= '</div>';
 486          if (empty($htmlarray[$assignment->course]['assign'])) {
 487              $htmlarray[$assignment->course]['assign'] = $str;
 488          } else {
 489              $htmlarray[$assignment->course]['assign'] .= $str;
 490          }
 491      }
 492  }
 493  
 494  /**
 495   * Print recent activity from all assignments in a given course
 496   *
 497   * This is used by the recent activity block
 498   * @param mixed $course the course to print activity for
 499   * @param bool $viewfullnames boolean to determine whether to show full names or not
 500   * @param int $timestart the time the rendering started
 501   * @return bool true if activity was printed, false otherwise.
 502   */
 503  function assign_print_recent_activity($course, $viewfullnames, $timestart) {
 504      global $CFG, $USER, $DB, $OUTPUT;
 505      require_once($CFG->dirroot . '/mod/assign/locallib.php');
 506  
 507      // Do not use log table if possible, it may be huge.
 508  
 509      $dbparams = array($timestart, $course->id, 'assign', ASSIGN_SUBMISSION_STATUS_SUBMITTED);
 510      $namefields = user_picture::fields('u', null, 'userid');
 511      if (!$submissions = $DB->get_records_sql("SELECT asb.id, asb.timemodified, cm.id AS cmid,
 512                                                       $namefields
 513                                                  FROM {assign_submission} asb
 514                                                       JOIN {assign} a      ON a.id = asb.assignment
 515                                                       JOIN {course_modules} cm ON cm.instance = a.id
 516                                                       JOIN {modules} md        ON md.id = cm.module
 517                                                       JOIN {user} u            ON u.id = asb.userid
 518                                                 WHERE asb.timemodified > ? AND
 519                                                       asb.latest = 1 AND
 520                                                       a.course = ? AND
 521                                                       md.name = ? AND
 522                                                       asb.status = ?
 523                                              ORDER BY asb.timemodified ASC", $dbparams)) {
 524           return false;
 525      }
 526  
 527      $modinfo = get_fast_modinfo($course);
 528      $show    = array();
 529      $grader  = array();
 530  
 531      $showrecentsubmissions = get_config('assign', 'showrecentsubmissions');
 532  
 533      foreach ($submissions as $submission) {
 534          if (!array_key_exists($submission->cmid, $modinfo->get_cms())) {
 535              continue;
 536          }
 537          $cm = $modinfo->get_cm($submission->cmid);
 538          if (!$cm->uservisible) {
 539              continue;
 540          }
 541          if ($submission->userid == $USER->id) {
 542              $show[] = $submission;
 543              continue;
 544          }
 545  
 546          $context = context_module::instance($submission->cmid);
 547          // The act of submitting of assignment may be considered private -
 548          // only graders will see it if specified.
 549          if (empty($showrecentsubmissions)) {
 550              if (!array_key_exists($cm->id, $grader)) {
 551                  $grader[$cm->id] = has_capability('moodle/grade:viewall', $context);
 552              }
 553              if (!$grader[$cm->id]) {
 554                  continue;
 555              }
 556          }
 557  
 558          $groupmode = groups_get_activity_groupmode($cm, $course);
 559  
 560          if ($groupmode == SEPARATEGROUPS &&
 561                  !has_capability('moodle/site:accessallgroups',  $context)) {
 562              if (isguestuser()) {
 563                  // Shortcut - guest user does not belong into any group.
 564                  continue;
 565              }
 566  
 567              // This will be slow - show only users that share group with me in this cm.
 568              if (!$modinfo->get_groups($cm->groupingid)) {
 569                  continue;
 570              }
 571              $usersgroups =  groups_get_all_groups($course->id, $submission->userid, $cm->groupingid);
 572              if (is_array($usersgroups)) {
 573                  $usersgroups = array_keys($usersgroups);
 574                  $intersect = array_intersect($usersgroups, $modinfo->get_groups($cm->groupingid));
 575                  if (empty($intersect)) {
 576                      continue;
 577                  }
 578              }
 579          }
 580          $show[] = $submission;
 581      }
 582  
 583      if (empty($show)) {
 584          return false;
 585      }
 586  
 587      echo $OUTPUT->heading(get_string('newsubmissions', 'assign').':', 3);
 588  
 589      foreach ($show as $submission) {
 590          $cm = $modinfo->get_cm($submission->cmid);
 591          $link = $CFG->wwwroot.'/mod/assign/view.php?id='.$cm->id;
 592          print_recent_activity_note($submission->timemodified,
 593                                     $submission,
 594                                     $cm->name,
 595                                     $link,
 596                                     false,
 597                                     $viewfullnames);
 598      }
 599  
 600      return true;
 601  }
 602  
 603  /**
 604   * Returns all assignments since a given time.
 605   *
 606   * @param array $activities The activity information is returned in this array
 607   * @param int $index The current index in the activities array
 608   * @param int $timestart The earliest activity to show
 609   * @param int $courseid Limit the search to this course
 610   * @param int $cmid The course module id
 611   * @param int $userid Optional user id
 612   * @param int $groupid Optional group id
 613   * @return void
 614   */
 615  function assign_get_recent_mod_activity(&$activities,
 616                                          &$index,
 617                                          $timestart,
 618                                          $courseid,
 619                                          $cmid,
 620                                          $userid=0,
 621                                          $groupid=0) {
 622      global $CFG, $COURSE, $USER, $DB;
 623  
 624      require_once($CFG->dirroot . '/mod/assign/locallib.php');
 625  
 626      if ($COURSE->id == $courseid) {
 627          $course = $COURSE;
 628      } else {
 629          $course = $DB->get_record('course', array('id'=>$courseid));
 630      }
 631  
 632      $modinfo = get_fast_modinfo($course);
 633  
 634      $cm = $modinfo->get_cm($cmid);
 635      $params = array();
 636      if ($userid) {
 637          $userselect = 'AND u.id = :userid';
 638          $params['userid'] = $userid;
 639      } else {
 640          $userselect = '';
 641      }
 642  
 643      if ($groupid) {
 644          $groupselect = 'AND gm.groupid = :groupid';
 645          $groupjoin   = 'JOIN {groups_members} gm ON  gm.userid=u.id';
 646          $params['groupid'] = $groupid;
 647      } else {
 648          $groupselect = '';
 649          $groupjoin   = '';
 650      }
 651  
 652      $params['cminstance'] = $cm->instance;
 653      $params['timestart'] = $timestart;
 654      $params['submitted'] = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
 655  
 656      $userfields = user_picture::fields('u', null, 'userid');
 657  
 658      if (!$submissions = $DB->get_records_sql('SELECT asb.id, asb.timemodified, ' .
 659                                                       $userfields .
 660                                               '  FROM {assign_submission} asb
 661                                                  JOIN {assign} a ON a.id = asb.assignment
 662                                                  JOIN {user} u ON u.id = asb.userid ' .
 663                                            $groupjoin .
 664                                              '  WHERE asb.timemodified > :timestart AND
 665                                                       asb.status = :submitted AND
 666                                                       a.id = :cminstance
 667                                                       ' . $userselect . ' ' . $groupselect .
 668                                              ' ORDER BY asb.timemodified ASC', $params)) {
 669           return;
 670      }
 671  
 672      $groupmode       = groups_get_activity_groupmode($cm, $course);
 673      $cmcontext      = context_module::instance($cm->id);
 674      $grader          = has_capability('moodle/grade:viewall', $cmcontext);
 675      $accessallgroups = has_capability('moodle/site:accessallgroups', $cmcontext);
 676      $viewfullnames   = has_capability('moodle/site:viewfullnames', $cmcontext);
 677  
 678  
 679      $showrecentsubmissions = get_config('assign', 'showrecentsubmissions');
 680      $show = array();
 681      foreach ($submissions as $submission) {
 682          if ($submission->userid == $USER->id) {
 683              $show[] = $submission;
 684              continue;
 685          }
 686          // The act of submitting of assignment may be considered private -
 687          // only graders will see it if specified.
 688          if (empty($showrecentsubmissions)) {
 689              if (!$grader) {
 690                  continue;
 691              }
 692          }
 693  
 694          if ($groupmode == SEPARATEGROUPS and !$accessallgroups) {
 695              if (isguestuser()) {
 696                  // Shortcut - guest user does not belong into any group.
 697                  continue;
 698              }
 699  
 700              // This will be slow - show only users that share group with me in this cm.
 701              if (!$modinfo->get_groups($cm->groupingid)) {
 702                  continue;
 703              }
 704              $usersgroups =  groups_get_all_groups($course->id, $submission->userid, $cm->groupingid);
 705              if (is_array($usersgroups)) {
 706                  $usersgroups = array_keys($usersgroups);
 707                  $intersect = array_intersect($usersgroups, $modinfo->get_groups($cm->groupingid));
 708                  if (empty($intersect)) {
 709                      continue;
 710                  }
 711              }
 712          }
 713          $show[] = $submission;
 714      }
 715  
 716      if (empty($show)) {
 717          return;
 718      }
 719  
 720      if ($grader) {
 721          require_once($CFG->libdir.'/gradelib.php');
 722          $userids = array();
 723          foreach ($show as $id => $submission) {
 724              $userids[] = $submission->userid;
 725          }
 726          $grades = grade_get_grades($courseid, 'mod', 'assign', $cm->instance, $userids);
 727      }
 728  
 729      $aname = format_string($cm->name, true);
 730      foreach ($show as $submission) {
 731          $activity = new stdClass();
 732  
 733          $activity->type         = 'assign';
 734          $activity->cmid         = $cm->id;
 735          $activity->name         = $aname;
 736          $activity->sectionnum   = $cm->sectionnum;
 737          $activity->timestamp    = $submission->timemodified;
 738          $activity->user         = new stdClass();
 739          if ($grader) {
 740              $activity->grade = $grades->items[0]->grades[$submission->userid]->str_long_grade;
 741          }
 742  
 743          $userfields = explode(',', user_picture::fields());
 744          foreach ($userfields as $userfield) {
 745              if ($userfield == 'id') {
 746                  // Aliased in SQL above.
 747                  $activity->user->{$userfield} = $submission->userid;
 748              } else {
 749                  $activity->user->{$userfield} = $submission->{$userfield};
 750              }
 751          }
 752          $activity->user->fullname = fullname($submission, $viewfullnames);
 753  
 754          $activities[$index++] = $activity;
 755      }
 756  
 757      return;
 758  }
 759  
 760  /**
 761   * Print recent activity from all assignments in a given course
 762   *
 763   * This is used by course/recent.php
 764   * @param stdClass $activity
 765   * @param int $courseid
 766   * @param bool $detail
 767   * @param array $modnames
 768   */
 769  function assign_print_recent_mod_activity($activity, $courseid, $detail, $modnames) {
 770      global $CFG, $OUTPUT;
 771  
 772      echo '<table border="0" cellpadding="3" cellspacing="0" class="assignment-recent">';
 773  
 774      echo '<tr><td class="userpicture" valign="top">';
 775      echo $OUTPUT->user_picture($activity->user);
 776      echo '</td><td>';
 777  
 778      if ($detail) {
 779          $modname = $modnames[$activity->type];
 780          echo '<div class="title">';
 781          echo '<img src="' . $OUTPUT->pix_url('icon', 'assign') . '" '.
 782               'class="icon" alt="' . $modname . '">';
 783          echo '<a href="' . $CFG->wwwroot . '/mod/assign/view.php?id=' . $activity->cmid . '">';
 784          echo $activity->name;
 785          echo '</a>';
 786          echo '</div>';
 787      }
 788  
 789      if (isset($activity->grade)) {
 790          echo '<div class="grade">';
 791          echo get_string('grade').': ';
 792          echo $activity->grade;
 793          echo '</div>';
 794      }
 795  
 796      echo '<div class="user">';
 797      echo "<a href=\"$CFG->wwwroot/user/view.php?id={$activity->user->id}&amp;course=$courseid\">";
 798      echo "{$activity->user->fullname}</a>  - " . userdate($activity->timestamp);
 799      echo '</div>';
 800  
 801      echo '</td></tr></table>';
 802  }
 803  
 804  /**
 805   * Checks if a scale is being used by an assignment.
 806   *
 807   * This is used by the backup code to decide whether to back up a scale
 808   * @param int $assignmentid
 809   * @param int $scaleid
 810   * @return boolean True if the scale is used by the assignment
 811   */
 812  function assign_scale_used($assignmentid, $scaleid) {
 813      global $DB;
 814  
 815      $return = false;
 816      $rec = $DB->get_record('assign', array('id'=>$assignmentid, 'grade'=>-$scaleid));
 817  
 818      if (!empty($rec) && !empty($scaleid)) {
 819          $return = true;
 820      }
 821  
 822      return $return;
 823  }
 824  
 825  /**
 826   * Checks if scale is being used by any instance of assignment
 827   *
 828   * This is used to find out if scale used anywhere
 829   * @param int $scaleid
 830   * @return boolean True if the scale is used by any assignment
 831   */
 832  function assign_scale_used_anywhere($scaleid) {
 833      global $DB;
 834  
 835      if ($scaleid and $DB->record_exists('assign', array('grade'=>-$scaleid))) {
 836          return true;
 837      } else {
 838          return false;
 839      }
 840  }
 841  
 842  /**
 843   * List the actions that correspond to a view of this module.
 844   * This is used by the participation report.
 845   *
 846   * Note: This is not used by new logging system. Event with
 847   *       crud = 'r' and edulevel = LEVEL_PARTICIPATING will
 848   *       be considered as view action.
 849   *
 850   * @return array
 851   */
 852  function assign_get_view_actions() {
 853      return array('view submission', 'view feedback');
 854  }
 855  
 856  /**
 857   * List the actions that correspond to a post of this module.
 858   * This is used by the participation report.
 859   *
 860   * Note: This is not used by new logging system. Event with
 861   *       crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING
 862   *       will be considered as post action.
 863   *
 864   * @return array
 865   */
 866  function assign_get_post_actions() {
 867      return array('upload', 'submit', 'submit for grading');
 868  }
 869  
 870  /**
 871   * Call cron on the assign module.
 872   */
 873  function assign_cron() {
 874      global $CFG;
 875  
 876      require_once($CFG->dirroot . '/mod/assign/locallib.php');
 877      assign::cron();
 878  
 879      $plugins = core_component::get_plugin_list('assignsubmission');
 880  
 881      foreach ($plugins as $name => $plugin) {
 882          $disabled = get_config('assignsubmission_' . $name, 'disabled');
 883          if (!$disabled) {
 884              $class = 'assign_submission_' . $name;
 885              require_once($CFG->dirroot . '/mod/assign/submission/' . $name . '/locallib.php');
 886              $class::cron();
 887          }
 888      }
 889      $plugins = core_component::get_plugin_list('assignfeedback');
 890  
 891      foreach ($plugins as $name => $plugin) {
 892          $disabled = get_config('assignfeedback_' . $name, 'disabled');
 893          if (!$disabled) {
 894              $class = 'assign_feedback_' . $name;
 895              require_once($CFG->dirroot . '/mod/assign/feedback/' . $name . '/locallib.php');
 896              $class::cron();
 897          }
 898      }
 899  
 900      return true;
 901  }
 902  
 903  /**
 904   * Returns all other capabilities used by this module.
 905   * @return array Array of capability strings
 906   */
 907  function assign_get_extra_capabilities() {
 908      return array('gradereport/grader:view',
 909                   'moodle/grade:viewall',
 910                   'moodle/site:viewfullnames',
 911                   'moodle/site:config');
 912  }
 913  
 914  /**
 915   * Create grade item for given assignment.
 916   *
 917   * @param stdClass $assign record with extra cmidnumber
 918   * @param array $grades optional array/object of grade(s); 'reset' means reset grades in gradebook
 919   * @return int 0 if ok, error code otherwise
 920   */
 921  function assign_grade_item_update($assign, $grades=null) {
 922      global $CFG;
 923      require_once($CFG->libdir.'/gradelib.php');
 924  
 925      if (!isset($assign->courseid)) {
 926          $assign->courseid = $assign->course;
 927      }
 928  
 929      $params = array('itemname'=>$assign->name, 'idnumber'=>$assign->cmidnumber);
 930  
 931      // Check if feedback plugin for gradebook is enabled, if yes then
 932      // gradetype = GRADE_TYPE_TEXT else GRADE_TYPE_NONE.
 933      $gradefeedbackenabled = false;
 934  
 935      if (isset($assign->gradefeedbackenabled)) {
 936          $gradefeedbackenabled = $assign->gradefeedbackenabled;
 937      } else if ($assign->grade == 0) { // Grade feedback is needed only when grade == 0.
 938          require_once($CFG->dirroot . '/mod/assign/locallib.php');
 939          $mod = get_coursemodule_from_instance('assign', $assign->id, $assign->courseid);
 940          $cm = context_module::instance($mod->id);
 941          $assignment = new assign($cm, null, null);
 942          $gradefeedbackenabled = $assignment->is_gradebook_feedback_enabled();
 943      }
 944  
 945      if ($assign->grade > 0) {
 946          $params['gradetype'] = GRADE_TYPE_VALUE;
 947          $params['grademax']  = $assign->grade;
 948          $params['grademin']  = 0;
 949  
 950      } else if ($assign->grade < 0) {
 951          $params['gradetype'] = GRADE_TYPE_SCALE;
 952          $params['scaleid']   = -$assign->grade;
 953  
 954      } else if ($gradefeedbackenabled) {
 955          // $assign->grade == 0 and feedback enabled.
 956          $params['gradetype'] = GRADE_TYPE_TEXT;
 957      } else {
 958          // $assign->grade == 0 and no feedback enabled.
 959          $params['gradetype'] = GRADE_TYPE_NONE;
 960      }
 961  
 962      if ($grades  === 'reset') {
 963          $params['reset'] = true;
 964          $grades = null;
 965      }
 966  
 967      return grade_update('mod/assign',
 968                          $assign->courseid,
 969                          'mod',
 970                          'assign',
 971                          $assign->id,
 972                          0,
 973                          $grades,
 974                          $params);
 975  }
 976  
 977  /**
 978   * Return grade for given user or all users.
 979   *
 980   * @param stdClass $assign record of assign with an additional cmidnumber
 981   * @param int $userid optional user id, 0 means all users
 982   * @return array array of grades, false if none
 983   */
 984  function assign_get_user_grades($assign, $userid=0) {
 985      global $CFG;
 986  
 987      require_once($CFG->dirroot . '/mod/assign/locallib.php');
 988  
 989      $cm = get_coursemodule_from_instance('assign', $assign->id, 0, false, MUST_EXIST);
 990      $context = context_module::instance($cm->id);
 991      $assignment = new assign($context, null, null);
 992      $assignment->set_instance($assign);
 993      return $assignment->get_user_grades_for_gradebook($userid);
 994  }
 995  
 996  /**
 997   * Update activity grades.
 998   *
 999   * @param stdClass $assign database record
1000   * @param int $userid specific user only, 0 means all
1001   * @param bool $nullifnone - not used
1002   */
1003  function assign_update_grades($assign, $userid=0, $nullifnone=true) {
1004      global $CFG;
1005      require_once($CFG->libdir.'/gradelib.php');
1006  
1007      if ($assign->grade == 0) {
1008          assign_grade_item_update($assign);
1009  
1010      } else if ($grades = assign_get_user_grades($assign, $userid)) {
1011          foreach ($grades as $k => $v) {
1012              if ($v->rawgrade == -1) {
1013                  $grades[$k]->rawgrade = null;
1014              }
1015          }
1016          assign_grade_item_update($assign, $grades);
1017  
1018      } else {
1019          assign_grade_item_update($assign);
1020      }
1021  }
1022  
1023  /**
1024   * List the file areas that can be browsed.
1025   *
1026   * @param stdClass $course
1027   * @param stdClass $cm
1028   * @param stdClass $context
1029   * @return array
1030   */
1031  function assign_get_file_areas($course, $cm, $context) {
1032      global $CFG;
1033      require_once($CFG->dirroot . '/mod/assign/locallib.php');
1034  
1035      $areas = array(ASSIGN_INTROATTACHMENT_FILEAREA => get_string('introattachments', 'mod_assign'));
1036  
1037      $assignment = new assign($context, $cm, $course);
1038      foreach ($assignment->get_submission_plugins() as $plugin) {
1039          if ($plugin->is_visible()) {
1040              $pluginareas = $plugin->get_file_areas();
1041  
1042              if ($pluginareas) {
1043                  $areas = array_merge($areas, $pluginareas);
1044              }
1045          }
1046      }
1047      foreach ($assignment->get_feedback_plugins() as $plugin) {
1048          if ($plugin->is_visible()) {
1049              $pluginareas = $plugin->get_file_areas();
1050  
1051              if ($pluginareas) {
1052                  $areas = array_merge($areas, $pluginareas);
1053              }
1054          }
1055      }
1056  
1057      return $areas;
1058  }
1059  
1060  /**
1061   * File browsing support for assign module.
1062   *
1063   * @param file_browser $browser
1064   * @param object $areas
1065   * @param object $course
1066   * @param object $cm
1067   * @param object $context
1068   * @param string $filearea
1069   * @param int $itemid
1070   * @param string $filepath
1071   * @param string $filename
1072   * @return object file_info instance or null if not found
1073   */
1074  function assign_get_file_info($browser,
1075                                $areas,
1076                                $course,
1077                                $cm,
1078                                $context,
1079                                $filearea,
1080                                $itemid,
1081                                $filepath,
1082                                $filename) {
1083      global $CFG;
1084      require_once($CFG->dirroot . '/mod/assign/locallib.php');
1085  
1086      if ($context->contextlevel != CONTEXT_MODULE) {
1087          return null;
1088      }
1089  
1090      $urlbase = $CFG->wwwroot.'/pluginfile.php';
1091      $fs = get_file_storage();
1092      $filepath = is_null($filepath) ? '/' : $filepath;
1093      $filename = is_null($filename) ? '.' : $filename;
1094  
1095      // Need to find where this belongs to.
1096      $assignment = new assign($context, $cm, $course);
1097      if ($filearea === ASSIGN_INTROATTACHMENT_FILEAREA) {
1098          if (!has_capability('moodle/course:managefiles', $context)) {
1099              // Students can not peak here!
1100              return null;
1101          }
1102          if (!($storedfile = $fs->get_file($assignment->get_context()->id,
1103                                            'mod_assign', $filearea, 0, $filepath, $filename))) {
1104              return null;
1105          }
1106          return new file_info_stored($browser,
1107                          $assignment->get_context(),
1108                          $storedfile,
1109                          $urlbase,
1110                          $filearea,
1111                          $itemid,
1112                          true,
1113                          true,
1114                          false);
1115      }
1116  
1117      $pluginowner = null;
1118      foreach ($assignment->get_submission_plugins() as $plugin) {
1119          if ($plugin->is_visible()) {
1120              $pluginareas = $plugin->get_file_areas();
1121  
1122              if (array_key_exists($filearea, $pluginareas)) {
1123                  $pluginowner = $plugin;
1124                  break;
1125              }
1126          }
1127      }
1128      if (!$pluginowner) {
1129          foreach ($assignment->get_feedback_plugins() as $plugin) {
1130              if ($plugin->is_visible()) {
1131                  $pluginareas = $plugin->get_file_areas();
1132  
1133                  if (array_key_exists($filearea, $pluginareas)) {
1134                      $pluginowner = $plugin;
1135                      break;
1136                  }
1137              }
1138          }
1139      }
1140  
1141      if (!$pluginowner) {
1142          return null;
1143      }
1144  
1145      $result = $pluginowner->get_file_info($browser, $filearea, $itemid, $filepath, $filename);
1146      return $result;
1147  }
1148  
1149  /**
1150   * Prints the complete info about a user's interaction with an assignment.
1151   *
1152   * @param stdClass $course
1153   * @param stdClass $user
1154   * @param stdClass $coursemodule
1155   * @param stdClass $assign the database assign record
1156   *
1157   * This prints the submission summary and feedback summary for this student.
1158   */
1159  function assign_user_complete($course, $user, $coursemodule, $assign) {
1160      global $CFG;
1161      require_once($CFG->dirroot . '/mod/assign/locallib.php');
1162  
1163      $context = context_module::instance($coursemodule->id);
1164  
1165      $assignment = new assign($context, $coursemodule, $course);
1166  
1167      echo $assignment->view_student_summary($user, false);
1168  }
1169  
1170  /**
1171   * Print the grade information for the assignment for this user.
1172   *
1173   * @param stdClass $course
1174   * @param stdClass $user
1175   * @param stdClass $coursemodule
1176   * @param stdClass $assignment
1177   */
1178  function assign_user_outline($course, $user, $coursemodule, $assignment) {
1179      global $CFG;
1180      require_once($CFG->libdir.'/gradelib.php');
1181      require_once($CFG->dirroot.'/grade/grading/lib.php');
1182  
1183      $gradinginfo = grade_get_grades($course->id,
1184                                          'mod',
1185                                          'assign',
1186                                          $assignment->id,
1187                                          $user->id);
1188  
1189      $gradingitem = $gradinginfo->items[0];
1190      $gradebookgrade = $gradingitem->grades[$user->id];
1191  
1192      if (empty($gradebookgrade->str_long_grade)) {
1193          return null;
1194      }
1195      $result = new stdClass();
1196      $result->info = get_string('outlinegrade', 'assign', $gradebookgrade->str_long_grade);
1197      $result->time = $gradebookgrade->dategraded;
1198  
1199      return $result;
1200  }
1201  
1202  /**
1203   * Obtains the automatic completion state for this module based on any conditions
1204   * in assign settings.
1205   *
1206   * @param object $course Course
1207   * @param object $cm Course-module
1208   * @param int $userid User ID
1209   * @param bool $type Type of comparison (or/and; can be used as return value if no conditions)
1210   * @return bool True if completed, false if not, $type if conditions not set.
1211   */
1212  function assign_get_completion_state($course, $cm, $userid, $type) {
1213      global $CFG, $DB;
1214      require_once($CFG->dirroot . '/mod/assign/locallib.php');
1215  
1216      $assign = new assign(null, $cm, $course);
1217  
1218      // If completion option is enabled, evaluate it and return true/false.
1219      if ($assign->get_instance()->completionsubmit) {
1220          $dbparams = array('assignment'=>$assign->get_instance()->id, 'userid'=>$userid);
1221          $submission = $DB->get_record('assign_submission', $dbparams, '*', IGNORE_MISSING);
1222          return $submission && $submission->status == ASSIGN_SUBMISSION_STATUS_SUBMITTED;
1223      } else {
1224          // Completion option is not enabled so just return $type.
1225          return $type;
1226      }
1227  }
1228  
1229  /**
1230   * Serves intro attachment files.
1231   *
1232   * @param mixed $course course or id of the course
1233   * @param mixed $cm course module or id of the course module
1234   * @param context $context
1235   * @param string $filearea
1236   * @param array $args
1237   * @param bool $forcedownload
1238   * @param array $options additional options affecting the file serving
1239   * @return bool false if file not found, does not return if found - just send the file
1240   */
1241  function assign_pluginfile($course,
1242                  $cm,
1243                  context $context,
1244                  $filearea,
1245                  $args,
1246                  $forcedownload,
1247                  array $options=array()) {
1248      global $CFG;
1249  
1250      if ($context->contextlevel != CONTEXT_MODULE) {
1251          return false;
1252      }
1253  
1254      require_login($course, false, $cm);
1255      if (!has_capability('mod/assign:view', $context)) {
1256          return false;
1257      }
1258  
1259      require_once($CFG->dirroot . '/mod/assign/locallib.php');
1260      $assign = new assign($context, $cm, $course);
1261  
1262      if ($filearea !== ASSIGN_INTROATTACHMENT_FILEAREA) {
1263          return false;
1264      }
1265      if (!$assign->show_intro()) {
1266          return false;
1267      }
1268  
1269      $itemid = (int)array_shift($args);
1270      if ($itemid != 0) {
1271          return false;
1272      }
1273  
1274      $relativepath = implode('/', $args);
1275  
1276      $fullpath = "/{$context->id}/mod_assign/$filearea/$itemid/$relativepath";
1277  
1278      $fs = get_file_storage();
1279      if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
1280          return false;
1281      }
1282      send_stored_file($file, 0, 0, $forcedownload, $options);
1283  }


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