Пример #1
0
/**
 * 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
 *
 * @uses $CFG
 * @uses $db
 * @param string $table The database table to be checked against.
 * @param object $dataobject An object with contents equal to fieldname=>fieldvalue. Must have an entry for 'id' to map to the table specified.
 * @return bool
 */
function update_record($table, $dataobject)
{
    global $db, $CFG;
    if (!isset($dataobject->id)) {
        return false;
    }
    /// Check we are handling a proper $dataobject
    if (is_array($dataobject)) {
        debugging('Warning. Wrong call to update_record(). $dataobject must be an object. array found instead', DEBUG_DEVELOPER);
        $dataobject = (object) $dataobject;
    }
    // Remove this record from record cache since it will change
    if (!empty($CFG->rcache)) {
        // no === here! breaks upgrade
        rcache_unset($table, $dataobject->id);
    }
    /// Temporary hack as part of phasing out all access to obsolete user tables  XXX
    if (!empty($CFG->rolesactive)) {
        if (in_array($table, array('user_students', 'user_teachers', 'user_coursecreators', 'user_admins'))) {
            if (debugging()) {
                var_dump(debug_backtrace());
            }
            error('This SQL relies on obsolete tables (' . $table . ')!  Your code must be fixed by a developer.');
        }
    }
    /// Begin DIRTY HACK
    if ($CFG->dbfamily == 'oracle') {
        oracle_dirty_hack($table, $dataobject);
        // Convert object to the correct "empty" values for Oracle DB
    }
    /// End DIRTY HACK
    /// Under Oracle, MSSQL and PostgreSQL we have our own update record process
    /// detect all the clob/blob fields and delete them from the record being updated
    /// saving them into $foundclobs and $foundblobs [$fieldname]->contents
    /// They will be updated later
    if (($CFG->dbfamily == 'oracle' || $CFG->dbfamily == 'mssql' || $CFG->dbfamily == 'postgres') && !empty($dataobject->id)) {
        /// Detect lobs
        $foundclobs = array();
        $foundblobs = array();
        db_detect_lobs($table, $dataobject, $foundclobs, $foundblobs, true);
    }
    // Determine all the fields in the table
    if (!($columns = $db->MetaColumns($CFG->prefix . $table))) {
        return false;
    }
    $data = (array) $dataobject;
    if (defined('MDL_PERFDB')) {
        global $PERF;
        $PERF->dbqueries++;
    }
    // Pull out data matching these fields
    $ddd = array();
    foreach ($columns as $column) {
        if ($column->name != 'id' and array_key_exists($column->name, $data)) {
            $ddd[$column->name] = $data[$column->name];
        }
    }
    // Construct SQL queries
    $numddd = count($ddd);
    $count = 0;
    $update = '';
    /// Only if we have fields to be updated (this will prevent both wrong updates +
    /// updates of only LOBs in Oracle
    if ($numddd) {
        foreach ($ddd as $key => $value) {
            $count++;
            if ($value === NULL) {
                $update .= $key . ' = NULL';
                // previously NULLs were not updated
            } else {
                $update .= $key . ' = \'' . $value . '\'';
                // All incoming data is already quoted
            }
            if ($count < $numddd) {
                $update .= ', ';
            }
        }
        if (!($rs = $db->Execute('UPDATE ' . $CFG->prefix . $table . ' SET ' . $update . ' WHERE id = \'' . $dataobject->id . '\''))) {
            debugging($db->ErrorMsg() . '<br /><br />UPDATE ' . $CFG->prefix . $table . ' SET ' . s($update) . ' WHERE id = \'' . $dataobject->id . '\'');
            if (!empty($CFG->dblogerror)) {
                $debug = array_shift(debug_backtrace());
                error_log("SQL " . $db->ErrorMsg() . " in {$debug['file']} on line {$debug['line']}. STATEMENT:  UPDATE {$CFG->prefix}{$table} SET {$update} WHERE id = '{$dataobject->id}'");
            }
            return false;
        }
    }
    /// Under Oracle, MSSQL and PostgreSQL, finally, update all the Clobs and Blobs present in the record
    /// if we know we have some of them in the query
    if (($CFG->dbfamily == 'oracle' || $CFG->dbfamily == 'mssql' || $CFG->dbfamily == 'postgres') && !empty($dataobject->id) && (!empty($foundclobs) || !empty($foundblobs))) {
        if (!db_update_lobs($table, $dataobject->id, $foundclobs, $foundblobs)) {
            return false;
            //Some error happened while updating LOBs
        }
    }
    return true;
}
Пример #2
0
/**
 * 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
 *
 * @uses $CFG
 * @uses $db
 * @param string $table The database table to be checked against.
 * @param object $dataobject An object with contents equal to fieldname=>fieldvalue. Must have an entry for 'id' to map to the table specified.
 * @return bool
 */
function update_record($table, $dataobject)
{
    global $db, $CFG;
    // integer value in id propery required
    if (empty($dataobject->id)) {
        return false;
    }
    $dataobject->id = (int) $dataobject->id;
    /// Check we are handling a proper $dataobject
    if (is_array($dataobject)) {
        debugging('Warning. Wrong call to update_record(). $dataobject must be an object. array found instead', DEBUG_DEVELOPER);
        $dataobject = (object) $dataobject;
    } else {
        if (is_object($dataobject)) {
            // make sure there are no properties or private methods because we cast to array later,
            // at the same time this undos the object references so that PHP 5 works the same as PHP 4,
            // the main reason for this is BC after the dirty magic hack introduction
            if ($properties = get_object_vars($dataobject)) {
                $dataobject = (object) $properties;
            }
            unset($properties);
        }
    }
    /// Extra protection against SQL injections
    foreach ((array) $dataobject as $k => $v) {
        $dataobject->{$k} = sql_magic_quotes_hack($v);
    }
    // Remove this record from record cache since it will change
    if (!empty($CFG->rcache)) {
        // no === here! breaks upgrade
        rcache_unset($table, $dataobject->id);
    }
    /// Temporary hack as part of phasing out all access to obsolete user tables  XXX
    if (!empty($CFG->rolesactive)) {
        if (in_array($table, array('user_students', 'user_teachers', 'user_coursecreators', 'user_admins'))) {
            if (debugging()) {
                var_dump(debug_backtrace());
            }
            error('This SQL relies on obsolete tables (' . $table . ')!  Your code must be fixed by a developer.');
        }
    }
    /// Begin DIRTY HACK
    if ($CFG->dbfamily == 'oracle') {
        oracle_dirty_hack($table, $dataobject);
        // Convert object to the correct "empty" values for Oracle DB
    }
    /// End DIRTY HACK
    /// Under Oracle, MSSQL and PostgreSQL we have our own update record process
    /// detect all the clob/blob fields and delete them from the record being updated
    /// saving them into $foundclobs and $foundblobs [$fieldname]->contents
    /// They will be updated later
    if (($CFG->dbfamily == 'oracle' || $CFG->dbfamily == 'mssql' || $CFG->dbfamily == 'postgres') && !empty($dataobject->id)) {
        /// Detect lobs
        $foundclobs = array();
        $foundblobs = array();
        db_detect_lobs($table, $dataobject, $foundclobs, $foundblobs, true);
    }
    // Determine all the fields in the table
    if (!($columns = $db->MetaColumns($CFG->prefix . $table))) {
        return false;
    }
    $data = (array) $dataobject;
    if (defined('MDL_PERFDB')) {
        global $PERF;
        $PERF->dbqueries++;
    }
    // Pull out data matching these fields
    $update = array();
    foreach ($columns as $column) {
        if ($column->name == 'id') {
            continue;
        }
        if (array_key_exists($column->name, $data)) {
            $key = $column->name;
            $value = $data[$key];
            if (is_null($value)) {
                $update[] = "{$key} = NULL";
                // previously NULLs were not updated
            } else {
                if (is_bool($value)) {
                    $value = (int) $value;
                    $update[] = "{$key} = {$value}";
                    // lets keep pg happy, '' is not correct smallint MDL-13038
                } else {
                    $update[] = "{$key} = '{$value}'";
                    // All incoming data is already quoted
                }
            }
        }
    }
    /// Only if we have fields to be updated (this will prevent both wrong updates +
    /// updates of only LOBs in Oracle
    if ($update) {
        $query = "UPDATE {$CFG->prefix}{$table} SET " . implode(',', $update) . " WHERE id = {$dataobject->id}";
        if (!($rs = $db->Execute($query))) {
            debugging($db->ErrorMsg() . '<br /><br />' . s($query));
            if (!empty($CFG->dblogerror)) {
                $debug = array_shift(debug_backtrace());
                error_log("SQL " . $db->ErrorMsg() . " in {$debug['file']} on line {$debug['line']}. STATEMENT:  {$query}");
            }
            return false;
        }
    }
    /// Under Oracle, MSSQL and PostgreSQL, finally, update all the Clobs and Blobs present in the record
    /// if we know we have some of them in the query
    if (($CFG->dbfamily == 'oracle' || $CFG->dbfamily == 'mssql' || $CFG->dbfamily == 'postgres') && !empty($dataobject->id) && (!empty($foundclobs) || !empty($foundblobs))) {
        if (!db_update_lobs($table, $dataobject->id, $foundclobs, $foundblobs)) {
            return false;
            //Some error happened while updating LOBs
        }
    }
    return true;
}
Пример #3
0
/**
 * Store user last access times - called when use enters a course or site
 *
 * Note: we use ADOdb code directly in this function to save some CPU
 * cycles here and there. They are simple operations not needing any
 * of the postprocessing performed by dmllib.php
 *
 * @param int $courseid, empty means site
 * @return void
 */
function user_accesstime_log($courseid = 0)
{
    global $USER, $CFG, $PERF, $db;
    if (!isloggedin() or !empty($USER->realuser)) {
        // no access tracking
        return;
    }
    if (empty($courseid)) {
        $courseid = SITEID;
    }
    $timenow = time();
    /// Store site lastaccess time for the current user
    if ($timenow - $USER->lastaccess > LASTACCESS_UPDATE_SECS) {
        /// Update $USER->lastaccess for next checks
        $USER->lastaccess = $timenow;
        if (defined('MDL_PERFDB')) {
            global $PERF;
            $PERF->dbqueries++;
        }
        $remoteaddr = getremoteaddr();
        if ($db->Execute("UPDATE {$CFG->prefix}user\n                             SET lastip = '{$remoteaddr}', lastaccess = {$timenow}\n                           WHERE id = {$USER->id}")) {
        } else {
            debugging('Error: Could not update global user lastaccess information');
            // Don't throw an error
        }
        /// Remove this record from record cache since it will change
        if (!empty($CFG->rcache)) {
            rcache_unset('user', $USER->id);
        }
    }
    if ($courseid == SITEID) {
        ///  no user_lastaccess for frontpage
        return;
    }
    /// Store course lastaccess times for the current user
    if (empty($USER->currentcourseaccess[$courseid]) or $timenow - $USER->currentcourseaccess[$courseid] > LASTACCESS_UPDATE_SECS) {
        if (defined('MDL_PERFDB')) {
            global $PERF;
            $PERF->dbqueries++;
        }
        $exists = false;
        // To detect if the user_lastaccess record exists or no
        if ($rs = $db->Execute("SELECT timeaccess\n                                  FROM {$CFG->prefix}user_lastaccess\n                                 WHERE userid = {$USER->id} AND courseid = {$courseid}")) {
            if (!$rs->EOF) {
                $exists = true;
                $lastaccess = reset($rs->fields);
                if ($timenow - $lastaccess < LASTACCESS_UPDATE_SECS) {
                    /// no need to update now, it was updated recently in concurrent login ;-)
                    $rs->Close();
                    return;
                }
            }
            $rs->Close();
        }
        /// Update course lastaccess for next checks
        $USER->currentcourseaccess[$courseid] = $timenow;
        if (defined('MDL_PERFDB')) {
            global $PERF;
            $PERF->dbqueries++;
        }
        if ($exists) {
            // user_lastaccess record exists, update it
            if ($db->Execute("UPDATE {$CFG->prefix}user_lastaccess\n                                 SET timeaccess = {$timenow}\n                               WHERE userid = {$USER->id} AND courseid = {$courseid}")) {
            } else {
                debugging('Error: Could not update course user lastacess information');
                // Don't throw an error
            }
        } else {
            // user lastaccess record doesn't exist, insert it
            if ($db->Execute("INSERT INTO {$CFG->prefix}user_lastaccess\n                                     (userid, courseid, timeaccess)\n                              VALUES ({$USER->id}, {$courseid}, {$timenow})")) {
            } else {
                debugging('Error: Could not insert course user lastaccess information');
                // Don't throw an error
            }
        }
    }
}
Пример #4
0
/**
 * 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.
 *
 * @uses $CFG
 * @uses $USER
 * @uses $db
 * @uses $REMOTE_ADDR
 * @uses SITEID
 * @param    int     $courseid  The course id
 * @param    string  $module  The module name - e.g. forum, journal, resource, course, user etc
 * @param    string  $action  'view', 'update', 'add' or 'delete', possibly followed by another word to clarify.
 * @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)
{
    // Note that this function intentionally does not follow the normal Moodle DB access idioms.
    // This is for a good reason: it is the most frequently used DB update function,
    // so it has been optimised for speed.
    global $db, $CFG, $USER;
    if ($cm === '' || is_null($cm)) {
        // postgres won't translate empty string to its default
        $cm = 0;
    }
    if ($user) {
        $userid = $user;
    } else {
        if (!empty($USER->realuser)) {
            // Don't log
            return;
        }
        $userid = empty($USER->id) ? '0' : $USER->id;
    }
    $REMOTE_ADDR = getremoteaddr();
    $timenow = time();
    $info = addslashes($info);
    if (!empty($url)) {
        // could break doing html_entity_decode on an empty var.
        $url = html_entity_decode($url);
        // for php < 4.3.0 this is defined in moodlelib.php
    }
    if (defined('MDL_PERFDB')) {
        global $PERF;
        $PERF->dbqueries++;
        $PERF->logwrites++;
    }
    if ($CFG->type = 'oci8po') {
        if (empty($info)) {
            $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 debugging()) {
        echo '<p>Error: Could not insert a new entry to the Moodle log</p>';
        // Don't throw an error
    }
    /// Store lastaccess times for the current user, do not use in cron and other commandline scripts
    if (!empty($USER->id) && $userid == $USER->id && !defined('FULLME')) {
        $db->Execute('UPDATE ' . $CFG->prefix . 'user
                         SET lastip=\'' . $REMOTE_ADDR . '\', lastaccess=\'' . $timenow . '\'
                       WHERE id = \'' . $userid . '\' ');
        /// Remove this record from record cache since it will change
        if (!empty($CFG->rcache)) {
            rcache_unset('user', $userid);
        }
        if ($courseid != SITEID && !empty($courseid)) {
            if (defined('MDL_PERFDB')) {
                global $PERF;
                $PERF->dbqueries++;
            }
            if ($record = get_record('user_lastaccess', 'userid', $userid, 'courseid', $courseid)) {
                $record->timeaccess = $timenow;
                return update_record('user_lastaccess', $record);
            } else {
                $record = new object();
                $record->userid = $userid;
                $record->courseid = $courseid;
                $record->timeaccess = $timenow;
                return insert_record('user_lastaccess', $record);
            }
        }
    }
}