[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/availability/condition/grade/classes/ -> condition.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   * Condition on grades of current user.
  19   *
  20   * @package availability_grade
  21   * @copyright 2014 The Open University
  22   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace availability_grade;
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  /**
  30   * Condition on grades of current user.
  31   *
  32   * @package availability_grade
  33   * @copyright 2014 The Open University
  34   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  class condition extends \core_availability\condition {
  37      /** @var int Grade item id */
  38      private $gradeitemid;
  39  
  40      /** @var float|null Min grade (must be >= this) or null if none */
  41      private $min;
  42  
  43      /** @var float|null Max grade (must be < this) or null if none */
  44      private $max;
  45  
  46      /**
  47       * Constructor.
  48       *
  49       * @param \stdClass $structure Data structure from JSON decode
  50       * @throws \coding_exception If invalid data structure.
  51       */
  52      public function __construct($structure) {
  53          // Get grade item id.
  54          if (isset($structure->id) && is_int($structure->id)) {
  55              $this->gradeitemid = $structure->id;
  56          } else {
  57              throw new \coding_exception('Missing or invalid ->id for grade condition');
  58          }
  59  
  60          // Get min and max.
  61          if (!property_exists($structure, 'min')) {
  62              $this->min = null;
  63          } else if (is_float($structure->min) || is_int($structure->min)) {
  64              $this->min = $structure->min;
  65          } else {
  66              throw new \coding_exception('Missing or invalid ->min for grade condition');
  67          }
  68          if (!property_exists($structure, 'max')) {
  69              $this->max = null;
  70          } else if (is_float($structure->max) || is_int($structure->max)) {
  71              $this->max = $structure->max;
  72          } else {
  73              throw new \coding_exception('Missing or invalid ->max for grade condition');
  74          }
  75      }
  76  
  77      public function save() {
  78          $result = (object)array('type' => 'grade', 'id' => $this->gradeitemid);
  79          if (!is_null($this->min)) {
  80              $result->min = $this->min;
  81          }
  82          if (!is_null($this->max)) {
  83              $result->max = $this->max;
  84          }
  85          return $result;
  86      }
  87  
  88      /**
  89       * Returns a JSON object which corresponds to a condition of this type.
  90       *
  91       * Intended for unit testing, as normally the JSON values are constructed
  92       * by JavaScript code.
  93       *
  94       * @param int $gradeitemid Grade item id
  95       * @param number|null $min Min grade (or null if no min)
  96       * @param number|null $max Max grade (or null if no max)
  97       * @return stdClass Object representing condition
  98       */
  99      public static function get_json($gradeitemid, $min = null, $max = null) {
 100          $result = (object)array('type' => 'grade', 'id' => (int)$gradeitemid);
 101          if (!is_null($min)) {
 102              $result->min = $min;
 103          }
 104          if (!is_null($max)) {
 105              $result->max = $max;
 106          }
 107          return $result;
 108      }
 109  
 110      public function is_available($not, \core_availability\info $info, $grabthelot, $userid) {
 111          $course = $info->get_course();
 112          $score = $this->get_cached_grade_score($this->gradeitemid, $course->id, $grabthelot, $userid);
 113          $allow = $score !== false &&
 114                  (is_null($this->min) || $score >= $this->min) &&
 115                  (is_null($this->max) || $score < $this->max);
 116          if ($not) {
 117              $allow = !$allow;
 118          }
 119  
 120          return $allow;
 121      }
 122  
 123      public function get_description($full, $not, \core_availability\info $info) {
 124          $course = $info->get_course();
 125          // String depends on type of requirement. We are coy about
 126          // the actual numbers, in case grades aren't released to
 127          // students.
 128          if (is_null($this->min) && is_null($this->max)) {
 129              $string = 'any';
 130          } else if (is_null($this->max)) {
 131              $string = 'min';
 132          } else if (is_null($this->min)) {
 133              $string = 'max';
 134          } else {
 135              $string = 'range';
 136          }
 137          if ($not) {
 138              // The specific strings don't make as much sense with 'not'.
 139              if ($string === 'any') {
 140                  $string = 'notany';
 141              } else {
 142                  $string = 'notgeneral';
 143              }
 144          }
 145          $name = self::get_cached_grade_name($course->id, $this->gradeitemid);
 146          return get_string('requires_' . $string, 'availability_grade', $name);
 147      }
 148  
 149      protected function get_debug_string() {
 150          $out = '#' . $this->gradeitemid;
 151          if (!is_null($this->min)) {
 152              $out .= ' >= ' . sprintf('%.5f', $this->min);
 153          }
 154          if (!is_null($this->max)) {
 155              if (!is_null($this->min)) {
 156                  $out .= ',';
 157              }
 158              $out .= ' < ' . sprintf('%.5f', $this->max);
 159          }
 160          return $out;
 161      }
 162  
 163      /**
 164       * Obtains the name of a grade item, also checking that it exists. Uses a
 165       * cache. The name returned is suitable for display.
 166       *
 167       * @param int $courseid Course id
 168       * @param int $gradeitemid Grade item id
 169       * @return string Grade name or empty string if no grade with that id
 170       */
 171      private static function get_cached_grade_name($courseid, $gradeitemid) {
 172          global $DB, $CFG;
 173          require_once($CFG->libdir . '/gradelib.php');
 174  
 175          // Get all grade item names from cache, or using db query.
 176          $cache = \cache::make('availability_grade', 'items');
 177          if (($cacheditems = $cache->get($courseid)) === false) {
 178              // We cache the whole items table not the name; the format_string
 179              // call for the name might depend on current user (e.g. multilang)
 180              // and this is a shared cache.
 181              $cacheditems = $DB->get_records('grade_items', array('courseid' => $courseid));
 182              $cache->set($courseid, $cacheditems);
 183          }
 184  
 185          // Return name from cached item or a lang string.
 186          if (!array_key_exists($gradeitemid, $cacheditems)) {
 187              return get_string('missing', 'availability_grade');
 188          }
 189          $gradeitemobj = $cacheditems[$gradeitemid];
 190          $item = new \grade_item;
 191          \grade_object::set_properties($item, $gradeitemobj);
 192          return $item->get_name();
 193      }
 194  
 195      /**
 196       * Obtains a grade score. Note that this score should not be displayed to
 197       * the user, because gradebook rules might prohibit that. It may be a
 198       * non-final score subject to adjustment later.
 199       *
 200       * @param int $gradeitemid Grade item ID we're interested in
 201       * @param int $courseid Course id
 202       * @param bool $grabthelot If true, grabs all scores for current user on
 203       *   this course, so that later ones come from cache
 204       * @param int $userid Set if requesting grade for a different user (does
 205       *   not use cache)
 206       * @return float Grade score as a percentage in range 0-100 (e.g. 100.0
 207       *   or 37.21), or false if user does not have a grade yet
 208       */
 209      protected static function get_cached_grade_score($gradeitemid, $courseid,
 210              $grabthelot=false, $userid=0) {
 211          global $USER, $DB;
 212          if (!$userid) {
 213              $userid = $USER->id;
 214          }
 215          $cache = \cache::make('availability_grade', 'scores');
 216          if (($cachedgrades = $cache->get($userid)) === false) {
 217              $cachedgrades = array();
 218          }
 219          if (!array_key_exists($gradeitemid, $cachedgrades)) {
 220              if ($grabthelot) {
 221                  // Get all grades for the current course.
 222                  $rs = $DB->get_recordset_sql('
 223                          SELECT
 224                              gi.id,gg.finalgrade,gg.rawgrademin,gg.rawgrademax
 225                          FROM
 226                              {grade_items} gi
 227                              LEFT JOIN {grade_grades} gg ON gi.id=gg.itemid AND gg.userid=?
 228                          WHERE
 229                              gi.courseid = ?', array($userid, $courseid));
 230                  foreach ($rs as $record) {
 231                      if (is_null($record->finalgrade)) {
 232                          // No grade = false.
 233                          $cachedgrades[$record->id] = false;
 234                      } else {
 235                          // Otherwise convert grade to percentage.
 236                          $cachedgrades[$record->id] =
 237                                  (($record->finalgrade - $record->rawgrademin) * 100) /
 238                                  ($record->rawgrademax - $record->rawgrademin);
 239                      }
 240                  }
 241                  $rs->close();
 242                  // And if it's still not set, well it doesn't exist (eg
 243                  // maybe the user set it as a condition, then deleted the
 244                  // grade item) so we call it false.
 245                  if (!array_key_exists($gradeitemid, $cachedgrades)) {
 246                      $cachedgrades[$gradeitemid] = false;
 247                  }
 248              } else {
 249                  // Just get current grade.
 250                  $record = $DB->get_record('grade_grades', array(
 251                      'userid' => $userid, 'itemid' => $gradeitemid));
 252                  if ($record && !is_null($record->finalgrade)) {
 253                      $score = (($record->finalgrade - $record->rawgrademin) * 100) /
 254                          ($record->rawgrademax - $record->rawgrademin);
 255                  } else {
 256                      // Treat the case where row exists but is null, same as
 257                      // case where row doesn't exist.
 258                      $score = false;
 259                  }
 260                  $cachedgrades[$gradeitemid] = $score;
 261              }
 262              $cache->set($userid, $cachedgrades);
 263          }
 264          return $cachedgrades[$gradeitemid];
 265      }
 266  
 267      public function update_after_restore($restoreid, $courseid, \base_logger $logger, $name) {
 268          global $DB;
 269          $rec = \restore_dbops::get_backup_ids_record($restoreid, 'grade_item', $this->gradeitemid);
 270          if (!$rec || !$rec->newitemid) {
 271              // If we are on the same course (e.g. duplicate) then we can just
 272              // use the existing one.
 273              if ($DB->record_exists('grade_items',
 274                      array('id' => $this->gradeitemid, 'courseid' => $courseid))) {
 275                  return false;
 276              }
 277              // Otherwise it's a warning.
 278              $this->gradeitemid = 0;
 279              $logger->process('Restored item (' . $name .
 280                      ') has availability condition on grade that was not restored',
 281                      \backup::LOG_WARNING);
 282          } else {
 283              $this->gradeitemid = (int)$rec->newitemid;
 284          }
 285          return true;
 286      }
 287  
 288      public function update_dependency_id($table, $oldid, $newid) {
 289          if ($table === 'grade_items' && (int)$this->gradeitemid === (int)$oldid) {
 290              $this->gradeitemid = $newid;
 291              return true;
 292          } else {
 293              return false;
 294          }
 295      }
 296  }


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