Files
bolsa/php/db.php
T

367 lines
9.6 KiB
PHP

<?php
namespace App\Database;
use PDO;
use PDOException;
use RuntimeException;
/**
* Class Database
*
* Gère la connexion PDO à la base de données MySQL.
*/
class Database
{
private PDO $connection;
public const DB_HOST = '127.0.0.1';
public const DB_NAME = 'bolsa';
public const DB_USER = 'root';
public const DB_PASS = 'sysadm-1963';
public const DB_CHARSET = 'utf8mb4';
/**
* Database constructor.
*
* Initialise la connexion PDO.
*
* @throws RuntimeException
*/
public function __construct()
{
$dsn = sprintf(
'mysql:host=%s;dbname=%s;charset=%s',
self::DB_HOST,
self::DB_NAME,
self::DB_CHARSET
);
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$this->connection = new PDO($dsn, self::DB_USER, self::DB_PASS, $options);
} catch (PDOException $exception) {
throw new RuntimeException('Connexion à la base de données impossible : ' . $exception->getMessage());
}
}
/**
* Retourne l'objet PDO.
*
* @return PDO
*/
public function getConnection(): PDO
{
return $this->connection;
}
/**
* Ferme la connexion PDO.
*
* @return void
*/
public function disconnect(): void
{
$this->connection = null;
}
}
/**
* Class LoginManager
*
* Fournit les opérations CRUD pour la table `login`.
*/
class LoginManager
{
private PDO $connection;
public function __construct(Database $database)
{
$this->connection = $database->getConnection();
}
/**
* Crée un nouvel utilisateur dans la table login.
*
* @param array $data
* @return int L'ID généré de l'utilisateur.
*/
public function create(array $data): int
{
$statement = $this->connection->prepare(
'INSERT INTO login (login, nom, prenom, mail, pass, actif, creer_le, modifie_le)
VALUES (:login, :nom, :prenom, :mail, :pass, :actif, NOW(), NOW())'
);
$hashedPassword = password_hash($data['pass'], PASSWORD_DEFAULT);
$actif = array_key_exists('actif', $data) ? (int) $data['actif'] : 0;
$statement->bindValue(':login', $data['login'], PDO::PARAM_STR);
$statement->bindValue(':nom', $data['nom'], PDO::PARAM_STR);
$statement->bindValue(':prenom', $data['prenom'], PDO::PARAM_STR);
$statement->bindValue(':mail', $data['mail'], PDO::PARAM_STR);
$statement->bindValue(':pass', $hashedPassword, PDO::PARAM_STR);
$statement->bindValue(':actif', $actif, PDO::PARAM_INT);
$statement->execute();
return (int) $this->connection->lastInsertId();
}
/**
* Lit un utilisateur par son ID.
*
* @param int $id
* @return array|null
*/
public function read(int $id): ?array
{
$statement = $this->connection->prepare(
'SELECT id, login, nom, prenom, mail, creer_le, modifie_le
FROM login
WHERE id = :id'
);
$statement->bindValue(':id', $id, PDO::PARAM_INT);
$statement->execute();
$result = $statement->fetch();
return $result === false ? null : $result;
}
/**
* Met à jour un utilisateur.
*
* @param int $id
* @param array $data
* @return bool
*/
public function update(int $id, array $data): bool
{
$fields = [];
$params = [':id' => $id];
if (isset($data['login'])) {
$fields[] = 'login = :login';
$params[':login'] = $data['login'];
}
if (isset($data['nom'])) {
$fields[] = 'nom = :nom';
$params[':nom'] = $data['nom'];
}
if (isset($data['prenom'])) {
$fields[] = 'prenom = :prenom';
$params[':prenom'] = $data['prenom'];
}
if (isset($data['mail'])) {
$fields[] = 'mail = :mail';
$params[':mail'] = $data['mail'];
}
if (isset($data['pass'])) {
$fields[] = 'pass = :pass';
$params[':pass'] = password_hash($data['pass'], PASSWORD_DEFAULT);
}
if (empty($fields)) {
return false;
}
$fields[] = 'modifie_le = NOW()';
$statement = $this->connection->prepare(
sprintf('UPDATE login SET %s WHERE id = :id', implode(', ', $fields))
);
foreach ($params as $param => $value) {
$statement->bindValue($param, $value, is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR);
}
return $statement->execute();
}
/**
* Supprime un utilisateur par son ID.
*
* @param int $id
* @return bool
*/
public function delete(int $id): bool
{
$statement = $this->connection->prepare('DELETE FROM login WHERE id = :id');
$statement->bindValue(':id', $id, PDO::PARAM_INT);
return $statement->execute();
}
/**
* Retourne tous les utilisateurs.
*
* @return array
*/
public function list(): array
{
$statement = $this->connection->query(
'SELECT id, login, nom, prenom, mail, creer_le, modifie_le FROM login ORDER BY id ASC'
);
return $statement->fetchAll();
}
/**
* Retourne un utilisateur par son login.
*
* @param string $login
* @return array|null
*/
public function getByLogin(string $login): ?array
{
$statement = $this->connection->prepare(
'SELECT id, login, nom, prenom, mail, pass, actif, creer_le, modifie_le
FROM login
WHERE login = :login'
);
$statement->bindValue(':login', $login, PDO::PARAM_STR);
$statement->execute();
$result = $statement->fetch();
return $result === false ? null : $result;
}
/**
* Vérifie si le mot de passe correspond au login.
*
* @param string $login
* @param string $password
* @return bool
*/
public function verifyPasswordByLogin(string $login, string $password): bool
{
$user = $this->getByLogin($login);
if ($user === null) {
return false;
}
return ((int) ($user['actif'] ?? 0) === 1) && password_verify($password, $user['pass']);
}
/**
* Vérifie si un login ou un email existe déjà.
*
* @param string $login
* @param string $email
* @return bool
*/
public function existsByLoginOrEmail(string $login, string $email): bool
{
$statement = $this->connection->prepare(
'SELECT COUNT(*) AS total
FROM login
WHERE login = :login OR mail = :mail'
);
$statement->bindValue(':login', $login, PDO::PARAM_STR);
$statement->bindValue(':mail', $email, PDO::PARAM_STR);
$statement->execute();
$result = $statement->fetch();
return isset($result['total']) && (int) $result['total'] > 0;
}
/**
* Vérifie si une adresse e-mail existe.
*
* @param string $email
* @return bool
*/
public function existsByEmail(string $email): bool
{
$statement = $this->connection->prepare(
'SELECT COUNT(*) AS total FROM login WHERE mail = :mail'
);
$statement->bindValue(':mail', $email, PDO::PARAM_STR);
$statement->execute();
$result = $statement->fetch();
return isset($result['total']) && (int) $result['total'] > 0;
}
/**
* Définit un token de réinitialisation pour un utilisateur identifié par son e-mail.
*
* @param string $email
* @param string $token
* @return bool
*/
public function setResetTokenByEmail(string $email, string $token): bool
{
$statement = $this->connection->prepare(
'UPDATE login SET reset_token = :token, reset_token_created_at = NOW(), modifie_le = NOW() WHERE mail = :mail'
);
$statement->bindValue(':token', $token, PDO::PARAM_STR);
$statement->bindValue(':mail', $email, PDO::PARAM_STR);
return $statement->execute();
}
/**
* Retourne un utilisateur identifié par son token de réinitialisation.
*
* @param string $token
* @return array|null
*/
public function getByResetToken(string $token): ?array
{
$statement = $this->connection->prepare(
'SELECT id, login, nom, prenom, mail, pass, actif, reset_token, reset_token_created_at, creer_le, modifie_le
FROM login
WHERE reset_token = :token
AND reset_token_created_at >= NOW() - INTERVAL 30 MINUTE'
);
$statement->bindValue(':token', $token, PDO::PARAM_STR);
$statement->execute();
$result = $statement->fetch();
return $result === false ? null : $result;
}
/**
* Met à jour le mot de passe d'un utilisateur et supprime le token de réinitialisation.
*
* @param int $id
* @param string $password
* @return bool
*/
public function updatePasswordById(int $id, string $password): bool
{
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
$statement = $this->connection->prepare(
'UPDATE login SET pass = :pass, reset_token = NULL, reset_token_created_at = NULL, modifie_le = NOW() WHERE id = :id'
);
$statement->bindValue(':pass', $hashedPassword, PDO::PARAM_STR);
$statement->bindValue(':id', $id, PDO::PARAM_INT);
return $statement->execute();
}
}