Contains database functions split-off from moodlelib, just so you can see
[moodle.git] / lib / database.php
CommitLineData
df28d6c5 1<?PHP // $Id$
2
3/// FUNCTIONS FOR DATABASE HANDLING ////////////////////////////////
4
5function execute_sql($command, $feedback=true) {
6/// Completely general function - it just runs some SQL and reports success.
7
8 global $db;
9
10 $result = $db->Execute("$command");
11
12 if ($result) {
13 if ($feedback) {
14 echo "<P><FONT COLOR=green><B>".get_string("success")."</B></FONT></P>";
15 }
16 return true;
17 } else {
18 if ($feedback) {
19 echo "<P><FONT COLOR=red><B>".get_string("error")."</B></FONT></P>";
20 }
21 return false;
22 }
23}
24
25function modify_database($sqlfile) {
26/// Assumes that the input text file consists of a number
27/// of SQL statements ENDING WITH SEMICOLONS. The semicolons
28/// MUST be the last character in a line.
29/// Lines that are blank or that start with "#" are ignored.
30/// Only tested with mysql dump files (mysqldump -p -d moodle)
31
32 global $CFG;
33
34 if (file_exists($sqlfile)) {
35 $success = true;
36 $lines = file($sqlfile);
37 $command = "";
38
39 while ( list($i, $line) = each($lines) ) {
40 $line = chop($line);
41 $length = strlen($line);
42
43 if ($length && substr($line, 0, 1) <> "#") {
44 if (substr($line, $length-1, 1) == ";") {
45 $line = substr($line, 0, $length-1); // strip ;
46 $command .= $line;
47 $command = str_replace("prefix_", $CFG->prefix, $command); // Table prefixes
48 if (! execute_sql($command)) {
49 $success = false;
50 }
51 $command = "";
52 } else {
53 $command .= $line;
54 }
55 }
56 }
57
58 } else {
59 $success = false;
60 echo "<P>Tried to modify database, but \"$sqlfile\" doesn't exist!</P>";
61 }
62
63 return $success;
64}
65
66
67function record_exists($table, $field="", $value="", $field2="", $value2="", $field3="", $value3="") {
68/// Returns true or false depending on whether the specified record exists
69
70 global $CFG;
71
72 if ($field and $value) {
73 $select = "WHERE $field = '$value'";
74 if ($field2 and $value2) {
75 $select .= " AND $field2 = '$value2'";
76 if ($field3 and $value3) {
77 $select .= " AND $field3 = '$value3'";
78 }
79 }
80 }
81
82 return record_exists_sql("SELECT * FROM $CFG->prefix$table $select LIMIT 1");
83}
84
85
86function record_exists_sql($sql) {
87/// Returns true or false depending on whether the specified record exists
88/// The sql statement is provided as a string.
89
90 global $db;
91
92 $rs = $db->Execute($sql);
93 if (!$rs) return false;
94
95 if ( $rs->RecordCount() ) {
96 return true;
97 } else {
98 return false;
99 }
100}
101
102
103function count_records($table, $field="", $value="", $field2="", $value2="", $field3="", $value3="") {
104/// Get all the records and count them
105
106 global $CFG;
107
108 if ($field and $value) {
109 $select = "WHERE $field = '$value'";
110 if ($field2 and $value2) {
111 $select .= " AND $field2 = '$value2'";
112 if ($field3 and $value3) {
113 $select .= " AND $field3 = '$value3'";
114 }
115 }
116 }
117
118 return count_records_sql("SELECT COUNT(*) FROM $CFG->prefix$table $select");
119}
120
121function count_records_sql($sql) {
122/// Get all the records and count them
123/// The sql statement is provided as a string.
124
125 global $db;
126
127 $rs = $db->Execute("$sql");
128 if (!$rs) return 0;
129
130 return $rs->fields[0];
131}
132
133function get_record($table, $field, $value, $field2="", $value2="", $field3="", $value3="") {
134/// Get a single record as an object
135
136 global $CFG;
137
138 $select = "WHERE $field = '$value'";
139
140 if ($field2 and $value2) {
141 $select .= " AND $field2 = '$value2'";
142 if ($field3 and $value3) {
143 $select .= " AND $field3 = '$value3'";
144 }
145 }
146
147 return get_record_sql("SELECT * FROM $CFG->prefix$table $select");
148}
149
150function get_record_sql($sql) {
151/// Get a single record as an object
152/// The sql statement is provided as a string.
153
154 global $db;
155
156 $rs = $db->Execute("$sql");
157 if (!$rs) return false;
158
159 if ( $rs->RecordCount() == 1 ) {
160 return (object)$rs->fields;
161 } else {
162 return false;
163 }
164}
165
166function get_records($table, $field="", $value="", $sort="", $fields="*") {
167/// Get a number of records as an array of objects
168/// Can optionally be sorted eg "time ASC" or "time DESC"
169/// If "fields" is specified, only those fields are returned
170/// The "key" is the first column returned, eg usually "id"
171
172 global $CFG;
173
174 if ($field and $value) {
175 $select = "WHERE $field = '$value'";
176 }
177 if ($sort) {
178 $sortorder = "ORDER BY $sort";
179 }
180
181 return get_records_sql("SELECT $fields FROM $CFG->prefix$table $select $sortorder");
182}
183
184
185function get_records_list($table, $field="", $values="", $sort="", $fields="*") {
186// Get a number of records as an array of objects
187// Differs from get_records() in that the values variable
188// can be a comma-separated list of values eg "4,5,6,10"
189// Can optionally be sorted eg "time ASC" or "time DESC"
190// The "key" is the first column returned, eg usually "id"
191
192 global $CFG;
193
194 if ($field and $value) {
195 $select = "WHERE $field in ($values)";
196 }
197 if ($sort) {
198 $sortorder = "ORDER BY $sort";
199 }
200
201 return get_records_sql("SELECT $fields FROM $CFG->prefix$table $select $sortorder");
202}
203
204
205function get_records_sql($sql) {
206// Get a number of records as an array of objects
207// The "key" is the first column returned, eg usually "id"
208// The sql statement is provided as a string.
209
210 global $db;
211
212 $rs = $db->Execute("$sql");
213 if (!$rs) return false;
214
215 if ( $rs->RecordCount() > 0 ) {
216 if ($records = $rs->GetAssoc(true)) {
217 foreach ($records as $key => $record) {
218 $objects[$key] = (object) $record;
219 }
220 return $objects;
221 } else {
222 return false;
223 }
224 } else {
225 return false;
226 }
227}
228
229function get_records_sql_menu($sql) {
230// Given an SQL select, this function returns an associative
231// array of the first two columns. This is most useful in
232// combination with the choose_from_menu function to create
233// a form menu.
234
235 global $db;
236
237 $rs = $db->Execute("$sql");
238 if (!$rs) return false;
239
240 if ( $rs->RecordCount() > 0 ) {
241 while (!$rs->EOF) {
242 $menu[$rs->fields[0]] = $rs->fields[1];
243 $rs->MoveNext();
244 }
245 return $menu;
246
247 } else {
248 return false;
249 }
250}
251
252function get_field($table, $return, $field, $value) {
253/// Get a single field from a database record
254
255 global $db, $CFG;
256
257 $rs = $db->Execute("SELECT $return FROM $CFG->prefix$table WHERE $field = '$value'");
258 if (!$rs) return false;
259
260 if ( $rs->RecordCount() == 1 ) {
261 return $rs->fields["$return"];
262 } else {
263 return false;
264 }
265}
266
267function set_field($table, $newfield, $newvalue, $field, $value) {
268/// Set a single field in a database record
269
270 global $db, $CFG;
271
272 return $db->Execute("UPDATE $CFG->prefix$table SET $newfield = '$newvalue' WHERE $field = '$value'");
273}
274
275
276function delete_records($table, $field="", $value="", $field2="", $value2="", $field3="", $value3="") {
277/// Delete one or more records from a table
278
279 global $db, $CFG;
280
281 if ($field and $value) {
282 $select = "WHERE $field = '$value'";
283 if ($field2 and $value2) {
284 $select .= " AND $field2 = '$value2'";
285 if ($field3 and $value3) {
286 $select .= " AND $field3 = '$value3'";
287 }
288 }
289 }
290
291 return $db->Execute("DELETE FROM $CFG->prefix$table $select");
292}
293
294
295function insert_record($table, $dataobject, $returnid=true) {
296/// Insert a record into a table and return the "id" field if required
297/// If the return ID isn't required, then this just reports success as true/false.
298/// $dataobject is an object containing needed data
299
300 global $db, $CFG;
301
302 // Determine all the fields needed
303 if (! $columns = $db->MetaColumns("$CFG->prefix$table")) {
304 return false;
305 }
306
307 $data = (array)$dataobject;
308
309 // Pull out data matching these fields
310 foreach ($columns as $column) {
311 if ($column->name <> "id" && isset($data[$column->name]) ) {
312 $ddd[$column->name] = $data[$column->name];
313 }
314 }
315
316 // Construct SQL queries
317 if (! $numddd = count($ddd)) {
318 return false;
319 }
320
321 $count = 0;
322 $inscolumns = "";
323 $insvalues = "";
324 $select = "";
325
326 foreach ($ddd as $key => $value) {
327 $count++;
328 $inscolumns .= "$key";
329 $insvalues .= "'$value'";
330 $select .= "$key = '$value'";
331 if ($count < $numddd) {
332 $inscolumns .= ", ";
333 $insvalues .= ", ";
334 $select .= " AND ";
335 }
336 }
337
338 if (! $rs = $db->Execute("INSERT INTO $CFG->prefix$table ($inscolumns) VALUES ($insvalues)")) {
339 return false;
340 }
341
342 if ($returnid) {
343 // Pull it out again to find the id. This is the most cross-platform method.
344 if ($rs = $db->Execute("SELECT id FROM $CFG->prefix$table WHERE $select")) {
345 return $rs->fields[0];
346 } else {
347 return false;
348 }
349 } else {
350 return true;
351 }
352}
353
354
355function update_record($table, $dataobject) {
356/// Update a record in a table
357/// $dataobject is an object containing needed data
358
359 global $db, $CFG;
360
361 if (! isset($dataobject->id) ) {
362 return false;
363 }
364
365 // Determine all the fields in the table
366 if (!$columns = $db->MetaColumns("$CFG->prefix$table")) {
367 return false;
368 }
369 $data = (array)$dataobject;
370
371 // Pull out data matching these fields
372 foreach ($columns as $column) {
373 if ($column->name <> "id" && isset($data[$column->name]) ) {
374 $ddd[$column->name] = $data[$column->name];
375 }
376 }
377
378 // Construct SQL queries
379 $numddd = count($ddd);
380 $count = 0;
381 $update = "";
382
383 foreach ($ddd as $key => $value) {
384 $count++;
385 $update .= "$key = '$value'";
386 if ($count < $numddd) {
387 $update .= ", ";
388 }
389 }
390
391 if ($rs = $db->Execute("UPDATE $CFG->prefix$table SET $update WHERE id = '$dataobject->id'")) {
392 return true;
393 } else {
394 return false;
395 }
396}
397
398
399function print_object($object) {
400/// Mostly just for debugging
401
402 $array = (array)$object;
403 foreach ($array as $key => $item) {
404 echo "$key -> $item <BR>";
405 }
406}
407
408
409
410
411/// USER DATABASE ////////////////////////////////////////////////
412
413function get_user_info_from_db($field, $value) {
414/// Get a complete user record, which includes all the info
415/// in the user record, as well as membership information
416/// Suitable for setting as $USER session cookie.
417
418 global $db, $CFG;
419
420 if (!$field || !$value)
421 return false;
422
423 if (! $result = $db->Execute("SELECT * FROM {$CFG->prefix}user WHERE $field = '$value' AND deleted <> '1'")) {
424 error("Could not find any active users!");
425 }
426
427 if ( $result->RecordCount() == 1 ) {
428 $user = (object)$result->fields;
429
430 $rs = $db->Execute("SELECT course FROM {$CFG->prefix}user_students WHERE user = '$user->id' ");
431 while (!$rs->EOF) {
432 $course = $rs->fields["course"];
433 $user->student["$course"] = true;
434 $rs->MoveNext();
435 }
436
437 $rs = $db->Execute("SELECT course FROM {$CFG->prefix}user_teachers WHERE user = '$user->id' ");
438 while (!$rs->EOF) {
439 $course = $rs->fields["course"];
440 $user->teacher["$course"] = true;
441 $rs->MoveNext();
442 }
443
444 $rs = $db->Execute("SELECT * FROM {$CFG->prefix}user_admins WHERE user = '$user->id' ");
445 while (!$rs->EOF) {
446 $user->admin = true;
447 $rs->MoveNext();
448 }
449
450 if ($course = get_site()) {
451 // Everyone is always a member of the top course
452 $user->student["$course->id"] = true;
453 }
454
455 return $user;
456
457 } else {
458 return false;
459 }
460}
461
462function update_user_in_db() {
463/// Updates user record to record their last access
464
465 global $db, $USER, $REMOTE_ADDR, $CFG;
466
467 if (!isset($USER->id))
468 return false;
469
470 $timenow = time();
471 if ($db->Execute("UPDATE {$CFG->prefix}user SET lastIP='$REMOTE_ADDR', lastaccess='$timenow'
472 WHERE id = '$USER->id' ")) {
473 return true;
474 } else {
475 return false;
476 }
477}
478
479
480function adminlogin($username, $md5password) {
481/// Does this username and password specify a valid admin user?
482
483 global $CFG;
484
485 return record_exists_sql("SELECT u.id FROM {$CFG->prefix}user u, {$CFG->prefix}user_admins a
486 WHERE u.id = a.user
487 AND u.username = '$username'
488 AND u.password = '$md5password'");
489}
490
491
492function get_site () {
493/// Returns $course object of the top-level site.
494
495 if ( $course = get_record("course", "category", 0)) {
496 return $course;
497 } else {
498 return false;
499 }
500}
501
502function get_admin () {
503/// Returns $user object of the main admin user
504
505 global $CFG;
506
507 if ( $admins = get_admins() ) {
508 foreach ($admins as $admin) {
509 return $admin; // ie the first one
510 }
511 } else {
512 return false;
513 }
514}
515
516function get_admins() {
517/// Returns list of all admins
518
519 global $CFG;
520
521 return get_records_sql("SELECT u.* FROM {$CFG->prefix}user u, {$CFG->prefix}user_admins a
522 WHERE a.user = u.id
523 ORDER BY u.id ASC");
524}
525
526
527function get_teacher($courseid) {
528/// Returns $user object of the main teacher for a course
529
530 global $CFG;
531
532 if ( $teachers = get_course_teachers($courseid, "t.authority ASC")) {
533 foreach ($teachers as $teacher) {
534 if ($teacher->authority) {
535 return $teacher; // the highest authority teacher
536 }
537 }
538 } else {
539 return false;
540 }
541}
542
543function get_course_students($courseid, $sort="u.lastaccess DESC") {
544/// Returns list of all students in this course
545
546 global $CFG;
547
548 return get_records_sql("SELECT u.* FROM {$CFG->prefix}user u, {$CFG->prefix}user_students s
549 WHERE s.course = '$courseid' AND s.user = u.id AND u.deleted = '0'
550 ORDER BY $sort");
551}
552
553function get_course_teachers($courseid, $sort="t.authority ASC") {
554/// Returns list of all teachers in this course
555
556 global $CFG;
557
558 return get_records_sql("SELECT u.*,t.authority,t.role FROM {$CFG->prefix}user u, {$CFG->prefix}user_teachers t
559 WHERE t.course = '$courseid' AND t.user = u.id AND u.deleted = '0'
560 ORDER BY $sort");
561}
562
563function get_course_users($courseid, $sort="u.lastaccess DESC") {
564/// Using this method because the direct SQL just would not always work!
565
566 $teachers = get_course_teachers($courseid, $sort);
567 $students = get_course_students($courseid, $sort);
568
569 if ($teachers and $students) {
570 return array_merge($teachers, $students);
571 } else if ($teachers) {
572 return $teachers;
573 } else {
574 return $students;
575 }
576
577/// return get_records_sql("SELECT u.* FROM user u, user_students s, user_teachers t
578/// WHERE (s.course = '$courseid' AND s.user = u.id) OR
579/// (t.course = '$courseid' AND t.user = u.id)
580/// ORDER BY $sort");
581}
582
583
584
585/// MODULE FUNCTIONS /////////////////////////////////////////////////
586
587function get_coursemodule_from_instance($modulename, $instance, $courseid) {
588/// Given an instance of a module, finds the coursemodule description
589
590 global $CFG;
591
592 return get_record_sql("SELECT cm.*, m.name
593 FROM {$CFG->prefix}course_modules cm, {$CFG->prefix}modules md, {$CFG->prefix}$modulename m
594 WHERE cm.course = '$courseid' AND
595 cm.deleted = '0' AND
596 cm.instance = m.id AND
597 md.name = '$modulename' AND
598 md.id = cm.module AND
599 m.id = '$instance'");
600
601}
602
603function get_all_instances_in_course($modulename, $courseid, $sort="cw.section") {
604/// Returns an array of all the active instances of a particular
605/// module in a given course. Returns false on any errors.
606
607 global $CFG;
608
609 return get_records_sql("SELECT m.*,cw.section,cm.id as coursemodule
610 FROM {$CFG->prefix}course_modules cm, {$CFG->prefix}course_sections cw,
611 {$CFG->prefix}modules md, {$CFG->prefix}$modulename m
612 WHERE cm.course = '$courseid' AND
613 cm.instance = m.id AND
614 cm.deleted = '0' AND
615 cm.section = cw.id AND
616 md.name = '$modulename' AND
617 md.id = cm.module
618 ORDER BY $sort");
619
620}
621
622?>