MDL-30995 Completion Fixedup some more PHP DOC issues
[moodle.git] / lib / completion / data_object.php
CommitLineData
2be4d090 1<?php
836375ec
SH
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/>.
2be4d090 16
836375ec
SH
17/**
18 * Course completion critieria aggregation
19 *
20 * @package core_completion
21 * @category completion
22 * @copyright 2009 Catalyst IT Ltd
23 * @author Aaron Barnes <aaronb@catalyst.net.nz>
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26
27defined('MOODLE_INTERNAL') || die();
2be4d090
MD
28
29/**
30 * A data abstraction object that holds methods and attributes
836375ec
SH
31 *
32 * @package core_completion
33 * @category completion
34 * @copyright 2009 Catalyst IT Ltd
35 * @author Aaron Barnes <aaronb@catalyst.net.nz>
36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2be4d090
MD
37 */
38abstract class data_object {
836375ec 39
95dd54ee 40 /* @var string Table that the class maps to in the database */
2be4d090
MD
41 public $table;
42
95dd54ee 43 /* @var array Array of required table fields, must start with 'id'. */
2be4d090
MD
44 public $required_fields = array('id');
45
46 /**
47 * Array of optional fields with default values - usually long text information that is not always needed.
48 * If you want to create an instance without optional fields use: new data_object($only_required_fields, false);
836375ec 49 * @var array
2be4d090
MD
50 */
51 public $optional_fields = array();
52
95dd54ee 53 /* @var int The primary key */
2be4d090
MD
54 public $id;
55
56 /**
57 * Constructor. Optionally (and by default) attempts to fetch corresponding row from DB.
836375ec 58 *
2be4d090 59 * @param array $params an array with required parameters for this data object.
836375ec 60 * @param bool $fetch Whether to fetch corresponding row from DB or not,
2be4d090
MD
61 * optional fields might not be defined if false used
62 */
836375ec 63 public function __construct($params = NULL, $fetch = true) {
2be4d090
MD
64 if (!empty($params) and (is_array($params) or is_object($params))) {
65 if ($fetch) {
66 if ($data = $this->fetch($params)) {
67 self::set_properties($this, $data);
68 } else {
69 self::set_properties($this, $this->optional_fields);//apply defaults for optional fields
70 self::set_properties($this, $params);
71 }
72
73 } else {
74 self::set_properties($this, $params);
75 }
76
77 } else {
78 self::set_properties($this, $this->optional_fields);//apply defaults for optional fields
79 }
80 }
81
82 /**
83 * Makes sure all the optional fields are loaded.
836375ec 84 *
2be4d090
MD
85 * If id present (==instance exists in db) fetches data from db.
86 * Defaults are used for new instances.
87 */
88 public function load_optional_fields() {
89 global $DB;
90 foreach ($this->optional_fields as $field=>$default) {
4cc977a6 91 if (property_exists($this, $field)) {
2be4d090
MD
92 continue;
93 }
94 if (empty($this->id)) {
95 $this->$field = $default;
96 } else {
97 $this->$field = $DB->get_field($this->table, $field, array('id', $this->id));
98 }
99 }
100 }
101
102 /**
103 * Finds and returns a data_object instance based on params.
2be4d090 104 *
836375ec
SH
105 * This function MUST be overridden by all deriving classes.
106 *
107 * @param array $params associative arrays varname => value
108 * @throws coding_exception This function MUST be overridden
109 * @return data_object instance of data_object or false if none found.
2be4d090 110 */
7c109ea3
PS
111 public static function fetch($params) {
112 throw new coding_exception('fetch() method needs to be overridden in each subclass of data_object');
113 }
2be4d090
MD
114
115 /**
116 * Finds and returns all data_object instances based on params.
117 *
836375ec
SH
118 * This function MUST be overridden by all deriving classes.
119 *
120 * @param array $params associative arrays varname => value
121 * @throws coding_exception This function MUST be overridden
7c109ea3 122 * @return array array of data_object instances or false if none found.
2be4d090 123 */
7c109ea3
PS
124 public static function fetch_all($params) {
125 throw new coding_exception('fetch_all() method needs to be overridden in each subclass of data_object');
126 }
2be4d090
MD
127
128 /**
129 * Factory method - uses the parameters to retrieve matching instance from the DB.
836375ec
SH
130 *
131 * @final
132 * @param string $table The table name to fetch from
133 * @param string $classname The class that you want the result instantiated as
134 * @param array $params Any params required to select the desired row
135 * @return object Instance of $classname or false.
2be4d090
MD
136 */
137 protected static function fetch_helper($table, $classname, $params) {
138 if ($instances = self::fetch_all_helper($table, $classname, $params)) {
139 if (count($instances) > 1) {
140 // we should not tolerate any errors here - problems might appear later
141 print_error('morethanonerecordinfetch','debug');
142 }
143 return reset($instances);
144 } else {
145 return false;
146 }
147 }
148
149 /**
150 * Factory method - uses the parameters to retrieve all matching instances from the DB.
836375ec
SH
151 *
152 * @final
153 * @param string $table The table name to fetch from
154 * @param string $classname The class that you want the result instantiated as
155 * @param array $params Any params required to select the desired row
2be4d090
MD
156 * @return mixed array of object instances or false if not found
157 */
158 public static function fetch_all_helper($table, $classname, $params) {
159 $instance = new $classname();
160
161 $classvars = (array)$instance;
162 $params = (array)$params;
163
164 $wheresql = array();
165
166 foreach ($params as $var=>$value) {
167 if (!in_array($var, $instance->required_fields) and !array_key_exists($var, $instance->optional_fields)) {
168 continue;
169 }
170 if (is_null($value)) {
171 $wheresql[] = " $var IS NULL ";
172 } else {
173 $wheresql[] = " $var = ? ";
174 $params[] = $value;
175 }
176 }
177
178 if (empty($wheresql)) {
179 $wheresql = '';
180 } else {
181 $wheresql = implode("AND", $wheresql);
182 }
183
184 global $DB;
185 if ($datas = $DB->get_records_select($table, $wheresql, $params)) {
6142a4a5 186
2be4d090
MD
187 $result = array();
188 foreach($datas as $data) {
189 $instance = new $classname();
190 self::set_properties($instance, $data);
191 $result[$instance->id] = $instance;
192 }
193 return $result;
194
195 } else {
6142a4a5 196
2be4d090
MD
197 return false;
198 }
199 }
200
201 /**
202 * Updates this object in the Database, based on its object variables. ID must be set.
836375ec 203 *
95dd54ee 204 * @return bool success
2be4d090
MD
205 */
206 public function update() {
207 global $DB;
208
209 if (empty($this->id)) {
210 debugging('Can not update data object, no id!');
211 return false;
212 }
213
214 $data = $this->get_record_data();
215
216 $DB->update_record($this->table, $data);
217
218 $this->notify_changed(false);
219 return true;
220 }
221
222 /**
223 * Deletes this object from the database.
836375ec 224 *
95dd54ee 225 * @return bool success
2be4d090
MD
226 */
227 public function delete() {
228 global $DB;
229
230 if (empty($this->id)) {
231 debugging('Can not delete data object, no id!');
232 return false;
233 }
234
235 $data = $this->get_record_data();
236
237 if ($DB->delete_records($this->table, array('id'=>$this->id))) {
238 $this->notify_changed(true);
239 return true;
240
241 } else {
242 return false;
243 }
244 }
245
246 /**
247 * Returns object with fields and values that are defined in database
836375ec
SH
248 *
249 * @return stdClass
2be4d090
MD
250 */
251 public function get_record_data() {
365a5941 252 $data = new stdClass();
2be4d090
MD
253
254 foreach ($this as $var=>$value) {
255 if (in_array($var, $this->required_fields) or array_key_exists($var, $this->optional_fields)) {
256 if (is_object($value) or is_array($value)) {
257 debugging("Incorrect property '$var' found when inserting data object");
258 } else {
259 $data->$var = $value;
260 }
261 }
262 }
263 return $data;
264 }
265
266 /**
267 * Records this object in the Database, sets its id to the returned value, and returns that value.
268 * If successful this function also fetches the new object data from database and stores it
269 * in object properties.
836375ec 270 *
2be4d090
MD
271 * @return int PK ID if successful, false otherwise
272 */
273 public function insert() {
274 global $DB;
275
276 if (!empty($this->id)) {
277 debugging("Data object already exists!");
278 return false;
279 }
280
281 $data = $this->get_record_data();
282
283 $this->id = $DB->insert_record($this->table, $data);
284
285 // set all object properties from real db data
286 $this->update_from_db();
287
288 $this->notify_changed(false);
289 return $this->id;
290 }
291
292 /**
293 * Using this object's id field, fetches the matching record in the DB, and looks at
294 * each variable in turn. If the DB has different data, the db's data is used to update
295 * the object. This is different from the update() function, which acts on the DB record
296 * based on the object.
836375ec
SH
297 *
298 * @return bool True for success, false otherwise.
2be4d090
MD
299 */
300 public function update_from_db() {
301 if (empty($this->id)) {
302 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.");
303 return false;
304 }
305 global $DB;
306 if (!$params = $DB->get_record($this->table, array('id' => $this->id))) {
307 debugging("Object with this id:{$this->id} does not exist in table:{$this->table}, can not update from db!");
308 return false;
309 }
310
311 self::set_properties($this, $params);
312
313 return true;
314 }
315
316 /**
317 * Given an associated array or object, cycles through each key/variable
318 * and assigns the value to the corresponding variable in this object.
836375ec
SH
319 *
320 * @final
321 * @param data_object $instance
322 * @param array $params
2be4d090
MD
323 */
324 public static function set_properties(&$instance, $params) {
325 $params = (array) $params;
326 foreach ($params as $var => $value) {
327 if (in_array($var, $instance->required_fields) or array_key_exists($var, $instance->optional_fields)) {
328 $instance->$var = $value;
329 }
330 }
331 }
332
333 /**
6142a4a5
PS
334 * Called immediately after the object data has been inserted, updated, or
335 * deleted in the database. Default does nothing, can be overridden to
2be4d090
MD
336 * hook in special behaviour.
337 *
836375ec 338 * @param bool $deleted Set this to true if it has been deleted.
2be4d090 339 */
95dd54ee 340 public function notify_changed($deleted) {}
836375ec 341}