PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/grade/grade_object.php

https://bitbucket.org/kudutest1/moodlegit
PHP | 441 lines | 208 code | 54 blank | 179 comment | 35 complexity | 369cd13e03cdde5be59a2402cfd8ca43 MD5 | raw file
  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. * Definition of a grade object class for grade item, grade category etc to inherit from
  18. *
  19. * @package core_grades
  20. * @category grade
  21. * @copyright 2006 Nicolas Connault
  22. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23. */
  24. defined('MOODLE_INTERNAL') || die();
  25. /**
  26. * An abstract object that holds methods and attributes common to all grade_* objects defined here.
  27. *
  28. * @package core_grades
  29. * @category grade
  30. * @copyright 2006 Nicolas Connault
  31. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  32. */
  33. abstract class grade_object {
  34. /**
  35. * The database table this grade object is stored in
  36. * @var string $table
  37. */
  38. public $table;
  39. /**
  40. * Array of required table fields, must start with 'id'.
  41. * @var array $required_fields
  42. */
  43. public $required_fields = array('id', 'timecreated', 'timemodified', 'hidden');
  44. /**
  45. * Array of optional fields with default values - usually long text information that is not always needed.
  46. * If you want to create an instance without optional fields use: new grade_object($only_required_fields, false);
  47. * @var array $optional_fields
  48. */
  49. public $optional_fields = array();
  50. /**
  51. * The PK.
  52. * @var int $id
  53. */
  54. public $id;
  55. /**
  56. * The first time this grade_object was created.
  57. * @var int $timecreated
  58. */
  59. public $timecreated;
  60. /**
  61. * The last time this grade_object was modified.
  62. * @var int $timemodified
  63. */
  64. public $timemodified;
  65. /**
  66. * 0 if visible, 1 always hidden or date not visible until
  67. * @var int $hidden
  68. */
  69. var $hidden = 0;
  70. /**
  71. * Constructor. Optionally (and by default) attempts to fetch corresponding row from the database
  72. *
  73. * @param array $params An array with required parameters for this grade object.
  74. * @param bool $fetch Whether to fetch corresponding row from the database or not,
  75. * optional fields might not be defined if false used
  76. */
  77. public function __construct($params=NULL, $fetch=true) {
  78. if (!empty($params) and (is_array($params) or is_object($params))) {
  79. if ($fetch) {
  80. if ($data = $this->fetch($params)) {
  81. grade_object::set_properties($this, $data);
  82. } else {
  83. grade_object::set_properties($this, $this->optional_fields);//apply defaults for optional fields
  84. grade_object::set_properties($this, $params);
  85. }
  86. } else {
  87. grade_object::set_properties($this, $params);
  88. }
  89. } else {
  90. grade_object::set_properties($this, $this->optional_fields);//apply defaults for optional fields
  91. }
  92. }
  93. /**
  94. * Makes sure all the optional fields are loaded.
  95. *
  96. * If id present, meaning the instance exists in the database, then data will be fetched from the database.
  97. * Defaults are used for new instances.
  98. */
  99. public function load_optional_fields() {
  100. global $DB;
  101. foreach ($this->optional_fields as $field=>$default) {
  102. if (property_exists($this, $field)) {
  103. continue;
  104. }
  105. if (empty($this->id)) {
  106. $this->$field = $default;
  107. } else {
  108. $this->$field = $DB->get_field($this->table, $field, array('id', $this->id));
  109. }
  110. }
  111. }
  112. /**
  113. * Finds and returns a grade_object instance based on params.
  114. *
  115. * @static
  116. * @abstract
  117. * @param array $params associative arrays varname=>value
  118. * @return object grade_object instance or false if none found.
  119. */
  120. public static function fetch($params) {
  121. throw new coding_exception('fetch() method needs to be overridden in each subclass of grade_object');
  122. }
  123. /**
  124. * Finds and returns all grade_object instances based on $params.
  125. *
  126. * @static
  127. * @abstract
  128. * @throws coding_exception Throws a coding exception if fetch_all() has not been overriden by the grade object subclass
  129. * @param array $params Associative arrays varname=>value
  130. * @return array|bool Array of grade_object instances or false if none found.
  131. */
  132. public static function fetch_all($params) {
  133. throw new coding_exception('fetch_all() method needs to be overridden in each subclass of grade_object');
  134. }
  135. /**
  136. * Factory method which uses the parameters to retrieve matching instances from the database
  137. *
  138. * @param string $table The table to retrieve from
  139. * @param string $classname The name of the class to instantiate
  140. * @param array $params An array of conditions like $fieldname => $fieldvalue
  141. * @return mixed An object instance or false if not found
  142. */
  143. protected static function fetch_helper($table, $classname, $params) {
  144. if ($instances = grade_object::fetch_all_helper($table, $classname, $params)) {
  145. if (count($instances) > 1) {
  146. // we should not tolerate any errors here - problems might appear later
  147. print_error('morethanonerecordinfetch','debug');
  148. }
  149. return reset($instances);
  150. } else {
  151. return false;
  152. }
  153. }
  154. /**
  155. * Factory method which uses the parameters to retrieve all matching instances from the database
  156. *
  157. * @param string $table The table to retrieve from
  158. * @param string $classname The name of the class to instantiate
  159. * @param array $params An array of conditions like $fieldname => $fieldvalue
  160. * @return array|bool Array of object instances or false if not found
  161. */
  162. public static function fetch_all_helper($table, $classname, $params) {
  163. $instance = new $classname();
  164. $classvars = (array)$instance;
  165. $params = (array)$params;
  166. $wheresql = array();
  167. $newparams = array();
  168. foreach ($params as $var=>$value) {
  169. if (!in_array($var, $instance->required_fields) and !array_key_exists($var, $instance->optional_fields)) {
  170. continue;
  171. }
  172. if (is_null($value)) {
  173. $wheresql[] = " $var IS NULL ";
  174. } else {
  175. $wheresql[] = " $var = ? ";
  176. $newparams[] = $value;
  177. }
  178. }
  179. if (empty($wheresql)) {
  180. $wheresql = '';
  181. } else {
  182. $wheresql = implode("AND", $wheresql);
  183. }
  184. global $DB;
  185. $rs = $DB->get_recordset_select($table, $wheresql, $newparams);
  186. //returning false rather than empty array if nothing found
  187. if (!$rs->valid()) {
  188. $rs->close();
  189. return false;
  190. }
  191. $result = array();
  192. foreach($rs as $data) {
  193. $instance = new $classname();
  194. grade_object::set_properties($instance, $data);
  195. $result[$instance->id] = $instance;
  196. }
  197. $rs->close();
  198. return $result;
  199. }
  200. /**
  201. * Updates this object in the Database, based on its object variables. ID must be set.
  202. *
  203. * @param string $source from where was the object updated (mod/forum, manual, etc.)
  204. * @return bool success
  205. */
  206. public function update($source=null) {
  207. global $USER, $CFG, $DB;
  208. if (empty($this->id)) {
  209. debugging('Can not update grade object, no id!');
  210. return false;
  211. }
  212. $data = $this->get_record_data();
  213. $DB->update_record($this->table, $data);
  214. if (empty($CFG->disablegradehistory)) {
  215. unset($data->timecreated);
  216. $data->action = GRADE_HISTORY_UPDATE;
  217. $data->oldid = $this->id;
  218. $data->source = $source;
  219. $data->timemodified = time();
  220. $data->loggeduser = $USER->id;
  221. $DB->insert_record($this->table.'_history', $data);
  222. }
  223. $this->notify_changed(false);
  224. return true;
  225. }
  226. /**
  227. * Deletes this object from the database.
  228. *
  229. * @param string $source From where was the object deleted (mod/forum, manual, etc.)
  230. * @return bool success
  231. */
  232. public function delete($source=null) {
  233. global $USER, $CFG, $DB;
  234. if (empty($this->id)) {
  235. debugging('Can not delete grade object, no id!');
  236. return false;
  237. }
  238. $data = $this->get_record_data();
  239. if ($DB->delete_records($this->table, array('id'=>$this->id))) {
  240. if (empty($CFG->disablegradehistory)) {
  241. unset($data->id);
  242. unset($data->timecreated);
  243. $data->action = GRADE_HISTORY_DELETE;
  244. $data->oldid = $this->id;
  245. $data->source = $source;
  246. $data->timemodified = time();
  247. $data->loggeduser = $USER->id;
  248. $DB->insert_record($this->table.'_history', $data);
  249. }
  250. $this->notify_changed(true);
  251. return true;
  252. } else {
  253. return false;
  254. }
  255. }
  256. /**
  257. * Returns object with fields and values that are defined in database
  258. *
  259. * @return stdClass
  260. */
  261. public function get_record_data() {
  262. $data = new stdClass();
  263. foreach ($this as $var=>$value) {
  264. if (in_array($var, $this->required_fields) or array_key_exists($var, $this->optional_fields)) {
  265. if (is_object($value) or is_array($value)) {
  266. debugging("Incorrect property '$var' found when inserting grade object");
  267. } else {
  268. $data->$var = $value;
  269. }
  270. }
  271. }
  272. return $data;
  273. }
  274. /**
  275. * Records this object in the Database, sets its id to the returned value, and returns that value.
  276. * If successful this function also fetches the new object data from database and stores it
  277. * in object properties.
  278. *
  279. * @param string $source From where was the object inserted (mod/forum, manual, etc.)
  280. * @return int The new grade object ID if successful, false otherwise
  281. */
  282. public function insert($source=null) {
  283. global $USER, $CFG, $DB;
  284. if (!empty($this->id)) {
  285. debugging("Grade object already exists!");
  286. return false;
  287. }
  288. $data = $this->get_record_data();
  289. $this->id = $DB->insert_record($this->table, $data);
  290. // set all object properties from real db data
  291. $this->update_from_db();
  292. $data = $this->get_record_data();
  293. if (empty($CFG->disablegradehistory)) {
  294. unset($data->timecreated);
  295. $data->action = GRADE_HISTORY_INSERT;
  296. $data->oldid = $this->id;
  297. $data->source = $source;
  298. $data->timemodified = time();
  299. $data->loggeduser = $USER->id;
  300. $DB->insert_record($this->table.'_history', $data);
  301. }
  302. $this->notify_changed(false);
  303. return $this->id;
  304. }
  305. /**
  306. * Using this object's id field, fetches the matching record in the DB, and looks at
  307. * each variable in turn. If the DB has different data, the db's data is used to update
  308. * the object. This is different from the update() function, which acts on the DB record
  309. * based on the object.
  310. *
  311. * @return bool True if successful
  312. */
  313. public function update_from_db() {
  314. if (empty($this->id)) {
  315. 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.");
  316. return false;
  317. }
  318. global $DB;
  319. if (!$params = $DB->get_record($this->table, array('id' => $this->id))) {
  320. debugging("Object with this id:{$this->id} does not exist in table:{$this->table}, can not update from db!");
  321. return false;
  322. }
  323. grade_object::set_properties($this, $params);
  324. return true;
  325. }
  326. /**
  327. * Given an associated array or object, cycles through each key/variable
  328. * and assigns the value to the corresponding variable in this object.
  329. *
  330. * @param stdClass $instance The object to set the properties on
  331. * @param array $params An array of properties to set like $propertyname => $propertyvalue
  332. * @return array|stdClass Either an associative array or an object containing property name, property value pairs
  333. */
  334. public static function set_properties(&$instance, $params) {
  335. $params = (array) $params;
  336. foreach ($params as $var => $value) {
  337. if (in_array($var, $instance->required_fields) or array_key_exists($var, $instance->optional_fields)) {
  338. $instance->$var = $value;
  339. }
  340. }
  341. }
  342. /**
  343. * Called immediately after the object data has been inserted, updated, or
  344. * deleted in the database. Default does nothing, can be overridden to
  345. * hook in special behaviour.
  346. *
  347. * @param bool $deleted
  348. */
  349. function notify_changed($deleted) {
  350. }
  351. /**
  352. * Returns the current hidden state of this grade_item
  353. *
  354. * This depends on the grade object hidden setting and the current time if hidden is set to a "hidden until" timestamp
  355. *
  356. * @return bool Current hidden state
  357. */
  358. function is_hidden() {
  359. return ($this->hidden == 1 or ($this->hidden != 0 and $this->hidden > time()));
  360. }
  361. /**
  362. * Check grade object hidden status
  363. *
  364. * @return bool True if a "hidden until" timestamp is set, false if grade object is set to always visible or always hidden.
  365. */
  366. function is_hiddenuntil() {
  367. return $this->hidden > 1;
  368. }
  369. /**
  370. * Check a grade item hidden status.
  371. *
  372. * @return int 0 means visible, 1 hidden always, a timestamp means "hidden until"
  373. */
  374. function get_hidden() {
  375. return $this->hidden;
  376. }
  377. /**
  378. * Set a grade object hidden status
  379. *
  380. * @param int $hidden 0 means visiable, 1 means hidden always, a timestamp means "hidden until"
  381. * @param bool $cascade Ignored
  382. */
  383. function set_hidden($hidden, $cascade=false) {
  384. $this->hidden = $hidden;
  385. $this->update();
  386. }
  387. }