moodle/lib/datalib.php
gustav_delius f950af3c43 All modules are now suitable for the site page. They now all follow the same rules, namely that any students enrolled in at least one course is considered to be a student on the site.
All the page headers work correctly also on the site course.

On the site page the modules don't require login unless necessary or required by $CFG->forcelogin.
2004-08-22 14:38:47 +00:00

2427 lines
68 KiB
PHP

<?PHP // $Id$
/// FUNCTIONS FOR DATABASE HANDLING ////////////////////////////////
/**
* execute a given sql command string
*
* Completely general function - it just runs some SQL and reports success.
*
* @param type description
*/
function execute_sql($command, $feedback=true) {
/// Completely general function - it just runs some SQL and reports success.
global $db;
$result = $db->Execute("$command");
if ($result) {
if ($feedback) {
echo "<P><FONT COLOR=green><B>".get_string("success")."</B></FONT></P>";
}
return true;
} else {
if ($feedback) {
echo "<P><FONT COLOR=red><B>".get_string("error")."</B></FONT></P>";
}
return false;
}
}
/**
* Run an arbitrary sequence of semicolon-delimited SQL commands
*
* Assumes that the input text (file or string consists of
* a number of SQL statements ENDING WITH SEMICOLONS. The
* semicolons MUST be the last character in a line.
* Lines that are blank or that start with "#" are ignored.
* Only tested with mysql dump files (mysqldump -p -d moodle)
*
* @param type description
*/
function modify_database($sqlfile="", $sqlstring="") {
global $CFG;
$success = true; // Let's be optimistic :-)
if (!empty($sqlfile)) {
if (!is_readable($sqlfile)) {
$success = false;
echo "<P>Tried to modify database, but \"$sqlfile\" doesn't exist!</P>";
return $success;
} else {
$lines = file($sqlfile);
}
} else {
$lines[] = $sqlstring;
}
$command = "";
foreach ($lines as $line) {
$line = rtrim($line);
$length = strlen($line);
if ($length and $line[0] <> "#") {
if (substr($line, $length-1, 1) == ";") {
$line = substr($line, 0, $length-1); // strip ;
$command .= $line;
$command = str_replace("prefix_", $CFG->prefix, $command); // Table prefixes
if (! execute_sql($command)) {
$success = false;
}
$command = "";
} else {
$command .= $line;
}
}
}
return $success;
}
/// FUNCTIONS TO MODIFY TABLES ////////////////////////////////////////////
/**
* Add a new field to a table, or modify an existing one (if oldfield is defined).
*
* Add a new field to a table, or modify an existing one (if oldfield is defined).
*
* @param type description
*/
function table_column($table, $oldfield, $field, $type="integer", $size="10",
$signed="unsigned", $default="0", $null="not null", $after="") {
global $CFG, $db;
switch (strtolower($CFG->dbtype)) {
case "mysql":
case "mysqlt":
switch (strtolower($type)) {
case "text":
$type = "TEXT";
$signed = "";
break;
case "integer":
$type = "INTEGER($size)";
break;
case "varchar":
$type = "VARCHAR($size)";
$signed = "";
break;
}
if (!empty($oldfield)) {
$operation = "CHANGE $oldfield $field";
} else {
$operation = "ADD $field";
}
$default = "DEFAULT '$default'";
if (!empty($after)) {
$after = "AFTER `$after`";
}
return execute_sql("ALTER TABLE {$CFG->prefix}$table $operation $type $signed $default $null $after");
break;
case "postgres7": // From Petri Asikainen
//Check db-version
$dbinfo = $db->ServerInfo();
$dbver = substr($dbinfo['version'],0,3);
//to prevent conflicts with reserved words
$realfield = "\"$field\"";
$field = "\"${field}_alter_column_tmp\"";
$oldfield = "\"$oldfield\"";
switch (strtolower($type)) {
case "integer":
if ($size <= 4) {
$type = "INT2";
}
if ($size <= 10) {
$type = "INT";
}
if ($size > 10) {
$type = "INT8";
}
break;
case "varchar":
$type = "VARCHAR($size)";
break;
}
$default = "'$default'";
//After is not implemented in postgesql
//if (!empty($after)) {
// $after = "AFTER '$after'";
//}
//Use transactions
execute_sql("BEGIN");
//Allways use temporaly column
execute_sql("ALTER TABLE {$CFG->prefix}$table ADD COLUMN $field $type");
//Add default values
execute_sql("UPDATE {$CFG->prefix}$table SET $field=$default");
if ($dbver >= "7.3") {
// modifying 'not null' is posible before 7.3
//update default values to table
if ($null == "NOT NULL") {
execute_sql("UPDATE {$CFG->prefix}$table SET $field=$default where $field IS NULL");
execute_sql("ALTER TABLE {$CFG->prefix}$table ALTER COLUMN $field SET $null");
} else {
execute_sql("ALTER TABLE {$CFG->prefix}$table ALTER COLUMN $field DROP NOT NULL");
}
}
execute_sql("ALTER TABLE {$CFG->prefix}$table ALTER COLUMN $field SET DEFAULT $default");
if ( $oldfield != "\"\"" ) {
execute_sql("UPDATE {$CFG->prefix}$table SET $field = $oldfield");
execute_sql("ALTER TABLE {$CFG->prefix}$table drop column $oldfield");
}
execute_sql("ALTER TABLE {$CFG->prefix}$table RENAME COLUMN $field TO $realfield");
return execute_sql("COMMIT");
break;
default:
switch (strtolower($type)) {
case "integer":
$type = "INTEGER";
break;
case "varchar":
$type = "VARCHAR";
break;
}
$default = "DEFAULT '$default'";
if (!empty($after)) {
$after = "AFTER $after";
}
if (!empty($oldfield)) {
execute_sql("ALTER TABLE {$CFG->prefix}$table RENAME COLUMN $oldfield $field");
} else {
execute_sql("ALTER TABLE {$CFG->prefix}$table ADD COLUMN $field $type");
}
execute_sql("ALTER TABLE {$CFG->prefix}$table ALTER COLUMN $field SET $null");
return execute_sql("ALTER TABLE {$CFG->prefix}$table ALTER COLUMN $field SET $default");
break;
}
}
/// GENERIC FUNCTIONS TO CHECK AND COUNT RECORDS ////////////////////////////////////////
/**
* Returns true or false depending on whether the specified record exists
*
* Returns true or false depending on whether the specified record exists
*
* @param type description
*/
function record_exists($table, $field1="", $value1="", $field2="", $value2="", $field3="", $value3="") {
global $CFG;
if ($field1) {
$select = "WHERE $field1 = '$value1'";
if ($field2) {
$select .= " AND $field2 = '$value2'";
if ($field3) {
$select .= " AND $field3 = '$value3'";
}
}
} else {
$select = "";
}
return record_exists_sql("SELECT * FROM $CFG->prefix$table $select LIMIT 1");
}
/**
* Returns true or false depending on whether the specified record exists
*
* The sql statement is provided as a string.
*
* @param type description
*/
function record_exists_sql($sql) {
global $CFG, $db;
if (!$rs = $db->Execute($sql)) {
if (isset($CFG->debug) and $CFG->debug > 7) {
notify($db->ErrorMsg()."<br /><br />$sql");
}
return false;
}
if ( $rs->RecordCount() ) {
return true;
} else {
return false;
}
}
/**
* Get all the records and count them
*
* Get all the records and count them
*
* @param type description
*/
function count_records($table, $field1="", $value1="", $field2="", $value2="", $field3="", $value3="") {
global $CFG;
if ($field1) {
$select = "WHERE $field1 = '$value1'";
if ($field2) {
$select .= " AND $field2 = '$value2'";
if ($field3) {
$select .= " AND $field3 = '$value3'";
}
}
} else {
$select = "";
}
return count_records_sql("SELECT COUNT(*) FROM $CFG->prefix$table $select");
}
/**
* Get all the records and count them
*
* Get all the records and count them
*
* @param type description
*
*/
function count_records_select($table, $select="", $countitem="COUNT(*)") {
global $CFG;
if ($select) {
$select = "WHERE $select";
}
return count_records_sql("SELECT $countitem FROM $CFG->prefix$table $select");
}
/**
* Get all the records and count them
*
* The sql statement is provided as a string.
*
* @param type description
*/
function count_records_sql($sql) {
global $CFG, $db;
$rs = $db->Execute("$sql");
if (!$rs) {
if (isset($CFG->debug) and $CFG->debug > 7) {
notify($db->ErrorMsg()."<br /><br />$sql");
}
return 0;
}
return $rs->fields[0];
}
/// GENERIC FUNCTIONS TO GET, INSERT, OR UPDATE DATA ///////////////////////////////////
/**
* Get a single record as an object
*
* Get a single record as an object
*
* @param string $table the name of the table to select from
* @param string $field1 the name of the field for the first criteria
* @param string $value1 the value of the field for the first criteria
* @param string $field2 the name of the field for the second criteria
* @param string $value2 the value of the field for the second criteria
* @param string $field3 the name of the field for the third criteria
* @param string $value3 the value of the field for the third criteria
* @return object(fieldset) a fieldset object containing the first record selected
*/
function get_record($table, $field1, $value1, $field2="", $value2="", $field3="", $value3="") {
global $CFG;
$select = "WHERE $field1 = '$value1'";
if ($field2) {
$select .= " AND $field2 = '$value2'";
if ($field3) {
$select .= " AND $field3 = '$value3'";
}
}
return get_record_sql("SELECT * FROM $CFG->prefix$table $select");
}
/**
* Get a single record as an object
*
* The sql statement is provided as a string.
* A LIMIT is normally added to only look for 1 record
*
* @param type description
*/
function get_record_sql($sql) {
global $db, $CFG;
if (isset($CFG->debug) and $CFG->debug > 7) { // Debugging mode - don't use limit
$limit = "";
} else {
$limit = " LIMIT 1"; // Workaround - limit to one record
}
if (!$rs = $db->Execute("$sql$limit")) {
if (isset($CFG->debug) and $CFG->debug > 7) { // Debugging mode - print checks
notify( $db->ErrorMsg() . "<br /><br />$sql$limit" );
}
return false;
}
if (!$recordcount = $rs->RecordCount()) {
return false; // Found no records
}
if ($recordcount == 1) { // Found one record
return (object)$rs->fields;
} else { // Error: found more than one record
notify("Error: Turn off debugging to hide this error.");
notify("$sql$limit");
if ($records = $rs->GetAssoc(true)) {
notify("Found more than one record in get_record_sql !");
print_object($records);
} else {
notify("Very strange error in get_record_sql !");
print_object($rs);
}
print_continue("$CFG->wwwroot/admin/config.php");
}
}
/**
* Gets one record from a table, as an object
*
* "select" is a fragment of SQL to define the selection criteria
*
* @param type description
*/
function get_record_select($table, $select="", $fields="*") {
global $CFG;
if ($select) {
$select = "WHERE $select";
}
return get_record_sql("SELECT $fields FROM $CFG->prefix$table $select");
}
/**
* Get a number of records as an array of objects
*
* Can optionally be sorted eg "time ASC" or "time DESC"
* If "fields" is specified, only those fields are returned
* The "key" is the first column returned, eg usually "id"
* limitfrom and limitnum must both be specified or not at all
*
* @param type description
*/
function get_records($table, $field="", $value="", $sort="", $fields="*", $limitfrom="", $limitnum="") {
global $CFG;
if ($field) {
$select = "WHERE $field = '$value'";
} else {
$select = "";
}
if ($limitfrom !== "") {
switch ($CFG->dbtype) {
case "mysql":
$limit = "LIMIT $limitfrom,$limitnum";
break;
case "postgres7":
$limit = "LIMIT $limitnum OFFSET $limitfrom";
break;
default:
$limit = "LIMIT $limitnum,$limitfrom";
}
} else {
$limit = "";
}
if ($sort) {
$sort = "ORDER BY $sort";
}
return get_records_sql("SELECT $fields FROM $CFG->prefix$table $select $sort $limit");
}
/**
* Get a number of records as an array of objects
*
* Can optionally be sorted eg "time ASC" or "time DESC"
* "select" is a fragment of SQL to define the selection criteria
* The "key" is the first column returned, eg usually "id"
* limitfrom and limitnum must both be specified or not at all
*
* @param type description
*/
function get_records_select($table, $select="", $sort="", $fields="*", $limitfrom="", $limitnum="") {
global $CFG;
if ($select) {
$select = "WHERE $select";
}
if ($limitfrom !== "") {
switch ($CFG->dbtype) {
case "mysql":
$limit = "LIMIT $limitfrom,$limitnum";
break;
case "postgres7":
$limit = "LIMIT $limitnum OFFSET $limitfrom";
break;
default:
$limit = "LIMIT $limitnum,$limitfrom";
}
} else {
$limit = "";
}
if ($sort) {
$sort = "ORDER BY $sort";
}
return get_records_sql("SELECT $fields FROM $CFG->prefix$table $select $sort $limit");
}
/**
* Get a number of records as an array of objects
*
* Differs from get_records() in that the values variable
* can be a comma-separated list of values eg "4,5,6,10"
* Can optionally be sorted eg "time ASC" or "time DESC"
* The "key" is the first column returned, eg usually "id"
*
* @param type description
*/
function get_records_list($table, $field="", $values="", $sort="", $fields="*") {
global $CFG;
if ($field) {
$select = "WHERE $field in ($values)";
} else {
$select = "";
}
if ($sort) {
$sort = "ORDER BY $sort";
}
return get_records_sql("SELECT $fields FROM $CFG->prefix$table $select $sort");
}
/**
* Get a number of records as an array of objects
*
* The "key" is the first column returned, eg usually "id"
* The sql statement is provided as a string.
*
* @param type description
*/
function get_records_sql($sql) {
global $CFG,$db;
if (!$rs = $db->Execute($sql)) {
if (isset($CFG->debug) and $CFG->debug > 7) {
notify($db->ErrorMsg()."<br /><br />$sql");
}
return false;
}
if ( $rs->RecordCount() > 0 ) {
if ($records = $rs->GetAssoc(true)) {
foreach ($records as $key => $record) {
$objects[$key] = (object) $record;
}
return $objects;
} else {
return false;
}
} else {
return false;
}
}
/**
* Get a number of records as an array of objects
*
* Can optionally be sorted eg "time ASC" or "time DESC"
* If "fields" is specified, only those fields are returned
* The "key" is the first column returned, eg usually "id"
*
* @param type description
*/
function get_records_menu($table, $field="", $value="", $sort="", $fields="*") {
global $CFG;
if ($field) {
$select = "WHERE $field = '$value'";
} else {
$select = "";
}
if ($sort) {
$sort = "ORDER BY $sort";
}
return get_records_sql_menu("SELECT $fields FROM $CFG->prefix$table $select $sort");
}
/**
* Get a number of records as an array of objects
*
* Can optionally be sorted eg "time ASC" or "time DESC"
* "select" is a fragment of SQL to define the selection criteria
* Returns associative array of first two fields
*
* @param type description
*/
function get_records_select_menu($table, $select="", $sort="", $fields="*") {
global $CFG;
if ($select) {
$select = "WHERE $select";
}
if ($sort) {
$sort = "ORDER BY $sort";
}
return get_records_sql_menu("SELECT $fields FROM $CFG->prefix$table $select $sort");
}
/**
* Given an SQL select, this function returns an associative
*
* array of the first two columns. This is most useful in
* combination with the choose_from_menu function to create
* a form menu.
*
* @param type description
*/
function get_records_sql_menu($sql) {
global $CFG, $db;
if (!$rs = $db->Execute($sql)) {
if (isset($CFG->debug) and $CFG->debug > 7) {
notify($db->ErrorMsg()."<br /><br />$sql");
}
return false;
}
if ( $rs->RecordCount() > 0 ) {
while (!$rs->EOF) {
$menu[$rs->fields[0]] = $rs->fields[1];
$rs->MoveNext();
}
return $menu;
} else {
return false;
}
}
/**
* Get a single field from a database record
*
* longdesc
*
* @param type description
*/
function get_field($table, $return, $field1, $value1, $field2="", $value2="", $field3="", $value3="") {
global $db, $CFG;
$select = "WHERE $field1 = '$value1'";
if ($field2) {
$select .= " AND $field2 = '$value2'";
if ($field3) {
$select .= " AND $field3 = '$value3'";
}
}
$rs = $db->Execute("SELECT $return FROM $CFG->prefix$table $select");
if (!$rs) {
if (isset($CFG->debug) and $CFG->debug > 7) {
notify($db->ErrorMsg()."<br /><br />SELECT $return FROM $CFG->prefix$table $select");
}
return false;
}
if ( $rs->RecordCount() == 1 ) {
return $rs->fields["$return"];
} else {
return false;
}
}
/**
* Get a single field from a database record
*
* longdesc
*
* @param type description
*/
function get_field_sql($sql) {
global $db, $CFG;
$rs = $db->Execute($sql);
if (!$rs) {
if (isset($CFG->debug) and $CFG->debug > 7) {
notify($db->ErrorMsg()."<br /><br />$sql");
}
return false;
}
if ( $rs->RecordCount() == 1 ) {
return $rs->fields[0];
} else {
return false;
}
}
/**
* Set a single field in a database record
*
* longdesc
*
* @param type description
*/
function set_field($table, $newfield, $newvalue, $field1, $value1, $field2="", $value2="", $field3="", $value3="") {
global $db, $CFG;
$select = "WHERE $field1 = '$value1'";
if ($field2) {
$select .= " AND $field2 = '$value2'";
if ($field3) {
$select .= " AND $field3 = '$value3'";
}
}
return $db->Execute("UPDATE $CFG->prefix$table SET $newfield = '$newvalue' $select");
}
/**
* Delete one or more records from a table
*
* Delete one or more records from a table
*
* @param type description
*/
function delete_records($table, $field1="", $value1="", $field2="", $value2="", $field3="", $value3="") {
global $db, $CFG;
if ($field1) {
$select = "WHERE $field1 = '$value1'";
if ($field2) {
$select .= " AND $field2 = '$value2'";
if ($field3) {
$select .= " AND $field3 = '$value3'";
}
}
} else {
$select = "";
}
return $db->Execute("DELETE FROM $CFG->prefix$table $select");
}
/**
* Delete one or more records from a table
*
* "select" is a fragment of SQL to define the selection criteria
*
* @param type description
*/
function delete_records_select($table, $select="") {
global $CFG, $db;
if ($select) {
$select = "WHERE $select";
}
return $db->Execute("DELETE FROM $CFG->prefix$table $select");
}
/**
* Insert a record into a table and return the "id" field if required
*
* If the return ID isn't required, then this just reports success as true/false.
* $dataobject is an object containing needed data
*
* @param type description
*/
function insert_record($table, $dataobject, $returnid=true, $primarykey='id') {
global $db, $CFG;
/// Execute a dummy query to get an empty recordset
if (!$rs = $db->Execute("SELECT * FROM $CFG->prefix$table WHERE $primarykey ='-1'")) {
return false;
}
/// Get the correct SQL from adoDB
if (!$insertSQL = $db->GetInsertSQL($rs, (array)$dataobject, true)) {
return false;
}
/// Run the SQL statement
if (!$rs = $db->Execute($insertSQL)) {
if (isset($CFG->debug) and $CFG->debug > 7) {
notify($db->ErrorMsg()."<br /><br />$insertSQL");
}
return false;
}
/// If a return ID is not needed then just return true now
if (!$returnid) {
return true;
}
/// Find the return ID of the newly inserted record
switch ($CFG->dbtype) {
case "postgres7": // Just loves to be special
$oid = $db->Insert_ID();
if ($rs = $db->Execute("SELECT $primarykey FROM $CFG->prefix$table WHERE oid = $oid")) {
if ($rs->RecordCount() == 1) {
return (integer) $rs->fields[0];
}
}
return false;
default:
return $db->Insert_ID(); // Should work on most databases, but not all!
}
}
/**
* Update a record in a table
*
* $dataobject is an object containing needed data
* Relies on $dataobject having a variable "id" to
* specify the record to update
*
* @param type description
*/
function update_record($table, $dataobject) {
global $db, $CFG;
if (! isset($dataobject->id) ) {
return false;
}
// Determine all the fields in the table
if (!$columns = $db->MetaColumns("$CFG->prefix$table")) {
return false;
}
$data = (array)$dataobject;
// Pull out data matching these fields
foreach ($columns as $column) {
if ($column->name <> "id" and isset($data[$column->name]) ) {
$ddd[$column->name] = $data[$column->name];
}
}
// Construct SQL queries
$numddd = count($ddd);
$count = 0;
$update = "";
foreach ($ddd as $key => $value) {
$count++;
$update .= "$key = '$value'";
if ($count < $numddd) {
$update .= ", ";
}
}
if ($rs = $db->Execute("UPDATE $CFG->prefix$table SET $update WHERE id = '$dataobject->id'")) {
return true;
} else {
if (isset($CFG->debug) and $CFG->debug > 7) {
notify($db->ErrorMsg()."<br /><br />UPDATE $CFG->prefix$table SET $update WHERE id = '$dataobject->id'");
}
return false;
}
}
/// USER DATABASE ////////////////////////////////////////////////
/**
* Get a complete user record, which includes all the info
*
* in the user record, as well as membership information
* Suitable for setting as $USER session cookie.
*
* @param type description
*/
function get_user_info_from_db($field, $value) {
global $CFG;
if (!$field or !$value) {
return false;
}
/// Get all the basic user data
if (! $user = get_record_select("user", "$field = '$value' AND deleted <> '1'")) {
return false;
}
/// Add membership information
if ($admins = get_records("user_admins", "userid", $user->id)) {
$user->admin = true;
}
if ($site = get_site()) {
$user->student[$site->id] = isstudent($site->id, $user->id);
}
/// Determine enrolments based on current enrolment module
require_once("$CFG->dirroot/enrol/$CFG->enrol/enrol.php");
$enrol = new enrolment_plugin();
$enrol->get_student_courses($user);
$enrol->get_teacher_courses($user);
/// Get various settings and preferences
if ($displays = get_records("course_display", "userid", $user->id)) {
foreach ($displays as $display) {
$user->display[$display->course] = $display->display;
}
}
if ($preferences = get_records('user_preferences', 'userid', $user->id)) {
foreach ($preferences as $preference) {
$user->preference[$preference->name] = $preference->value;
}
}
if ($groups = get_records("groups_members", "userid", $user->id)) {
foreach ($groups as $groupmember) {
$courseid = get_field("groups", "courseid", "id", $groupmember->groupid);
$user->groupmember[$courseid] = $groupmember->groupid;
}
}
return $user;
}
/**
* Updates user record to record their last access
*
* longdesc
*
*/
function update_user_in_db() {
global $db, $USER, $REMOTE_ADDR, $CFG;
if (!isset($USER->id))
return false;
$timenow = time();
if ($db->Execute("UPDATE {$CFG->prefix}user SET lastIP='$REMOTE_ADDR', lastaccess='$timenow'
WHERE id = '$USER->id' ")) {
return true;
} else {
return false;
}
}
/**
* Does this username and password specify a valid admin user?
*
* longdesc
*
* @param type description
*/
function adminlogin($username, $md5password) {
global $CFG;
return record_exists_sql("SELECT u.id
FROM {$CFG->prefix}user u,
{$CFG->prefix}user_admins a
WHERE u.id = a.userid
AND u.username = '$username'
AND u.password = '$md5password'");
}
/**
* Get the guest user information from the database
*
* longdesc
*
* @param type description
*/
function get_guest() {
return get_user_info_from_db("username", "guest");
}
/**
* Returns $user object of the main admin user
*
* longdesc
*
* @param type description
*/
function get_admin () {
global $CFG;
if ( $admins = get_admins() ) {
foreach ($admins as $admin) {
return $admin; // ie the first one
}
} else {
return false;
}
}
/**
* Returns list of all admins
*
* longdesc
*
* @param type description
*/
function get_admins() {
global $CFG;
return get_records_sql("SELECT u.*, a.id as adminid
FROM {$CFG->prefix}user u,
{$CFG->prefix}user_admins a
WHERE a.userid = u.id
ORDER BY a.id ASC");
}
/**
* Returns list of all creators
*
* longdesc
*
* @param type description
*/
function get_creators() {
global $CFG;
return get_records_sql("SELECT u.*
FROM {$CFG->prefix}user u,
{$CFG->prefix}user_coursecreators a
WHERE a.userid = u.id
ORDER BY u.id ASC");
}
/**
* Returns $user object of the main teacher for a course
*
* longdesc
*
* @param type description
*/
function get_teacher($courseid) {
global $CFG;
if ( $teachers = get_course_teachers($courseid, "t.authority ASC")) {
foreach ($teachers as $teacher) {
if ($teacher->authority) {
return $teacher; // the highest authority teacher
}
}
} else {
return false;
}
}
/**
* Searches logs to find all enrolments since a certain date
*
* used to print recent activity
*
* @param type description
*/
function get_recent_enrolments($courseid, $timestart) {
global $CFG;
return get_records_sql("SELECT DISTINCT u.id, u.firstname, u.lastname
FROM {$CFG->prefix}user u,
{$CFG->prefix}user_students s,
{$CFG->prefix}log l
WHERE l.time > '$timestart'
AND l.course = '$courseid'
AND l.module = 'course'
AND l.action = 'enrol'
AND l.info = u.id
AND u.id = s.userid
AND s.course = '$courseid'
ORDER BY l.time ASC");
}
/**
* Returns array of userinfo of all students in this course
* or on this site if courseid is id of site
*
* @param type description
*/
function get_course_students($courseid, $sort="s.timeaccess", $dir="", $page=0, $recordsperpage=99999,
$firstinitial="", $lastinitial="", $group=NULL, $search="", $fields='', $exceptions='') {
global $CFG;
switch ($CFG->dbtype) {
case "mysql":
$fullname = " CONCAT(firstname,\" \",lastname) ";
$limit = "LIMIT $page,$recordsperpage";
$LIKE = "LIKE";
break;
case "postgres7":
$fullname = " firstname||' '||lastname ";
$limit = "LIMIT $recordsperpage OFFSET ".($page);
$LIKE = "ILIKE";
break;
default:
$fullname = " firstname||\" \"||lastname ";
$limit = "LIMIT $recordsperpage,$page";
$LIKE = "ILIKE";
}
$groupmembers = '';
// make sure it works on the site course
$select = "s.course = '$courseid' AND ";
$site = get_site();
if ($courseid == $site->id) {
$select = '';
}
$select .= "s.userid = u.id AND u.deleted = '0' ";
if (!$fields) {
$fields = 'u.id, u.confirmed, u.username, u.firstname, u.lastname, '.
'u.maildisplay, u.mailformat, u.maildigest, u.email, u.city, '.
'u.country, u.picture, u.idnumber, u.department, u.institution, '.
'u.emailstop, u.lang, u.timezone, s.timeaccess as lastaccess';
}
if ($search) {
$search = " AND ($fullname $LIKE '%$search%' OR email $LIKE '%$search%') ";
}
if ($firstinitial) {
$select .= " AND u.firstname $LIKE '$firstinitial%' ";
}
if ($lastinitial) {
$select .= " AND u.lastname $LIKE '$lastinitial%' ";
}
if ($group === 0) { /// Need something here to get all students not in a group
return array();
} else if ($group !== NULL) {
$groupmembers = ", {$CFG->prefix}groups_members gm ";
$select .= " AND u.id = gm.userid AND gm.groupid = '$group'";
}
if (!empty($exceptions)) {
$select .= " AND u.id NOT IN ($exceptions)";
}
if ($sort) {
$sort = " ORDER BY $sort ";
}
return get_records_sql("SELECT $fields
FROM {$CFG->prefix}user u,
{$CFG->prefix}user_students s
$groupmembers
WHERE $select $search $sort $dir $limit");
}
/**
* Counts the students in a given course (or site), or a subset of them
*
* @param type description
*/
function count_course_students($course, $search="", $firstinitial="", $lastinitial="", $group=NULL, $exceptions='') {
global $CFG;
if (!$course->category) {
return count(get_site_users($sort, '', $exceptions));
}
switch ($CFG->dbtype) {
case "mysql":
$fullname = " CONCAT(firstname,\" \",lastname) ";
$LIKE = "LIKE";
break;
default:
$fullname = " firstname||\' \'||lastname ";
$LIKE = "ILIKE";
}
$groupmembers = "";
$select = "s.course = '$course->id' AND s.userid = u.id AND u.deleted = '0'";
if ($search) {
$search = " AND ($fullname $LIKE '%$search%' OR email $LIKE '%$search%') ";
}
if ($firstinitial) {
$select .= " AND u.firstname $LIKE '$firstinitial%'";
}
if ($lastinitial) {
$select .= " AND u.lastname $LIKE '$lastinitial%'";
}
if ($group === 0) { /// Need something here to get all students not in a group
return 0;
} else if ($group !== NULL) {
$groupmembers = ", {$CFG->prefix}groups_members gm ";
$select .= " AND u.id = gm.userid AND gm.groupid = '$group'";
}
if (!empty($exceptions)) {
$select .= " AND u.id NOT IN ($exceptions)";
}
return count_records_sql("SELECT COUNT(*)
FROM {$CFG->prefix}user u,
{$CFG->prefix}user_students s $groupmembers
WHERE $select");
}
/**
* Returns list of all teachers in this course
* (also works for site)
*
* @param type description
*/
function get_course_teachers($courseid, $sort="t.authority ASC", $exceptions='') {
global $CFG;
if (!empty($exceptions)) {
$except = " AND u.id NOT IN ($exceptions) ";
} else {
$except = '';
}
return get_records_sql("SELECT u.id, u.username, u.firstname, u.lastname, u.maildisplay, u.mailformat, u.maildigest,
u.email, u.city, u.country, u.lastlogin, u.picture, u.lang, u.timezone,
u.emailstop, t.authority,t.role,t.editall,t.timeaccess as lastaccess
FROM {$CFG->prefix}user u,
{$CFG->prefix}user_teachers t
WHERE t.course = '$courseid' AND t.userid = u.id AND u.deleted = '0' $except
ORDER BY $sort");
}
/**
* Returns all the users of a course: students and teachers
*
* @param type description
*/
function get_course_users($courseid, $sort="timeaccess DESC", $exceptions='') {
/// Using this method because the single SQL is too inefficient
// Note that this has the effect that teachers and students are
// sorted individually. Returns first all teachers, then all students
if (!$teachers = get_course_teachers($courseid, $sort, $exceptions)) {
$teachers = array();
}
if (!$students = get_course_students($courseid, $sort, "", 0, 99999, "", "", NULL, "", '', $exceptions)) {
$students = array();
}
return $teachers + $students;
// This is too inefficient on large sites.
// return get_records_sql("SELECT DISTINCT u.*
// FROM mdl_user u
// LEFT JOIN mdl_user_students s ON s.course = '$courseid'
// LEFT JOIN mdl_user_teachers t ON t.course = '$courseid'
// WHERE (u.id = t.userid OR u.id = s.userid)
// ORDER BY $sort");
}
/**
* Search through course users
*
* @param type description
*/
function search_users($courseid, $groupid, $searchtext, $sort='', $exceptions='') {
global $CFG;
switch ($CFG->dbtype) {
case "mysql":
$fullname = " CONCAT(u.firstname,\" \",u.lastname) ";
$LIKE = "LIKE";
break;
case "postgres7":
$fullname = " u.firstname||' '||u.lastname ";
$LIKE = "ILIKE";
break;
default:
$fullname = " u.firstname||\" \"||u.lastname ";
$LIKE = "ILIKE";
}
if (!empty($exceptions)) {
$except = " AND u.id NOT IN ($exceptions) ";
} else {
$except = '';
}
if (!empty($sort)) {
$order = " ORDER by $sort";
} else {
$order = '';
}
$site = get_site();
if (!$courseid or $courseid == $site->id) {
if (!$admins = get_records_sql("SELECT u.id, u.firstname, u.lastname, u.email
FROM {$CFG->prefix}user u,
{$CFG->prefix}user_admins s
WHERE s.userid = u.id AND u.deleted = '0'
AND ($fullname $LIKE '%$searchtext%' OR u.email $LIKE '%$searchtext%')
$except $order")) {
$admins = array();
}
if (!$teachers = get_records_sql("SELECT u.id, u.firstname, u.lastname, u.email
FROM {$CFG->prefix}user u,
{$CFG->prefix}user_teachers s
WHERE s.userid = u.id AND u.deleted = '0'
AND ($fullname $LIKE '%$searchtext%' OR u.email $LIKE '%$searchtext%')
$except $order")) {
$teachers = array();
}
if (!$students = get_records_sql("SELECT u.id, u.firstname, u.lastname, u.email
FROM {$CFG->prefix}user u,
{$CFG->prefix}user_students s
WHERE s.userid = u.id AND u.deleted = '0'
AND ($fullname $LIKE '%$searchtext%' OR u.email $LIKE '%$searchtext%')
$except $order")) {
$students = array();
}
return $admins + $teachers + $students;
} else {
if ($groupid) {
return get_records_sql("SELECT u.id, u.firstname, u.lastname, u.email
FROM {$CFG->prefix}user u,
{$CFG->prefix}groups_members g
WHERE g.groupid = '$groupid' AND g.userid = u.id AND u.deleted = '0'
AND ($fullname $LIKE '%$searchtext%' OR u.email $LIKE '%$searchtext%')
$except $order");
} else {
if (!$teachers = get_records_sql("SELECT u.id, u.firstname, u.lastname, u.email
FROM {$CFG->prefix}user u,
{$CFG->prefix}user_teachers s
WHERE s.course = '$courseid' AND s.userid = u.id AND u.deleted = '0'
AND ($fullname $LIKE '%$searchtext%' OR u.email $LIKE '%$searchtext%')
$except $order")) {
$teachers = array();
}
if (!$students = get_records_sql("SELECT u.id, u.firstname, u.lastname, u.email
FROM {$CFG->prefix}user u,
{$CFG->prefix}user_students s
WHERE s.course = '$courseid' AND s.userid = u.id AND u.deleted = '0'
AND ($fullname $LIKE '%$searchtext%' OR u.email $LIKE '%$searchtext%')
$except $order")) {
$students = array();
}
return $teachers + $students;
}
}
}
/**
* Returns a list of all active users who are enrolled
*
* or teaching in courses on this server
*
* @param type description
*/
function get_site_users($sort="u.lastaccess DESC", $select="", $exceptions='') {
global $CFG;
if (!empty($exceptions)) {
$except = " AND u.id NOT IN ($exceptions) ";
} else {
$except = '';
}
if ($select) {
$selectinfo = $select;
} else {
$selectinfo = "u.id, u.username, u.firstname, u.lastname, u.maildisplay, u.mailformat, u.maildigest,".
"u.email, u.emailstop, u.city, u.country, u.lastaccess, u.lastlogin, u.picture, u.lang, u.timezone";
}
if (!$students = get_records_sql("SELECT DISTINCT $selectinfo from {$CFG->prefix}user u, {$CFG->prefix}user_students s
WHERE s.userid = u.id $except ORDER BY $sort")) {
$students = array();
}
if (!$teachers = get_records_sql("SELECT DISTINCT $selectinfo from {$CFG->prefix}user u, {$CFG->prefix}user_teachers t
WHERE t.userid = u.id $except ORDER BY $sort")) {
$teachers = array();
}
if (!$admins = get_records_sql("SELECT DISTINCT $selectinfo from {$CFG->prefix}user u, {$CFG->prefix}user_admins a
WHERE a.userid = u.id $except ORDER BY $sort")) {
$admins = array();
}
return $admins + $teachers + $students;
}
/**
* Returns a subset of users
*
* longdesc
*
* @param bookean $get if false then only a count of the records is returned
* @param string $search a simple string to search for
* @param boolean $confirmed a switch to allow/disallow unconfirmed users
* @param array(int) $exceptions a list of IDs to ignore, eg 2,4,5,8,9,10
* @param string $sort a SQL snippet for the sorting criteria to use
* @param string $firstinitial
* @param string $lastinitial
* @param string $page
* @param string $recordsperpage
* @param string $fields a comma separated list of fields
*/
function get_users($get=true, $search="", $confirmed=false, $exceptions="", $sort="firstname ASC",
$firstinitial="", $lastinitial="", $page=0, $recordsperpage=99999, $fields="*") {
global $CFG;
switch ($CFG->dbtype) {
case "mysql":
$limit = "LIMIT $page,$recordsperpage";
$fullname = " CONCAT(firstname,\" \",lastname) ";
$LIKE = "LIKE";
break;
case "postgres7":
$limit = "LIMIT $recordsperpage OFFSET ".($page);
$fullname = " firstname||' '||lastname ";
$LIKE = "ILIKE";
break;
default:
$limit = "LIMIT $recordsperpage,$page";
$fullname = " firstname||\" \"||lastname ";
$LIKE = "ILIKE";
}
$select = "username <> 'guest' AND deleted = 0";
if ($search) {
$select .= " AND ($fullname $LIKE '%$search%' OR email $LIKE '%$search%') ";
}
if ($confirmed) {
$select .= " AND confirmed = '1' ";
}
if ($exceptions) {
$select .= " AND id NOT IN ($exceptions) ";
}
if ($firstinitial) {
$select .= " AND firstname $LIKE '$firstinitial%'";
}
if ($lastinitial) {
$select .= " AND lastname $LIKE '$lastinitial%'";
}
if ($sort and $get) {
$sort = " ORDER BY $sort ";
} else {
$sort = "";
}
if ($get) {
return get_records_select("user", "$select $sort $limit", '', $fields);
} else {
return count_records_select("user", "$select $sort $limit");
}
}
/**
* shortdesc
*
* longdesc
*
* @param type description
*/
function get_users_listing($sort="lastaccess", $dir="ASC", $page=0, $recordsperpage=99999,
$search="", $firstinitial="", $lastinitial="") {
global $CFG;
switch ($CFG->dbtype) {
case "mysql":
$limit = "LIMIT $page,$recordsperpage";
$fullname = " CONCAT(firstname,\" \",lastname) ";
$LIKE = "LIKE";
break;
case "postgres7":
$limit = "LIMIT $recordsperpage OFFSET ".($page);
$fullname = " firstname||' '||lastname ";
$LIKE = "ILIKE";
break;
default:
$limit = "LIMIT $recordsperpage,$page";
$fullname = " firstname||' '||lastname ";
$LIKE = "LIKE";
}
$select = 'deleted <> 1';
if ($search) {
$select .= " AND ($fullname $LIKE '%$search%' OR email $LIKE '%$search%') ";
}
if ($firstinitial) {
$select .= " AND firstname $LIKE '$firstinitial%' ";
}
if ($lastinitial) {
$select .= " AND lastname $LIKE '$lastinitial%' ";
}
if ($sort) {
$sort = " ORDER BY $sort $dir";
}
/// warning: will return UNCONFIRMED USERS
return get_records_sql("SELECT id, username, email, firstname, lastname, city, country, lastaccess, confirmed
FROM {$CFG->prefix}user
WHERE $select $sort $limit ");
}
/**
* shortdesc
*
* longdesc
*
* @param type description
*/
function get_users_confirmed() {
global $CFG;
return get_records_sql("SELECT *
FROM {$CFG->prefix}user
WHERE confirmed = 1
AND deleted = 0
AND username <> 'guest'
AND username <> 'changeme'");
}
/**
* shortdesc
*
* longdesc
*
* @param type description
*/
function get_users_unconfirmed($cutofftime=2000000000) {
global $CFG;
return get_records_sql("SELECT *
FROM {$CFG->prefix}user
WHERE confirmed = 0
AND firstaccess > 0
AND firstaccess < '$cutofftime'");
}
/**
* shortdesc
*
* longdesc
*
* @param type description
*/
function get_users_longtimenosee($cutofftime) {
global $CFG;
return get_records_sql("SELECT DISTINCT *
FROM {$CFG->prefix}user_students
WHERE timeaccess > '0'
AND timeaccess < '$cutofftime' ");
}
/**
* Returns an array of group objects that the user is a member of
* in the given course. If userid isn't specified, then return a
* list of all groups in the course.
*
* @param type description
*/
function get_groups($courseid, $userid=0) {
global $CFG;
if ($userid) {
$dbselect = ", {$CFG->prefix}groups_members m";
$userselect = "AND m.groupid = g.id AND m.userid = '$userid'";
} else {
$dbselect = '';
$userselect = '';
}
return get_records_sql("SELECT DISTINCT g.*
FROM {$CFG->prefix}groups g $dbselect
WHERE g.courseid = '$courseid' $userselect ");
}
/**
* Returns an array of user objects
*
* @param type description
*/
function get_group_users($groupid, $sort="u.lastaccess DESC", $exceptions='') {
global $CFG;
if (!empty($exceptions)) {
$except = " AND u.id NOT IN ($exceptions) ";
} else {
$except = '';
}
return get_records_sql("SELECT DISTINCT u.*
FROM {$CFG->prefix}user u,
{$CFG->prefix}groups_members m
WHERE m.groupid = '$groupid'
AND m.userid = u.id $except
ORDER BY $sort");
}
/**
* An efficient way of finding all the users who aren't in groups yet
*
* @param type description
*/
function get_users_not_in_group($courseid) {
global $CFG;
return array(); /// XXX TO BE DONE
}
/**
* Returns an array of user objects
*
* @param type description
*/
function get_group_students($groupid, $sort="u.lastaccess DESC") {
global $CFG;
return get_records_sql("SELECT DISTINCT u.*
FROM {$CFG->prefix}user u,
{$CFG->prefix}groups_members m,
{$CFG->prefix}groups g,
{$CFG->prefix}user_students s
WHERE m.groupid = '$groupid'
AND m.userid = u.id
AND m.groupid = g.id
AND g.courseid = s.course
AND s.userid = u.id
ORDER BY $sort");
}
/**
* Returns the user's group in a particular course
*
* @param type description
*/
function user_group($courseid, $userid) {
global $CFG;
return get_record_sql("SELECT g.*
FROM {$CFG->prefix}groups g,
{$CFG->prefix}groups_members m
WHERE g.courseid = '$courseid'
AND g.id = m.groupid
AND m.userid = '$userid'");
}
/// OTHER SITE AND COURSE FUNCTIONS /////////////////////////////////////////////
/**
* Returns $course object of the top-level site.
*
* Returns $course object of the top-level site.
*
* @param type description
*/
function get_site () {
if ( $course = get_record("course", "category", 0)) {
return $course;
} else {
return false;
}
}
/**
* Returns list of courses, for whole site, or category
*
* Returns list of courses, for whole site, or category
*
* @param type description
*/
function get_courses($categoryid="all", $sort="c.sortorder ASC", $fields="c.*") {
global $USER, $CFG;
$categoryselect = "";
if ($categoryid != "all") {
$categoryselect = "c.category = '$categoryid'";
}
$teachertable = "";
$visiblecourses = "";
$sqland = "";
if (!empty($categoryselect)) {
$sqland = "AND ";
}
if (!empty($USER->id)) { // May need to check they are a teacher
if (!iscreator()) {
$visiblecourses = "$sqland ((c.visible > 0) OR (t.userid = '$USER->id' AND t.course = c.id))";
$teachertable = ", {$CFG->prefix}user_teachers t";
}
} else {
$visiblecourses = "$sqland c.visible > 0";
}
if ($categoryselect or $visiblecourses) {
$selectsql = "{$CFG->prefix}course c $teachertable WHERE $categoryselect $visiblecourses";
} else {
$selectsql = "{$CFG->prefix}course c $teachertable";
}
return get_records_sql("SELECT DISTINCT $fields FROM $selectsql ORDER BY $sort");
}
/**
* Returns list of courses, for whole site, or category
*
* Similar to get_courses, but allows paging
*
* @param type description
*/
function get_courses_page($categoryid="all", $sort="c.sortorder ASC", $fields="c.*",
&$totalcount, $limitfrom="", $limitnum="") {
global $USER, $CFG;
$categoryselect = "";
if ($categoryid != "all") {
$categoryselect = "c.category = '$categoryid'";
}
$teachertable = "";
$visiblecourses = "";
$sqland = "";
if (!empty($categoryselect)) {
$sqland = "AND ";
}
if (!empty($USER)) { // May need to check they are a teacher
if (!iscreator()) {
$visiblecourses = "$sqland ((c.visible > 0) OR (t.userid = '$USER->id' AND t.course = c.id))";
$teachertable = ", {$CFG->prefix}user_teachers t";
}
} else {
$visiblecourses = "$sqland c.visible > 0";
}
if ($limitfrom !== "") {
switch ($CFG->dbtype) {
case "mysql":
$limit = "LIMIT $limitfrom,$limitnum";
break;
case "postgres7":
$limit = "LIMIT $limitnum OFFSET $limitfrom";
break;
default:
$limit = "LIMIT $limitnum,$limitfrom";
}
} else {
$limit = "";
}
$selectsql = "{$CFG->prefix}course c $teachertable WHERE $categoryselect $visiblecourses";
$totalcount = count_records_sql("SELECT COUNT(DISTINCT c.id) FROM $selectsql");
return get_records_sql("SELECT DISTINCT $fields FROM $selectsql ORDER BY $sort $limit");
}
/**
* shortdesc
*
* longdesc
*
* @param type description
*/
function get_my_courses($userid, $sort="visible DESC,sortorder ASC") {
global $CFG;
$course = array();
if ($students = get_records("user_students", "userid", $userid, "", "id, course")) {
foreach ($students as $student) {
$course[$student->course] = $student->course;
}
}
if ($teachers = get_records("user_teachers", "userid", $userid, "", "id, course")) {
foreach ($teachers as $teacher) {
$course[$teacher->course] = $teacher->course;
}
}
if (empty($course)) {
return $course;
}
$courseids = implode(',', $course);
return get_records_list("course", "id", $courseids, $sort);
// The following is correct but VERY slow with large datasets
//
// return get_records_sql("SELECT c.*
// FROM {$CFG->prefix}course c,
// {$CFG->prefix}user_students s,
// {$CFG->prefix}user_teachers t
// WHERE (s.userid = '$userid' AND s.course = c.id)
// OR (t.userid = '$userid' AND t.course = c.id)
// GROUP BY c.id
// ORDER BY $sort");
}
/**
* Returns a list of courses that match a search
*
* Returns a list of courses that match a search
*
* @param type description
*/
function get_courses_search($searchterms, $sort="fullname ASC", $page=0, $recordsperpage=50, &$totalcount) {
global $CFG;
switch ($CFG->dbtype) {
case "mysql":
$limit = "LIMIT $page,$recordsperpage";
break;
case "postgres7":
$limit = "LIMIT $recordsperpage OFFSET ".($page * $recordsperpage);
break;
default:
$limit = "LIMIT $recordsperpage,$page";
}
//to allow case-insensitive search for postgesql
if ($CFG->dbtype == "postgres7") {
$LIKE = "ILIKE";
$NOTLIKE = "NOT ILIKE"; // case-insensitive
$REGEXP = "~*";
$NOTREGEXP = "!~*";
} else {
$LIKE = "LIKE";
$NOTLIKE = "NOT LIKE";
$REGEXP = "REGEXP";
$NOTREGEXP = "NOT REGEXP";
}
$fullnamesearch = "";
$summarysearch = "";
foreach ($searchterms as $searchterm) {
if ($fullnamesearch) {
$fullnamesearch .= " AND ";
}
if ($summarysearch) {
$summarysearch .= " AND ";
}
if (substr($searchterm,0,1) == "+") {
$searchterm = substr($searchterm,1);
$summarysearch .= " summary $REGEXP '(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)' ";
$fullnamesearch .= " fullname $REGEXP '(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)' ";
} else if (substr($searchterm,0,1) == "-") {
$searchterm = substr($searchterm,1);
$summarysearch .= " summary $NOTREGEXP '(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)' ";
$fullnamesearch .= " fullname $NOTREGEXP '(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)' ";
} else {
$summarysearch .= " summary $LIKE '%$searchterm%' ";
$fullnamesearch .= " fullname $LIKE '%$searchterm%' ";
}
}
$selectsql = "{$CFG->prefix}course WHERE ($fullnamesearch OR $summarysearch) AND category > '0'";
$totalcount = count_records_sql("SELECT COUNT(*) FROM $selectsql");
$courses = get_records_sql("SELECT * FROM $selectsql ORDER BY $sort $limit");
if ($courses) { /// Remove unavailable courses from the list
foreach ($courses as $key => $course) {
if (!$course->visible) {
if (!isteacher($course->id)) {
unset($courses[$key]);
$totalcount--;
}
}
}
}
return $courses;
}
/**
* Returns a sorted list of categories
*
* Returns a sorted list of categories
*
* @param type description
*/
function get_categories($parent="none", $sort="sortorder ASC") {
if ($parent == "none") {
$categories = get_records("course_categories", "", "", $sort);
} else {
$categories = get_records("course_categories", "parent", $parent, $sort);
}
if ($categories) { /// Remove unavailable categories from the list
$creator = iscreator();
foreach ($categories as $key => $category) {
if (!$category->visible) {
if (!$creator) {
unset($categories[$key]);
}
}
}
}
return $categories;
}
/**
* This recursive function makes sure that the courseorder is consecutive
*
* @param type description
*/
function fix_course_sortorder($categoryid=0, $n=0) {
$count = 0;
if ($courses = get_courses($categoryid)) {
foreach ($courses as $course) {
set_field('course', 'sortorder', $n, 'id', $course->id);
$n++;
$count++;
}
}
set_field("course_categories", "coursecount", $count, "id", $categoryid);
if ($categories = get_categories($categoryid)) {
foreach ($categories as $category) {
$n = fix_course_sortorder($category->id, $n);
}
}
return $n;
}
/**
* This function creates a default separated/connected scale
*
* This function creates a default separated/connected scale
* so there's something in the database. The locations of
* strings and files is a bit odd, but this is because we
* need to maintain backward compatibility with many different
* existing language translations and older sites.
*
* @param type description
*/
function make_default_scale() {
global $CFG;
$defaultscale = NULL;
$defaultscale->courseid = 0;
$defaultscale->userid = 0;
$defaultscale->name = get_string("separateandconnected");
$defaultscale->scale = get_string("postrating1", "forum").",".
get_string("postrating2", "forum").",".
get_string("postrating3", "forum");
$defaultscale->timemodified = time();
/// Read in the big description from the file. Note this is not
/// HTML (despite the file extension) but Moodle format text.
$parentlang = get_string("parentlang");
if (is_readable("$CFG->dirroot/lang/$CFG->lang/help/forum/ratings.html")) {
$file = file("$CFG->dirroot/lang/$CFG->lang/help/forum/ratings.html");
} else if ($parentlang and is_readable("$CFG->dirroot/lang/$parentlang/help/forum/ratings.html")) {
$file = file("$CFG->dirroot/lang/$parentlang/help/forum/ratings.html");
} else if (is_readable("$CFG->dirroot/lang/en/help/forum/ratings.html")) {
$file = file("$CFG->dirroot/lang/en/help/forum/ratings.html");
} else {
$file = "";
}
$defaultscale->description = addslashes(implode("", $file));
if ($defaultscale->id = insert_record("scale", $defaultscale)) {
execute_sql("UPDATE {$CFG->prefix}forum SET scale = '$defaultscale->id'", false);
}
}
/**
* Returns a menu of all available scales from the site as well as the given course
*
* Returns a menu of all available scales from the site as well as the given course
*
* @param type description
*/
function get_scales_menu($courseid=0) {
global $CFG;
$sql = "SELECT id, name FROM {$CFG->prefix}scale
WHERE courseid = '0' or courseid = '$courseid'
ORDER BY courseid ASC, name ASC";
if ($scales = get_records_sql_menu("$sql")) {
return $scales;
}
make_default_scale();
return get_records_sql_menu("$sql");
}
/// MODULE FUNCTIONS /////////////////////////////////////////////////
/**
* Just gets a raw list of all modules in a course
*
* Just gets a raw list of all modules in a course
*
* @param type description
*/
function get_course_mods($courseid) {
global $CFG;
return get_records_sql("SELECT cm.*, m.name as modname
FROM {$CFG->prefix}modules m,
{$CFG->prefix}course_modules cm
WHERE cm.course = '$courseid'
AND cm.deleted = '0'
AND cm.module = m.id ");
}
/**
* Given an instance of a module, finds the coursemodule description
*
* Given an instance of a module, finds the coursemodule description
*
* @param type description
*/
function get_coursemodule_from_instance($modulename, $instance, $courseid) {
global $CFG;
return get_record_sql("SELECT cm.*, m.name
FROM {$CFG->prefix}course_modules cm,
{$CFG->prefix}modules md,
{$CFG->prefix}$modulename m
WHERE cm.course = '$courseid' AND
cm.deleted = '0' AND
cm.instance = m.id AND
md.name = '$modulename' AND
md.id = cm.module AND
m.id = '$instance'");
}
/**
* Returns an array of all the active instances of a particular module in a given course, sorted in the order they are defined
*
* Returns an array of all the active instances of a particular
* module in a given course, sorted in the order they are defined
* in the course. Returns false on any errors.
*
* @param string $modulename the name of the module to get instances for
* @param object(course) $course this depends on an accurate $course->modinfo
*/
function get_all_instances_in_course($modulename, $course) {
global $CFG;
if (!$modinfo = unserialize($course->modinfo)) {
return array();
}
if (!$rawmods = get_records_sql("SELECT cm.id as coursemodule, m.*,cw.section,cm.visible as visible,cm.groupmode
FROM {$CFG->prefix}course_modules cm,
{$CFG->prefix}course_sections cw,
{$CFG->prefix}modules md,
{$CFG->prefix}$modulename m
WHERE cm.course = '$course->id' AND
cm.instance = m.id AND
cm.deleted = '0' AND
cm.section = cw.id AND
md.name = '$modulename' AND
md.id = cm.module")) {
return array();
}
// Hide non-visible instances from students
if (isteacher($course->id)) {
$invisible = -1;
} else {
$invisible = 0;
}
foreach ($modinfo as $mod) {
if ($mod->mod == $modulename and $mod->visible > $invisible) {
$instance = $rawmods[$mod->cm];
if (!empty($mod->extra)) {
$instance->extra = $mod->extra;
}
$outputarray[] = $instance;
}
}
return $outputarray;
}
/**
* determine whether a module instance is visible within a course
*
* Given a valid module object with info about the id and course,
* and the module's type (eg "forum") returns whether the object
* is visible or not
*
* @param type description
*/
function instance_is_visible($moduletype, $module) {
global $CFG;
if ($records = get_records_sql("SELECT cm.instance, cm.visible
FROM {$CFG->prefix}course_modules cm,
{$CFG->prefix}modules m
WHERE cm.course = '$module->course' AND
cm.module = m.id AND
m.name = '$moduletype' AND
cm.instance = '$module->id'")) {
foreach ($records as $record) { // there should only be one - use the first one
return $record->visible;
}
}
return true; // visible by default!
}
/// LOG FUNCTIONS /////////////////////////////////////////////////////
/**
* Add an entry to the log table.
*
* Add an entry to the log table. These are "action" focussed rather
* than web server hits, and provide a way to easily reconstruct what
* any particular student has been doing.
*
* @param int $course the course id
* @param string $module the module name - e.g. forum, journal, resource, course, user etc
* @param string $action view, edit, post (often but not always the same as the file.php)
* @param string $url the file and parameters used to see the results of the action
* @param string $info additional description information
* @param string $cm the course_module->id if there is one
* @param string $user if log regards $user other than $USER
*/
function add_to_log($courseid, $module, $action, $url="", $info="", $cm=0, $user=0) {
global $db, $CFG, $USER, $REMOTE_ADDR;
if ($user) {
$userid = $user;
} else {
if (isset($USER->realuser)) { // Don't log
return;
}
$userid = empty($USER->id) ? "0" : $USER->id;
}
$timenow = time();
$info = addslashes($info);
$result = $db->Execute("INSERT INTO {$CFG->prefix}log (time, userid, course, ip, module, cmid, action, url, info)
VALUES ('$timenow', '$userid', '$courseid', '$REMOTE_ADDR', '$module', '$cm', '$action', '$url', '$info')");
if (!$result and ($CFG->debug > 7)) {
echo "<P>Error: Could not insert a new entry to the Moodle log</P>"; // Don't throw an error
}
if (!$user) {
if (isstudent($courseid)) {
$db->Execute("UPDATE {$CFG->prefix}user_students SET timeaccess = '$timenow' ".
"WHERE course = '$courseid' AND userid = '$userid'");
}
if (isteacher($courseid, false, false)) {
$db->Execute("UPDATE {$CFG->prefix}user_teachers SET timeaccess = '$timenow' ".
"WHERE course = '$courseid' AND userid = '$userid'");
}
}
}
/**
* select all log records based on SQL criteria
*
* select all log records based on SQL criteria
*
* @param string $select SQL select criteria
* @param string $order SQL order by clause to sort the records returned
*/
function get_logs($select, $order="l.time DESC", $limitfrom="", $limitnum="", &$totalcount) {
global $CFG;
if ($limitfrom !== "") {
switch ($CFG->dbtype) {
case "mysql":
$limit = "LIMIT $limitfrom,$limitnum";
break;
case "postgres7":
$limit = "LIMIT $limitnum OFFSET $limitfrom";
break;
default:
$limit = "LIMIT $limitnum,$limitfrom";
}
} else {
$limit = "";
}
if ($order) {
$order = "ORDER BY $order";
}
$selectsql = "{$CFG->prefix}log l LEFT JOIN {$CFG->prefix}user u ON l.userid = u.id ".((strlen($select) > 0) ? "WHERE $select" : "");
$totalcount = count_records_sql("SELECT COUNT(*) FROM $selectsql");
return get_records_sql("SELECT l.*, u.firstname, u.lastname, u.picture
FROM $selectsql $order $limit");
}
/**
* select all log records for a given course and user
*
* select all log records for a given course and user
*
* @param type description
*/
function get_logs_usercourse($userid, $courseid, $coursestart) {
global $CFG;
if ($courseid) {
$courseselect = " AND course = '$courseid' ";
}
return get_records_sql("SELECT floor((`time` - $coursestart)/86400) as day, count(*) as num
FROM {$CFG->prefix}log
WHERE userid = '$userid'
AND `time` > '$coursestart' $courseselect
GROUP BY day ");
}
/**
* select all log records for a given course, user, and day
*
* select all log records for a given course, user, and day
*
* @param type description
*/
function get_logs_userday($userid, $courseid, $daystart) {
global $CFG;
if ($courseid) {
$courseselect = " AND course = '$courseid' ";
}
return get_records_sql("SELECT floor((`time` - $daystart)/3600) as hour, count(*) as num
FROM {$CFG->prefix}log
WHERE userid = '$userid'
AND `time` > '$daystart' $courseselect
GROUP BY hour ");
}
/**
* Returns an object with counts of failed login attempts
*
* Returns information about failed login attempts. If the current user is
* an admin, then two numbers are returned: the number of attempts and the
* number of accounts. For non-admins, only the attempts on the given user
* are shown.
*
* @param mode - admin, teacher or everybody
* @param username - the username we are searching for
* @param lastlogin - the date from which we are searching
*/
function count_login_failures($mode, $username, $lastlogin) {
$select = "module='login' AND action='error' AND time > $lastlogin";
if (isadmin()) { // Return information about all accounts
if ($count->attempts = count_records_select('log', $select)) {
$count->accounts = count_records_select('log', $select, 'COUNT(DISTINCT info)');
return $count;
}
} else if ($mode == 'everybody' or ($mode == 'teacher' and isteacher())) {
if ($count->attempts = count_records_select('log', "$select AND info = '$username'")) {
return $count;
}
}
return NULL;
}
/// GENERAL HELPFUL THINGS ///////////////////////////////////
/**
* dump a given object's information in a PRE block
*
* dump a given object's information in a PRE block
* Mostly just for debugging
*
* @param type description
*/
function print_object($object) {
echo "<PRE>";
print_r($object);
echo "</PRE>";
}
// vim:autoindent:expandtab:shiftwidth=4:tabstop=4:tw=140:
?>