userName = ''; $this->password = ''; $this->callsign = null; $this->email = ''; $this->emailVerified = 0; $this->callsignVerified = 0; } /** * User class destructor ** Saves changes to the user record if there are any (and autoSave is not disabled) */ public function __destruct() { if ($this->_autoSave && $this->_isChanged) $this->save(); } /** * Set AutoSave ** Allows (or prevents) changes to the user record from being saved to the database at ** completion of script execution. Enabled by default. * * @param string $autoSave (True if changes are to be saved automatically, otherwise false) */ public function setAutoSave($autoSave) { $this->_autoSave = $autoSave; } /** * Check the username for validity, then set ** Has minimum 4 characters in length. ** Acceptable characters A-Z, a-z, 0-9, underscore(_), hyphen(-) * * @param string $username * @return boolean (True if username is acceptable and was set, otherwise false) */ public function setUsername($username) { // Remove whitespace $username = trim($username); // Test the username and set it if passes if (strlen($username) <= 4 || preg_match('/[^a-z_\-0-9]/i', $username) == 0) { // Username is good, check if it exists $user = UserRepository::getInstance()->getObjectByUsername($username); if (!$user->isExistingObject()) { $this->userName = $username; $this->_isChanged = true; return true; } $this->_lastError = 'Username is already in use.'; } else { $this->_lastError = 'Username is too short or contains invalid characters. Acceptable characters A-Z, a-z, 0-9, underscore(_), hyphen(-).'; } return false; } /** * Check the password for validity, then set and hash ** Has minimum 8 characters in length. Adjust it by modifying {8,} ** At least one uppercase English letter. You can remove this condition by removing (?=.*?[A-Z]) ** At least one lowercase English letter. You can remove this condition by removing (?=.*?[a-z]) ** At least one digit. You can remove this condition by removing (?=.*?[0-9]) ** //At least one special character, You can remove this condition by removing (?=.*?[#?!@$%^&*-]) ** ** "/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$/" * * @param string $password (Plain text password) * @return boolean (True if password is acceptable and was set, otherwise false) */ public function setPassword($password) { // Remove whitespace $password = trim($password); // Test the password and set it if passes (no ) if (preg_match("/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{8,}$/", $password) == 1) { // Password is good, hash it $this->password = password_hash($password, PASSWORD_ARGON2I); $this->_isChanged = true; return true; } else { $this->_lastError = 'Password does not meet length or complexity requirements.'; } return false; } /** * Check the password against the encrypted password. * * @param string $password (Plain text password) * @return boolean (True if password is correct, otherwise false) */ public function verifyPassword($password) { if ($this->password && !empty($this->password)) { // Remove whitespace $password = trim($password); return password_verify($password, $this->password); } return false; } /** * Check the password against the encrypted password. * * @return array (Cookie parameters, otherwise false) */ public function generatePersistentAuthToken() { // Generate a selector (aka database key) $selector = generateSecureToken(8); // Returns 16 bytes $identifier = generateSecureToken(32); // Returns 64 bytes $identifier_hashed = hash('sha256', $identifier); $cookie_expiration_time = time() + 7776000; // 90 days // Insert into the database $pdo = PDOMysqlConnection::getInstance(); $sql = 'INSERT INTO auth_tokens (user_id, selector, validator, expiration) VALUES (?, ?, ?, FROM_UNIXTIME(?))'; $stmt = $pdo->prepareAndExec($sql, [$this->_id, $selector, $identifier_hashed, $cookie_expiration_time]); $id = $pdo->lastInsertId(); if ($id) { return [ 'id' => $id, 'selector' => $selector, 'identifier'=> $identifier, 'expiration'=> $cookie_expiration_time ]; } return false; } /** * Validates the user token * * @param string $selector (Plain text 16 byte selector that identities the user) * @param string $identifier (Plain text 32 byte unique identifier that is compared against stored hash) * @return array (Cookie parameters, otherwise false) */ public function validatePersistentAuthToken($selector, $identifier) { $selector = trim($selector); // Get the latest token from the database $pdo = PDOMysqlConnection::getInstance(); $sql = 'SELECT validator, UNIX_TIMESTAMP(expiration) AS expires FROM auth_tokens WHERE user_id = ? AND selector = ? ORDER BY id DESC LIMIT 1'; $stmt = $pdo->prepareAndExec($sql, [$this->_id, $selector]); $latestToken = $stmt->fetch(PDO::FETCH_ASSOC); // Make sure a token was found and not expired if ($latestToken && $latestToken['expires'] > time()) { // Validate the validator against the stored hash if (hash_equals(hash('sha256', $identifier), $latestToken['validator'])) { return true; } } $this->_lastError = 'Persistent token not found.'; return false; } /** * Helper function for changing password by first checking the old password * against the encrypted password and setting the new password if the password * validates successfully. * * @param string $oldPassword (Password that is being changed) * @param string $newPassword (Password that is being set) * @return boolean (True if password is correct, otherwise false) */ public function changePassword($oldPassword, $newPassword) { // Can't do anything if the password has not been set (hashed) if ($this->password == null) { $this->_lastError = 'Cannot change password, no password is currently set.'; return false; } // Remove whitespace $oldPassword = trim($oldPassword); $newPassword = trim($newPassword); // Sanity check if (empty($oldPassword) || empty($newPassword)) { $this->_lastError = 'Cannot change password, old password or new password are empty.'; return false; } // Verify the old password and set if correct if ($this->verifyPassword($oldPassword)) { // setPassword will populate _lastError if the password is invalid return $this->setPassword($newPassword); } else { $this->_lastError = 'The old password is incorrect.'; } return false; } /** * Check the call for validity, then set ** Has minimum 4 characters in length. ** Acceptable characters A-Z, 0-9. Minimum length 3, Maximum length 10. * * @param string $callsign * @return boolean (True if callsign is acceptable and was set, otherwise false) */ public function setCallsign($callsign) { if (is_null($callsign) || strlen($callsign) == 0) { $this->callsign = null; return true; } // Remove whitespace & make all uppercase $callsign = strtoupper(trim($callsign)); // Test the password and set it if passes (no ) if (strlen($callsign) >= 3 && strlen($callsign) <= 10 && preg_match('/[^a-z0-9]/i', $callsign) == 0) { // Callsign is good, make sure it is not in use by another user $user = UserRepository::getInstance()->getObjectByCallsign($callsign); if (!$user->isExistingObject()) { if (!$this->isExistingObject() || ($this->isExistingObject() && is_null($this->callsign))) $this->callsign = $callsign; $this->callsignVerified = 0; $this->_isChanged = true; // Attempt callsign verification is the e-mail has already been verified if ($this->emailVerified) { $this->completeCallsignVerification(); } return true; } $this->_lastError = 'Callsign is already in use with another user.'; } else { $this->_lastError = 'Callsign must be 3-10 characters. Acceptable characters A-Z, 0-9.'; } return false; } /** * Check the email address for validity, then set ** Has minimum 4 characters in length. ** Acceptable characters A-Z, 0-9. Minimum length 3, Maximum length 10. * * @param string $callsign * @return boolean (True if email address is acceptable and was set, otherwise false) */ public function setEmail($email) { // Remove whitespace $email = strtolower(trim($email)); // Test the e-mail address and set it if passes (no ) // Also make sure it's not the same e-mail which wouldn't need to be saved if (filter_var($email, FILTER_VALIDATE_EMAIL) && $email != $this->email) { // Email is good, make sure it is not in use by another user $user = UserRepository::getInstance()->getObjectByEmail($email); if (!$user->isExistingObject()) { $this->email = $email; $this->_isChanged = true; $this->emailVerified = 0; return true; } $this->_lastError = 'E-mail address is already in use with another user.'; } else { $this->_lastError = 'E-mail address is not valid.'; } return false; } /** * Starts the e-mail verification process * * @return boolean (True if email with verification code was sent successfully) */ public function startEmailVerification() { // Do nothing if not enabled in config if (getWebsiteConfig('smtp_server_address') == '') return false; // Test the e-mail address before allowing the verification flag to be set to true if (!isset($this->email) || !filter_var($this->email, FILTER_VALIDATE_EMAIL)) { $this->_lastError = 'Cannot start e-mail verification, e-mail address is not valid.'; return false; } // Generate random reset code $code = generateSecureCode(6); // Code expires in 30 minutes $expiration = time() + 1800; // Get the site backend database connection $pdo = PDOMysqlConnection::getInstance(); // Save the code $sql = 'INSERT INTO email_verification (user_id, code, expiration) VALUES (?, ?, FROM_UNIXTIME(?))'; $stmt = $pdo->prepareAndExec($sql, [$this->_id, $code, $expiration]); $id = $pdo->lastInsertId(); if ($id) { // Set to unverified $this->emailVerified = false; $this->_isChanged = true; $this->_lastError = $code; $confirmation_link_with_code = ''; $confirmation_link_without_code = ''; // Send the confirmation e-mail $use_secure_smtp = !empty(getWebsiteConfig('smtp_server_password')) ? true : false; // Note: passing `true` enables exceptions $mail = new PHPMailer(true); try { // PHP_Mailer Server settings //$mail->SMTPDebug = \PHPMailer\PHPMailer\SMTP::DEBUG_SERVER; // Enable verbose debug output $mail->isSMTP(); // Send using SMTP $mail->Host = getWebsiteConfig('smtp_server_address'); // Set the SMTP server to send through $mail->SMTPAuth = $use_secure_smtp; // Enable SMTP authentication $mail->Username = getWebsiteConfig('smtp_server_username'); // SMTP username $mail->Password = getWebsiteConfig('smtp_server_password'); // SMTP password $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable implicit TLS encryption $mail->Port = getWebsiteConfig('smtp_server_port'); // TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS` // Set to & from addresses $mail->setFrom(getWebsiteConfig('smtp_from_email'), getWebsiteConfig('smtp_from_email')); $mail->addAddress($this->email, $this->userName); // Content $mail->isHTML(true); // Set email format to HTML $mail->Subject = 'Confirm your ' . getWebsiteConfig('title') . ' Account'; $mail->Body = 'You are receiving this e-mail because an account has been associated with this e-mail address at the ' . getWebsiteConfig('title') . "\r\nIf you believe that this has been received in error, you may safely disregard this message.\r\n" . "\r\n\r\n

If you recognize this account, please complete your account activation by confirming your e-mail address.\r\n" . 'Follow this link to verify your account. If asked, enter code ' . $code . "\r\n\r\n" . "\r\n" . '

Questions? Please contact us.' . "\r\n"; $mail->AltBody = 'You are receiving this e-mail because an account has been associated with this e-mail address at the ' . getWebsiteConfig('title') . getWebsiteConfig('cookie_domain') . "\r\nIf you believe that this has been received in error, you may safely disregard this message.\e\n" . "\r\n\r\nIf you recognize this account, please complete your account activation by confirming your e-mail address.\r\n" . "Go to " . getWebsiteConfig('email_link_url') . "/views/validate.php?a=email and enter code $code.\r\n\r\n" . "Questions? Please contact us at " . getWebsiteConfig('email_link_url') . "/views/contact.php\r\n"; $mail->send(); } catch (Exception $e) { $this->_lastError = "Activation e-mail could not be sent. Mailer Error: {$mail->ErrorInfo}"; return false; } return true; } $this->_lastError = 'An error occurred in generating or sending the email verification.'; return false; } /** * Completes e-mail verification. ** This is based on whether the user has completed e-mail verification by ** following the link in the e-mail or entering the code. * * @param string $code (Verification code to test) * @return boolean (True if email address is verification is complete, otherwise false) */ public function completeEmailVerification($code) { $code = trim($code); // Test the e-mail address before allowing the verification flag to be set to true if ($code && (!isset($this->email) || !filter_var($this->email, FILTER_VALIDATE_EMAIL))) { $this->_lastError = 'Cannot complete e-mail verification, e-mail address is not valid.'; return false; } // Get the lastest email verification record for the user $sql = 'SELECT code, UNIX_TIMESTAMP(expiration) AS expires FROM email_verification WHERE user_id = ? ORDER BY id DESC LIMIT 1'; $pdo = PDOMysqlConnection::getInstance(); $stmt = $pdo->prepareAndExec($sql, [$this->_id]); $verification = $stmt->fetch(PDO::FETCH_ASSOC); if ($verification) { // Does the code match, and is it not expired? if (time() < $verification['expires']) { if ($code == $verification['code']) { $this->emailVerified = true; $this->_isChanged = true; return true; } else { $this->_lastError = 'Cannot complete e-mail verification, verification code is incorrect.'; } } else { $this->_lastError = 'Cannot complete e-mail verification, verification code has expired.'; } } else { $this->_lastError = 'Cannot complete e-mail verification, no verification exists for this user.'; } return false; } /** * Returns the e-mail verification status as text * * @return string (Verified or Unverified) */ public function getEmailVerificationStatus() { return $this->emailVerified ? 'Verified' : 'Unverified'; } /** * Completes callsign verification. ** Contacts QRZ.com and pulls the users profile and verifies the e-mail address. * * @return boolean (True if callsign is verification is complete, otherwise false) */ public function completeCallsignVerification() { if (@is_null($this->callsign) || strlen($this->callsign) > 3) { // E-Mail address must first be verified if ($this->emailVerified == 1) { // Create a new instance of the QRZ helper class $qrz = new QRZ(); if ($qrz->queryCall($this->callsign)) { if (isset($qrz->Callsign) && isset($qrz->Callsign->email)) { if (strtolower($qrz->Callsign->email) == strtolower($this->email)) { $this->callsignVerified = 1; $this->_isChanged = true; return true; } else { $this->_lastError = 'The e-mail address does not match your public QRZ.com profile.'; } } else { $this->_lastError = 'No response or missing data reported by QRZ.com.'; } } else { // Pass the error from QRZ through $this->_lastError = $qrz->_lastError; } } else { $this->_lastError = 'E-mail address must be verified first.'; } } else { $this->_lastError = 'Invalid callsign.'; } return false; } /** * Returns thecallsign verification status as text * * @return string (Verified or Unverified) */ public function getCallsignVerificationStatus() { return $this->callsignVerified ? 'Verified' : 'Unverified'; } /** * Starts the password recovery process * * @return boolean (True if email with verification code was sent successfully) */ public function startPasswordRecovery() { // Do nothing if not enabled in config if (getWebsiteConfig('smtp_server_address') == '') return false; // Generate random reset code $code = generateSecureCode(6); // Code expires in 30 minutes $expiration = time() + 1800; // Get the site backend database connection $pdo = PDOMysqlConnection::getInstance(); // Save the code $sql = 'INSERT INTO password_verification (user_id, code, expiration) VALUES (?, ?, FROM_UNIXTIME(?))'; $stmt = $pdo->prepareAndExec($sql, [$this->_id, $code, $expiration]); $id = $pdo->lastInsertId(); if ($id) { $this->_lastError = $code; $confirmation_link_with_code = ''; $confirmation_link_without_code = ''; // Send the confirmation e-mail $use_secure_smtp = !empty(getWebsiteConfig('smtp_server_password')) ? true : false; // Note: passing `true` enables exceptions $mail = new PHPMailer(true); try { // PHP_Mailer Server settings //$mail->SMTPDebug = \PHPMailer\PHPMailer\SMTP::DEBUG_SERVER; // Enable verbose debug output $mail->isSMTP(); // Send using SMTP $mail->Host = getWebsiteConfig('smtp_server_address'); // Set the SMTP server to send through $mail->SMTPAuth = $use_secure_smtp; // Enable SMTP authentication $mail->Username = getWebsiteConfig('smtp_server_username'); // SMTP username $mail->Password = getWebsiteConfig('smtp_server_password'); // SMTP password $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable implicit TLS encryption $mail->Port = getWebsiteConfig('smtp_server_port'); // TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS` // Set to & from addresses $mail->setFrom(getWebsiteConfig('smtp_from_email'), getWebsiteConfig('smtp_from_email')); $mail->addAddress($this->email, $this->userName); // Content $mail->isHTML(true); // Set email format to HTML $mail->Subject = 'Password recovery for your ' . getWebsiteConfig('title') . ' account.'; $mail->Body = 'You are receiving this e-mail because an account which has been associated with this e-mail address at the ' . getWebsiteConfig('title') . " has requested a password reset.\r\nIf you believe that this has been received in error, you may safely disregard this message.\r\n" . "\r\n\r\n

If you recognize this account, please complete your password recovery by visitng the link below.\r\n" . 'Follow this link to reset your password. If asked, enter code ' . $code . "\r\n\r\n" . "\r\n" . '

Questions? Please contact us.' . "\r\n"; $mail->AltBody = 'You are receiving this e-mail because an account which has been associated with this e-mail address at the ' . getWebsiteConfig('title') . getWebsiteConfig('cookie_domain') . " has requested a password reset.\r\nIf you believe that this has been received in error, you may safely disregard this message.\e\n" . "\r\n\r\nIf you recognize this account, please complete your password recovery by visitng the link below.\r\n" . "Go to " . getWebsiteConfig('email_link_url') . "/views/validate.php?a=pass and enter code $code.\r\n\r\n" . "Questions? Please contact us at " . getWebsiteConfig('email_link_url') . "/views/contact.php\r\n"; $mail->send(); } catch (Exception $e) { $this->_lastError = "Password reset e-mail could not be sent. Mailer Error: {$mail->ErrorInfo}"; return false; } return true; } $this->_lastError = 'An error occurred in generating or sending the password reset email.'; return false; } /** * Completes password recovery process. ** This process validates the 6 digit code, and if confirmed ** return true to alow the password reset process to be completed. * * @param string $code (Verification code to test) * @param string $newpassword (New password to set if the code matches) * @return boolean (True if email address is verification is complete, otherwise false) */ public function completePasswordRecovery($code, $email, $newPassword) { $code = trim($code); $email = trim($email); $newPassword = trim($newPassword); // Get the lastest email verification record for the user $sql = 'SELECT user_id, UNIX_TIMESTAMP(expiration) AS expires FROM password_verification WHERE code = ? ORDER BY id DESC LIMIT 1'; $pdo = PDOMysqlConnection::getInstance(); $stmt = $pdo->prepareAndExec($sql, [$code]); $verification = $stmt->fetch(PDO::FETCH_ASSOC); if ($verification) { // Does the code match, and is it not expired? if (time() < $verification['expires']) { // Code is valid, load the user record $user = UserRepository::getInstance()->getObjectById($verification['user_id']); // Set the password if the user account is found if ($user->isExistingObject()) { // Compare the e-mail address provided if ($email == $user->email) { // Set the new password if it's valid then delete the reset code so it cannot be used again if ($user->setPassword($newPassword)) { $sql = 'DELETE FROM password_verification WHERE user_id = ?'; $pdo = PDOMysqlConnection::getInstance(); $stmt = $pdo->prepareAndExec($sql, [$user->_id]); return true; } else { $this->_lastError = $user->getLastError(); return false; // _lastError is set by setPassword(); } } else { $this->_lastError = 'Cannot complete password recovery, e-mail address provided is not on record.'; } } else { $this->_lastError = 'Cannot complete password recovery, verification code is incorrect.'; } } else { $this->_lastError = 'Cannot complete password recovery, verification code has expired.'; } } else { $this->_lastError = 'Cannot complete password recovery, no verification exists for this user.'; } return false; } /** * Save the user record if there are any changes pending * * @return boolean (True if save was successful, otherwise false) */ public function save() { // Don't save unless something has been changed if ($this->_isChanged === false) { $this->_lastError = 'No changes have been made to save.'; return false; } // Make sure all critical properties are completed if ($this->userName == null || $this->password == null || $this->email == null) { $this->_lastError = 'Cannot save, one or more user properties are missing.'; return false; } // Get the site backend database connection $pdo = PDOMysqlConnection::getInstance(); // Inserting or saving? if ($this->isExistingObject()) { $sql = 'UPDATE users SET user_name = ?, password = ?, callsign = ?, email = ?, email_verified = ?, callsign_verified = ? WHERE id = ? LIMIT 1'; $stmt = $pdo->prepareAndExec($sql, [$this->userName, $this->password, $this->callsign, $this->email, $this->emailVerified, $this->callsignVerified, $this->_id]); if ($stmt) { $this->_isChanged = false; return true; } $this->_lastError = 'An error occurred saving the user record.'; } else { $sql = 'INSERT INTO users (user_name, password, callsign, email, email_verified, callsign_verified) VALUES (?, ?, ?, ?, ?, ?)'; $stmt = $pdo->prepareAndExec($sql, [$this->userName, $this->password, $this->callsign, $this->email, $this->emailVerified, $this->callsignVerified]); $id = $pdo->lastInsertId(); if ($id) { $this->_id = $id; $this->_isChanged = false; return true; } $this->_lastError = 'An error occurred creating the user record.'; } return false; } /** * Checks the saved user favorite stations to see if the station is a favorite station * * @param int $station_id * @return boolean (True if station is a favorite, otherwise false) */ public function isStationAFavorite($station_id) { static $favorites = null; static $favoritesTS = null; if (!isInt($station_id)) return false; // Cache favorites for 30 seconds if (is_null($favorites) || (!is_null($favoritesTS) && $favoritesTS < time() - 30)) { $favorites = FavoriteStationRepository::getInstance()->getObjectListByUserId($this->id); $favoritesTS = time(); } if (is_null($favorites) || sizeof($favorites) == 0) return false; foreach($favorites AS $favorite) { if ($favorite->stationId == $station_id) return true; } return false; } /** * Records the a station browse (view) event */ public function recordStationBrowseHistory($station_id) { if (!isInt($station_id)) return false; // Only record history for valid users if ($this->isExistingObject()) { // Get the site backend database connection $pdo = PDOMysqlConnection::getInstance(); $sql = 'INSERT INTO station_browse_history SET user_id = ?, station_id = ?, view_time = NOW()'; $stmt = $pdo->prepareAndExec($sql, [$this->_id, $station_id]); if ($stmt) { return true; } $this->_lastError = 'An error occurred updating the user station browse history.'; } } /** * Returns a list of the stations the user has viewed * * @return Array (Station IDs with Last View Time) */ public function getStationBrowseHistory($iconScale = 16, $limit = 5) { if (!isInt($limit)) $limit = 5; // Only record history for valid users if ($this->isExistingObject()) { // Get the site backend database connection $pdoMysql = PDOMysqlConnection::getInstance(); $sql = "SELECT DISTINCT(station_id) FROM station_browse_history WHERE user_id = ? ORDER BY view_time DESC LIMIT $limit"; $stmt = $pdoMysql->prepareAndExec($sql, [$this->_id]); if ($stmt) { $records = $stmt->fetchAll(PDO::FETCH_ASSOC); $idList = implode(',', array_column($records, 'station_id')); // Main Database $pdo = PDOConnection::getInstance(); // Last viewed stations $history = []; if (count($records) > 0) { // Get full station details $query = $pdo->prepareAndExec ( "SELECT id,source_id,name,station_type_id,latest_confirmed_symbol,latest_confirmed_symbol_table,latest_confirmed_packet_timestamp FROM station WHERE latest_confirmed_packet_timestamp IS NOT NULL AND ID IN($idList) ORDER BY latest_confirmed_packet_timestamp DESC, name ASC;" ); $stationCache = []; while ($result = $query->fetch(PDO::FETCH_ASSOC)) { // Symbol if (strlen($result['latest_confirmed_symbol']) >= 1 && strlen($result['latest_confirmed_symbol_table']) >= 1) { $symbolAsciiValue = ord(substr($result['latest_confirmed_symbol'], 0, 1)); $symbolTableAsciiValue = ord(substr($result['latest_confirmed_symbol_table'], 0, 1)); } else { // Default values $symbolAsciiValue = 125; $symbolTableAsciiValue = 47; } // Symbol URL $symbolPath = '/symbols/symbol-' . $symbolAsciiValue . '-' . $symbolTableAsciiValue . '-scale'.$iconScale.'x'.$iconScale.'.svg'; $isFavorite = $this->isStationAFavorite($result['id']) ? 1 : 0; $stationCache[$result['id']] = ['id'=>$result['id'], 'source_id'=>$result['source_id'], 'type'=>$result['station_type_id'], 'text'=>$result['name'], 'icon'=>$symbolPath, 'fav'=>$isFavorite]; } foreach ($records AS $record) { if (isset($stationCache[$record['station_id']])) $history[] = $stationCache[$record['station_id']]; } } return $history; } $this->_lastError = 'An error occurred updating the user station browse history.'; } } /** * Delete the user record * * @return boolean (True if delete was successful, otherwise false) */ public function delete() { if ($this->isExistingObject()) { // Get the site backend database connection $pdo = PDOMysqlConnection::getInstance(); $sql = 'DELETE FROM users WHERE id = ? LIMIT 1'; $stmt = $pdo->prepareAndExec($sql, [$this->_id]); if ($stmt) { return true; } $this->_lastError = 'An error occurred deleting the user record.'; } } /** * Returns the last error message set during a user action then * sets _lastError to an empty string. * * @return string (Text of the last recorded error) */ public function getLastError() { $last_error = $this->_lastError; $this->_lastError = ''; return $last_error; } }