/** * @param integer $quizid the id of the quiz object. * @return boolean Whether this quiz has any non-blank feedback text. */ function quiz_has_feedback($quizid) { static $cache = array(); if (!array_key_exists($quizid, $cache)) { $cache[$quizid] = record_exists_select('quiz_feedback', "quizid = {$quizid} AND " . sql_isnotempty('quiz_feedback', 'feedbacktext', false, true)); } return $cache[$quizid]; }
/** * Given one user object (from backup file), perform all the neccesary * checks is order to decide how that user will be handled on restore. * * Note the function requires $user->mnethostid to be already calculated * so it's caller responsibility to set it * * This function is used both by @restore_precheck_users() and * @restore_create_users() to get consistent results in both places * * It returns: * - one user object (from DB), if match has been found and user will be remapped * - boolean true if the user needs to be created * - boolean false if some conflict happened and the user cannot be handled * * Each test is responsible for returning its results and interrupt * execution. At the end, boolean true (user needs to be created) will be * returned if no test has interrupted that. * * Here it's the logic applied, keep it updated: * * If restoring users from same site backup: * 1A - Normal check: If match by id and username and mnethost => ok, return target user * 1B - Handle users deleted in DB and "alive" in backup file: * If match by id and mnethost and user is deleted in DB and * (match by username LIKE 'backup_email.%' or by non empty email = md5(username)) => ok, return target user * 1C - Handle users deleted in backup file and "alive" in DB: * If match by id and mnethost and user is deleted in backup file * and match by email = email_without_time(backup_email) => ok, return target user * 1D - Conflict: If match by username and mnethost and doesn't match by id => conflict, return false * 1E - None of the above, return true => User needs to be created * * if restoring from another site backup (cannot match by id here, replace it by email/firstaccess combination): * 2A - Normal check: If match by username and mnethost and (email or non-zero firstaccess) => ok, return target user * 2B - Handle users deleted in DB and "alive" in backup file: * 2B1 - If match by mnethost and user is deleted in DB and not empty email = md5(username) and * (username LIKE 'backup_email.%' or non-zero firstaccess) => ok, return target user * 2B2 - If match by mnethost and user is deleted in DB and * username LIKE 'backup_email.%' and non-zero firstaccess) => ok, return target user * (to cover situations were md5(username) wasn't implemented on delete we requiere both) * 2C - Handle users deleted in backup file and "alive" in DB: * If match mnethost and user is deleted in backup file * and by email = email_without_time(backup_email) and non-zero firstaccess=> ok, return target user * 2D - Conflict: If match by username and mnethost and not by (email or non-zero firstaccess) => conflict, return false * 2E - None of the above, return true => User needs to be created * * Note: for DB deleted users email is stored in username field, hence we * are looking there for emails. See delete_user() * Note: for DB deleted users md5(username) is stored *sometimes* in the email field, * hence we are looking there for usernames if not empty. See delete_user() */ function restore_check_user($restore, $user) { global $CFG; // Verify mnethostid is set, return error if not // it's parent responsibility to define that before // arriving here if (empty($user->mnethostid)) { debugging("restore_check_user() wrong use, mnethostid not set for user {$user->username}", DEBUG_DEVELOPER); return false; } // Handle checks from same site backups if (backup_is_same_site($restore) && empty($CFG->forcedifferentsitecheckingusersonrestore)) { // 1A - If match by id and username and mnethost => ok, return target user if ($rec = get_record('user', 'id', $user->id, 'username', addslashes($user->username), 'mnethostid', $user->mnethostid)) { return $rec; // Matching user found, return it } // 1B - Handle users deleted in DB and "alive" in backup file // Note: for DB deleted users email is stored in username field, hence we // are looking there for emails. See delete_user() // Note: for DB deleted users md5(username) is stored *sometimes* in the email field, // hence we are looking there for usernames if not empty. See delete_user() // If match by id and mnethost and user is deleted in DB and // match by username LIKE 'backup_email.%' or by non empty email = md5(username) => ok, return target user if ($rec = get_record_sql("SELECT *\n FROM {$CFG->prefix}user u\n WHERE id = {$user->id}\n AND mnethostid = {$user->mnethostid}\n AND deleted = 1\n AND (\n username LIKE '" . addslashes($user->email) . ".%'\n OR (\n " . sql_isnotempty('user', 'email', false, false) . "\n AND email = '" . md5($user->username) . "'\n )\n )")) { return $rec; // Matching user, deleted in DB found, return it } // 1C - Handle users deleted in backup file and "alive" in DB // If match by id and mnethost and user is deleted in backup file // and match by email = email_without_time(backup_email) => ok, return target user if ($user->deleted) { // Note: for DB deleted users email is stored in username field, hence we // are looking there for emails. See delete_user() // Trim time() from email $trimemail = preg_replace('/(.*?)\\.[0-9]+.?$/', '\\1', $user->username); if ($rec = get_record_sql("SELECT *\n FROM {$CFG->prefix}user u\n WHERE id = {$user->id}\n AND mnethostid = {$user->mnethostid}\n AND email = '" . addslashes($trimemail) . "'")) { return $rec; // Matching user, deleted in backup file found, return it } } // 1D - If match by username and mnethost and doesn't match by id => conflict, return false if ($rec = get_record('user', 'username', addslashes($user->username), 'mnethostid', $user->mnethostid)) { if ($user->id != $rec->id) { return false; // Conflict, username already exists and belongs to another id } } // Handle checks from different site backups } else { // 2A - If match by username and mnethost and // (email or non-zero firstaccess) => ok, return target user if ($rec = get_record_sql("SELECT *\n FROM {$CFG->prefix}user u\n WHERE username = '******'\n AND mnethostid = {$user->mnethostid}\n AND (\n email = '" . addslashes($user->email) . "'\n OR (\n firstaccess != 0\n AND firstaccess = {$user->firstaccess}\n )\n )")) { return $rec; // Matching user found, return it } // 2B - Handle users deleted in DB and "alive" in backup file // Note: for DB deleted users email is stored in username field, hence we // are looking there for emails. See delete_user() // Note: for DB deleted users md5(username) is stored *sometimes* in the email field, // hence we are looking there for usernames if not empty. See delete_user() // 2B1 - If match by mnethost and user is deleted in DB and not empty email = md5(username) and // (by username LIKE 'backup_email.%' or non-zero firstaccess) => ok, return target user if ($rec = get_record_sql("SELECT *\n FROM {$CFG->prefix}user u\n WHERE mnethostid = {$user->mnethostid}\n AND deleted = 1\n AND " . sql_isnotempty('user', 'email', false, false) . "\n AND email = '" . md5($user->username) . "'\n AND (\n username LIKE '" . addslashes($user->email) . ".%'\n OR (\n firstaccess != 0\n AND firstaccess = {$user->firstaccess}\n )\n )")) { return $rec; // Matching user found, return it } // 2B2 - If match by mnethost and user is deleted in DB and // username LIKE 'backup_email.%' and non-zero firstaccess) => ok, return target user // (this covers situations where md5(username) wasn't being stored so we require both // the email & non-zero firstaccess to match) if ($rec = get_record_sql("SELECT *\n FROM {$CFG->prefix}user u\n WHERE mnethostid = {$user->mnethostid}\n AND deleted = 1\n AND username LIKE '" . addslashes($user->email) . ".%'\n AND firstaccess != 0\n AND firstaccess = {$user->firstaccess}")) { return $rec; // Matching user found, return it } // 2C - Handle users deleted in backup file and "alive" in DB // If match mnethost and user is deleted in backup file // and match by email = email_without_time(backup_email) and non-zero firstaccess=> ok, return target user if ($user->deleted) { // Note: for DB deleted users email is stored in username field, hence we // are looking there for emails. See delete_user() // Trim time() from email $trimemail = preg_replace('/(.*?)\\.[0-9]+.?$/', '\\1', $user->username); if ($rec = get_record_sql("SELECT *\n FROM {$CFG->prefix}user u\n WHERE mnethostid = {$user->mnethostid}\n AND email = '" . addslashes($trimemail) . "'\n AND firstaccess != 0\n AND firstaccess = {$user->firstaccess}")) { return $rec; // Matching user, deleted in backup file found, return it } } // 2D - If match by username and mnethost and not by (email or non-zero firstaccess) => conflict, return false if ($rec = get_record_sql("SELECT *\n FROM {$CFG->prefix}user u\n WHERE username = '******'\n AND mnethostid = {$user->mnethostid}\n AND NOT (\n email = '" . addslashes($user->email) . "'\n OR (\n firstaccess != 0\n AND firstaccess = {$user->firstaccess}\n )\n )")) { return false; // Conflict, username/mnethostid already exist and belong to another user (by email/firstaccess) } } // Arrived here, return true as the user will need to be created and no // conflicts have been found in the logic above. This covers: // 1E - else => user needs to be created, return true // 2E - else => user needs to be created, return true return true; }