questlab/models/UsersModel.inc

435 lines
14 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Questlab
*
* @author Oliver Hanraths <oliver.hanraths@uni-duesseldorf.de>
* @copyright 2014 2016 Heinrich-Heine-Universität Düsseldorf
* @license http://www.gnu.org/licenses/gpl.html
* @link https://github.com/coderkun/questlab
*/
namespace hhu\z\models;
/**
* Model of the UsersAgent to list users and get their data.
*
* @author Oliver Hanraths <oliver.hanraths@uni-duesseldorf.de>
*/
class UsersModel extends \hhu\z\Model
{
/**
* Construct a new UsersModel.
*/
public function __construct()
{
parent::__construct();
}
/**
* Get count of registered users.
*
* @param string $username Only get users with the given username (optional)
* @param string $name Only get users with the given name (optional)
* @param string $email Only get users with the given email address (optional)
* @return int Count of users
*/
public function getUsersCount($username=null, $name=null, $email=null)
{
// Create array of values
$values = array();
if(!is_null($username)) {
$values[] = sprintf('username LIKE \'%%%s%%\'', $username);
}
if(!is_null($name)) {
$values[] = sprintf('(surname LIKE \'%%%s%%\' OR prename LIKE \'%%%s%%\')', $name, $name);
}
if(!is_null($email)) {
$values[] = sprintf('email LIKE \'%%%s%%\'', $email);
}
// Execute query
$data = $this->db->query(
'SELECT count(DISTINCT id) AS c '.
'FROM users '.
(!empty($values) ? sprintf('WHERE %s', implode(' AND ', $values)) : null)
);
if(!empty($data)) {
return $data[0]['c'];
}
return 0;
}
/**
* Get registered users.
*
* @throws \nre\exceptions\ParamsNotValidException
* @param string $sort Field to sort by
* @param string $username Only get users with the given username (optional)
* @param string $name Only get users with the given name (optional)
* @param string $email Only get users with the given email address (optional)
* @param int $limit Limit amount of Characters (optional)
* @param int $offset Offset (optional)
* @return array Users
*/
public function getUsers($sort, $username=null, $name=null, $email=null, $limit=null, $offset=0)
{
// Create array of values
$values = array();
if(!is_null($username)) {
$values[] = sprintf('username LIKE \'%%%s%%\'', $username);
}
if(!is_null($name)) {
$values[] = sprintf('(surname LIKE \'%%%s%%\' OR prename LIKE \'%%%s%%\')', $name, $name);
}
if(!is_null($email)) {
$values[] = sprintf('email LIKE \'%%%s%%\'', $email);
}
// Execute query
switch($sort)
{
case 'username':
case 'created':
$orders = array(
'username' => 'ASC',
'created' => 'DESC'
);
return $this->db->query(
'SELECT id, created, username, url, surname, prename, email, mailing '.
'FROM users '.
(!empty($values) ? sprintf('WHERE %s ', implode(' AND ', $values)) : null).
sprintf('ORDER BY %s %s ', $sort, $orders[$sort]).
(!empty($limit) ? sprintf('LIMIT %d, %d', $offset, $limit) : null)
);
break;
case 'role':
return $this->db->query(
'SELECT DISTINCT users.id, users.created, users.username, users.url, users.surname, users.prename, users.email, users.mailing '.
'FROM users '.
'LEFT JOIN users_userroles ON users_userroles.user_id = users.id '.
'LEFT JOIN userroles ON userroles.id = users_userroles.user_id '.
(!empty($values) ? sprintf('WHERE %s ', implode(' AND ', $values)) : null).
'ORDER BY userroles.id IS NULL, userroles.id ASC '.
(!empty($limit) ? sprintf('LIMIT %d, %d', $offset, $limit) : null)
);
break;
default:
throw new \nre\exceptions\ParamsNotValidException($sort);
break;
}
}
/**
* Get users with the given user role.
*
* @param string $userrole User role
* @return array List of users
*/
public function getUsersWithRole($userrole)
{
return $this->db->query(
'SELECT users.id, users.created, users.username, users.url, users.surname, users.prename, users.email, users.mailing '.
'FROM users '.
'LEFT JOIN users_userroles ON users_userroles.user_id = users.id '.
'LEFT JOIN userroles ON userroles.id = users_userroles.userrole_id '.
'WHERE userroles.name = ? '.
'ORDER BY username ASC',
's',
$userrole
);
}
/**
* Get a user and its data by its ID.
*
* @throws \nre\exceptions\IdNotFoundException
* @param int $userId ID of an user
* @return array Userdata
*/
public function getUserById($userId)
{
// Get user
$user = $this->db->query(
'SELECT id, created, username, url, surname, prename, email, mailing '.
'FROM users '.
'WHERE id = ?',
'i',
$userId
);
if(empty($user)) {
throw new \nre\exceptions\IdNotFoundException($userId);
}
return $user[0];
}
/**
* Get a user and its data by its URL-username.
*
* @throws \nre\exceptions\IdNotFoundException
* @param string $userUrl URL-Username of an user
* @return array Userdata
*/
public function getUserByUrl($userUrl)
{
// Get user
$user = $this->db->query(
'SELECT id, created, username, url, surname, prename, email, mailing '.
'FROM users '.
'WHERE url = ?',
's',
$userUrl
);
if(empty($user)) {
throw new \nre\exceptions\IdNotFoundException($userUrl);
}
return $user[0];
}
/**
* Log a user in if its credentials are valid.
*
* @throws \nre\exceptions\DatamodelException
* @param string $username The name of the user to log in
* @param string $password Plaintext password of the user to log in
*/
public function login($username, $password)
{
$data = $this->db->query('SELECT id, password FROM users WHERE username = ?', 's', $username);
if(!empty($data))
{
$data = $data[0];
if($this->verify($password, $data['password'])) {
return $data['id'];
}
}
return null;
}
/**
* Check if an username already exists.
*
* @param string $username Username to check
* @param int $userId Do not check this ID (for editing)
* @return boolean Whether username exists or not
*/
public function usernameExists($username, $userId=null)
{
$data = $this->db->query(
'SELECT id '.
'FROM users '.
'WHERE username = ? OR url = ?',
'ss',
$username,
\nre\core\Linker::createLinkParam($username)
);
return (!empty($data) && (is_null($userId) || $userId != $data[0]['id']));
}
/**
* Check if an email address already exists.
*
* @param string $email Email address to check
* @param int $userId Do not check this ID (for editing)
* @return boolean Whether email address exists or not
*/
public function emailExists($email, $userId=null)
{
$data = $this->db->query(
'SELECT id '.
'FROM users '.
'WHERE email = ?',
's',
$email
);
return (!empty($data) && (is_null($userId) || $userId != $data[0]['id']));
}
/**
* Create a new user.
*
* @param string $username Username of the user to create
* @param string $prename Prename of the user to create
* @param string $surname Surname of the user to create
* @param string $email EMail-Address of the user to create
* @param string $password Password of the user to create
* @return int ID of the newly created user
*/
public function createUser($username, $prename, $surname, $email, $password)
{
$userId = null;
$this->db->setAutocommit(false);
try {
// Create user
$this->db->query(
'INSERT INTO users '.
'(username, url, surname, prename, email, password) '.
'VALUES '.
'(?, ?, ?, ?, ?, ?)',
'ssssss',
$username,
\nre\core\Linker::createLinkParam($username),
$surname,
$prename,
$email,
$this->hash($password)
);
$userId = $this->db->getInsertId();
// Add role “user”
$this->db->query(
'INSERT INTO users_userroles '.
'(user_id, userrole_id) '.
'SELECT ?, userroles.id '.
'FROM userroles '.
'WHERE userroles.name = ?',
'is',
$userId,
'user'
);
}
catch(Exception $e) {
$this->db->rollback();
$this->db->setAutocommit(true);
throw $e;
}
$this->db->setAutocommit(true);
return $userId;
}
/**
* Edit a user.
*
* @throws \nre\exceptions\DatamodelException
* @param int $userId ID of the user to delete
* @param string $username New name of user
* @param string $prename Prename of the user to create
* @param string $surname Surname of the user to create
* @param string $email Changed email-address of user
* @param string $password Changed plaintext password of user
* @param bool $mailing Whether to activate mailing or not
*/
public function editUser($userId, $username, $prename, $surname, $email, $password, $mailing)
{
$this->db->setAutocommit(false);
try {
// Update user data
$this->db->query(
'UPDATE users '.
'SET username = ?, url = ?, prename = ?, surname = ?, email = ?, mailing = ? '.
'WHERE id = ?',
'sssssii',
$username,
\nre\core\Linker::createLinkParam($username),
$prename,
$surname,
$email,
$mailing,
$userId
);
// Set new password
if(!empty($password))
{
$this->db->query(
'UPDATE users '.
'SET password = ? '.
'WHERE id = ?',
'si',
$this->hash($password),
$userId
);
}
}
catch(Exception $e) {
$this->db->rollback();
$this->db->setAutocommit(true);
throw $e;
}
$this->db->setAutocommit(true);
}
/**
* Delete a user.
*
* @param int $userId ID of the user to delete
*/
public function deleteUser($userId)
{
$this->db->query('DELETE FROM users WHERE id = ?', 'i', $userId);
}
/**
* Hash a password.
*
* @param string $password Plaintext password
* @return string Hashed password
*/
public function hash($password)
{
if(!function_exists('password_hash')) {
\hhu\z\lib\Password::load();
}
return password_hash($password, PASSWORD_DEFAULT);
}
/**
* Verify a password.
*
* @param string $password Plaintext password to verify
* @param string $hash Hashed password to match with
* @return boolean Verified
*/
private function verify($password, $hash)
{
if(!function_exists('password_verify')) {
\hhu\z\lib\Password::load();
}
return password_verify($password, $hash);
}
}
?>