Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
<?php// This file is part of Moodle - http://moodle.org///// Moodle is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Moodle is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Moodle. If not, see <http://www.gnu.org/licenses/>./*** Definition of a grade object class for grade item, grade category etc to inherit from** @package core_grades* @category grade* @copyright 2006 Nicolas Connault* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/defined('MOODLE_INTERNAL') || die();/*** An abstract object that holds methods and attributes common to all grade_* objects defined here.** @package core_grades* @category grade* @copyright 2006 Nicolas Connault* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/abstract class grade_object {/*** The database table this grade object is stored in* @var string $table*/public $table;/*** Array of required table fields, must start with 'id'.* @var array $required_fields*/public $required_fields = array('id', 'timecreated', 'timemodified', 'hidden');/*** Array of optional fields with default values - usually long text information that is not always needed.* If you want to create an instance without optional fields use: new grade_object($only_required_fields, false);* @var array $optional_fields*/public $optional_fields = array();/*** The PK.* @var int $id*/public $id;/*** The first time this grade_object was created.* @var int $timecreated*/public $timecreated;/*** The last time this grade_object was modified.* @var int $timemodified*/public $timemodified;/*** 0 if visible, 1 always hidden or date not visible until* @var int $hidden*/var $hidden = 0;/*** Constructor. Optionally (and by default) attempts to fetch corresponding row from the database** @param array $params An array with required parameters for this grade object.* @param bool $fetch Whether to fetch corresponding row from the database or not,* optional fields might not be defined if false used*/public function __construct($params=NULL, $fetch=true) {if (!empty($params) and (is_array($params) or is_object($params))) {if ($fetch) {if ($data = $this->fetch($params)) {grade_object::set_properties($this, $data);} else {grade_object::set_properties($this, $this->optional_fields);//apply defaults for optional fieldsgrade_object::set_properties($this, $params);}} else {grade_object::set_properties($this, $params);}} else {grade_object::set_properties($this, $this->optional_fields);//apply defaults for optional fields}}/*** Makes sure all the optional fields are loaded.** If id present, meaning the instance exists in the database, then data will be fetched from the database.* Defaults are used for new instances.*/public function load_optional_fields() {global $DB;foreach ($this->optional_fields as $field=>$default) {if (property_exists($this, $field)) {continue;}if (empty($this->id)) {$this->$field = $default;} else {$this->$field = $DB->get_field($this->table, $field, array('id', $this->id));}}}/*** Finds and returns a grade_object instance based on params.** @static* @abstract* @param array $params associative arrays varname=>value* @return object grade_object instance or false if none found.*/public static function fetch($params) {throw new coding_exception('fetch() method needs to be overridden in each subclass of grade_object');}/*** Finds and returns all grade_object instances based on $params.** @static* @abstract* @throws coding_exception Throws a coding exception if fetch_all() has not been overriden by the grade object subclass* @param array $params Associative arrays varname=>value* @return array|bool Array of grade_object instances or false if none found.*/public static function fetch_all($params) {throw new coding_exception('fetch_all() method needs to be overridden in each subclass of grade_object');}/*** Factory method which uses the parameters to retrieve matching instances from the database** @param string $table The table to retrieve from* @param string $classname The name of the class to instantiate* @param array $params An array of conditions like $fieldname => $fieldvalue* @return mixed An object instance or false if not found*/protected static function fetch_helper($table, $classname, $params) {if ($instances = grade_object::fetch_all_helper($table, $classname, $params)) {if (count($instances) > 1) {// we should not tolerate any errors here - problems might appear laterthrow new \moodle_exception('morethanonerecordinfetch', 'debug');}return reset($instances);} else {return false;}}/*** Factory method which uses the parameters to retrieve all matching instances from the database** @param string $table The table to retrieve from* @param string $classname The name of the class to instantiate* @param array $params An array of conditions like $fieldname => $fieldvalue* @return array|bool Array of object instances or false if not found*/public static function fetch_all_helper($table, $classname, $params) {global $DB; // Need to introspect DB here.$instance = new $classname();$classvars = (array)$instance;$params = (array)$params;$wheresql = array();$newparams = array();$columns = $DB->get_columns($table); // Cached, no worries.foreach ($params as $var=>$value) {if (!in_array($var, $instance->required_fields) and !array_key_exists($var, $instance->optional_fields)) {continue;}if (!array_key_exists($var, $columns)) {continue;}if (is_null($value)) {$wheresql[] = " $var IS NULL ";} else {if ($columns[$var]->meta_type === 'X') {// We have a text/clob column, use the cross-db method for its comparison.$wheresql[] = ' ' . $DB->sql_compare_text($var) . ' = ' . $DB->sql_compare_text('?') . ' ';} else {// Other columns (varchar, integers...).$wheresql[] = " $var = ? ";}$newparams[] = $value;}}if (empty($wheresql)) {$wheresql = '';} else {$wheresql = implode("AND", $wheresql);}global $DB;$rs = $DB->get_recordset_select($table, $wheresql, $newparams);//returning false rather than empty array if nothing foundif (!$rs->valid()) {$rs->close();return false;}$result = array();foreach($rs as $data) {$instance = new $classname();grade_object::set_properties($instance, $data);$result[$instance->id] = $instance;}$rs->close();return $result;}/*** Updates this object in the Database, based on its object variables. ID must be set.** @param string $source from where was the object updated (mod/forum, manual, etc.)* @param bool $isbulkupdate If bulk grade update is happening.* @return bool success*/public function update($source = null, $isbulkupdate = false) {global $USER, $CFG, $DB;if (empty($this->id)) {debugging('Can not update grade object, no id!');return false;}$data = $this->get_record_data();$DB->update_record($this->table, $data);$historyid = null;if (empty($CFG->disablegradehistory)) {unset($data->timecreated);$data->action = GRADE_HISTORY_UPDATE;$data->oldid = $this->id;$data->source = $source;$data->timemodified = time();$data->loggeduser = $USER->id;$historyid = $DB->insert_record($this->table.'_history', $data);}$this->notify_changed(false, $isbulkupdate);$this->update_feedback_files($historyid);return true;}/*** Deletes this object from the database.** @param string $source From where was the object deleted (mod/forum, manual, etc.)* @return bool success*/public function delete($source=null) {global $USER, $CFG, $DB;if (empty($this->id)) {debugging('Can not delete grade object, no id!');return false;}$data = $this->get_record_data();if ($DB->delete_records($this->table, array('id'=>$this->id))) {if (empty($CFG->disablegradehistory)) {unset($data->id);unset($data->timecreated);$data->action = GRADE_HISTORY_DELETE;$data->oldid = $this->id;$data->source = $source;$data->timemodified = time();$data->loggeduser = $USER->id;$DB->insert_record($this->table.'_history', $data);}$this->notify_changed(true);$this->delete_feedback_files();return true;} else {return false;}}/*** Returns object with fields and values that are defined in database** @return stdClass*/public function get_record_data() {$data = new stdClass();foreach ($this as $var=>$value) {if (in_array($var, $this->required_fields) or array_key_exists($var, $this->optional_fields)) {if (is_object($value) or is_array($value)) {debugging("Incorrect property '$var' found when inserting grade object");} else {$data->$var = $value;}}}return $data;}/*** Records this object in the Database, sets its id to the returned value, and returns that value.* If successful this function also fetches the new object data from database and stores it* in object properties.** @param string $source From where was the object inserted (mod/forum, manual, etc.)* @param string $isbulkupdate If bulk grade update is happening.* @return int The new grade object ID if successful, false otherwise*/public function insert($source = null, $isbulkupdate = false) {global $USER, $CFG, $DB;if (!empty($this->id)) {debugging("Grade object already exists!");return false;}$data = $this->get_record_data();$this->id = $DB->insert_record($this->table, $data);// set all object properties from real db data$this->update_from_db();$data = $this->get_record_data();$historyid = null;if (empty($CFG->disablegradehistory)) {unset($data->timecreated);$data->action = GRADE_HISTORY_INSERT;$data->oldid = $this->id;$data->source = $source;$data->timemodified = time();$data->loggeduser = $USER->id;$historyid = $DB->insert_record($this->table.'_history', $data);}$this->notify_changed(false, $isbulkupdate);$this->add_feedback_files($historyid);return $this->id;}/*** Using this object's id field, fetches the matching record in the DB, and looks at* each variable in turn. If the DB has different data, the db's data is used to update* the object. This is different from the update() function, which acts on the DB record* based on the object.** @return bool True if successful*/public function update_from_db() {if (empty($this->id)) {debugging("The object could not be used in its state to retrieve a matching record from the DB, because its id field is not set.");return false;}global $DB;if (!$params = $DB->get_record($this->table, array('id' => $this->id))) {debugging("Object with this id:{$this->id} does not exist in table:{$this->table}, can not update from db!");return false;}grade_object::set_properties($this, $params);return true;}/*** Given an associated array or object, cycles through each key/variable* and assigns the value to the corresponding variable in this object.** @param grade_object $instance The object to set the properties on* @param array $params An array of properties to set like $propertyname => $propertyvalue* @return array|stdClass Either an associative array or an object containing property name, property value pairs*/public static function set_properties(&$instance, $params) {$params = (array) $params;foreach ($params as $var => $value) {if (in_array($var, $instance->required_fields) or array_key_exists($var, $instance->optional_fields)) {$instance->$var = $value;}}}/*** Called immediately after the object data has been inserted, updated, or* deleted in the database. Default does nothing, can be overridden to* hook in special behaviour.** @param bool $deleted*/protected function notify_changed($deleted) {}/*** Handles adding feedback files in the gradebook.** @param int|null $historyid*/protected function add_feedback_files(int $historyid = null) {}/*** Handles updating feedback files in the gradebook.** @param int|null $historyid*/protected function update_feedback_files(int $historyid = null) {}/*** Handles deleting feedback files in the gradebook.*/protected function delete_feedback_files() {}/*** Returns the current hidden state of this grade_item** This depends on the grade object hidden setting and the current time if hidden is set to a "hidden until" timestamp** @return bool Current hidden state*/function is_hidden() {return ($this->hidden == 1 or ($this->hidden != 0 and $this->hidden > time()));}/*** Check grade object hidden status** @return bool True if a "hidden until" timestamp is set, false if grade object is set to always visible or always hidden.*/function is_hiddenuntil() {return $this->hidden > 1;}/*** Check a grade item hidden status.** @return int 0 means visible, 1 hidden always, a timestamp means "hidden until"*/function get_hidden() {return $this->hidden;}/*** Set a grade object hidden status** @param int $hidden 0 means visiable, 1 means hidden always, a timestamp means "hidden until"* @param bool $cascade Ignored*/function set_hidden($hidden, $cascade=false) {$this->hidden = $hidden;$this->update();}/*** Returns whether the grade object can control the visibility of the grades.** @return bool*/public function can_control_visibility() {return true;}}