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(); } } /** * Class ActionsManager * * Opérations CRUD sur la table `actions`. */ class ActionsManager { private PDO $connection; public function __construct(Database $database) { $this->connection = $database->getConnection(); } /** * Retourne toutes les actions. * * @return array */ public function listActions(): array { $statement = $this->connection->query( 'SELECT isin, ticker, yahoo_code, company_name, updated_at FROM actions ORDER BY updated_at DESC' ); return $statement->fetchAll(); } /** * Retourne une action par son ISIN. * * @param string $isin * @return array|null */ public function getActionByIsin(string $isin): ?array { $statement = $this->connection->prepare( 'SELECT isin, ticker, yahoo_code, company_name, updated_at FROM actions WHERE isin = :isin' ); $statement->bindValue(':isin', $isin, PDO::PARAM_STR); $statement->execute(); $result = $statement->fetch(); return $result === false ? null : $result; } /** * Crée une nouvelle action. * * @param array $data * @return bool */ public function createAction(array $data): bool { $statement = $this->connection->prepare( 'INSERT INTO actions (isin, ticker, yahoo_code, company_name, updated_at) VALUES (:isin, :ticker, :yahoo_code, :company_name, NOW())' ); $statement->bindValue(':isin', $data['isin'], PDO::PARAM_STR); $statement->bindValue(':ticker', $data['ticker'], PDO::PARAM_STR); $statement->bindValue(':yahoo_code', $data['yahoo_code'], PDO::PARAM_STR); $statement->bindValue(':company_name', $data['company_name'], PDO::PARAM_STR); return $statement->execute(); } /** * Met à jour une action. * * @param string $isin * @param array $data * @return bool */ public function updateAction(string $isin, array $data): bool { $statement = $this->connection->prepare( 'UPDATE actions SET ticker = :ticker, yahoo_code = :yahoo_code, company_name = :company_name, updated_at = NOW() WHERE isin = :isin' ); $statement->bindValue(':ticker', $data['ticker'], PDO::PARAM_STR); $statement->bindValue(':yahoo_code', $data['yahoo_code'], PDO::PARAM_STR); $statement->bindValue(':company_name', $data['company_name'], PDO::PARAM_STR); $statement->bindValue(':isin', $isin, PDO::PARAM_STR); return $statement->execute(); } }