Colin FRIZOT 2 years ago
commit 7e732bfb71

@ -16,4 +16,5 @@ $router->get('/^recent\/(?<page>\d+)$/', [$user, 'index']);
$router->get('/^news\/(?<id>\d+)$/', [$user, 'viewPost']); $router->get('/^news\/(?<id>\d+)$/', [$user, 'viewPost']);
$router->get('/^comments\/(?<id>[\w-]+)$/', [$user, 'viewPostComments']); $router->get('/^comments\/(?<id>[\w-]+)$/', [$user, 'viewPostComments']);
$router->match('/^login$/', [$security, 'login']); $router->match('/^login$/', [$security, 'login']);
$router->run(new \Silex\DI\DI($router))->render(__DIR__ . '/../' . VIEW_PATH); $router->match('/^register$/', [$security, 'register']);
$router->run(new \Silex\DI\DI($router))->render($router, __DIR__ . '/../' . VIEW_PATH);

@ -6,6 +6,7 @@ namespace Silex\Controller;
use Silex\DI\DI; use Silex\DI\DI;
use Silex\Http\HttpResponse; use Silex\Http\HttpResponse;
use Silex\Model\User;
class SecurityController class SecurityController
{ {
@ -19,9 +20,23 @@ class SecurityController
header('Location: ' . $di->getRouter()->url('')); header('Location: ' . $di->getRouter()->url(''));
exit(); exit();
} }
var_dump($success);
$fail = !$success; $fail = !$success;
} }
return HttpResponse::found('login', ['fail' => $fail]); return HttpResponse::found('login', ['fail' => $fail]);
} }
public function register(DI $di): HttpResponse
{
$fail = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$user = $di->getSecurity()->register(User::fromRawPassword($_POST['login'], $_POST['password']));
if ($user !== null) {
http_response_code(303);
header('Location: ' . $di->getRouter()->url(''));
exit();
}
$fail = $user === null;
}
return HttpResponse::found('register', ['fail' => $fail]);
}
} }

@ -28,7 +28,7 @@ class UserController
} else { } else {
$nbCommentsByUser = 0; $nbCommentsByUser = 0;
} }
return new HttpResponse(200, 'home', ['news' => $news, 'page' => $page, 'nbPages' => $nbPages, 'router' => $di->getRouter(), 'nbComments' => $nbComments, 'nbCommentsByUser' => $nbCommentsByUser]); return new HttpResponse(200, 'home', ['news' => $news, 'page' => $page, 'nbPages' => $nbPages, 'nbComments' => $nbComments, 'nbCommentsByUser' => $nbCommentsByUser]);
} }
public function viewPost(DI $di, array $params): HttpResponse public function viewPost(DI $di, array $params): HttpResponse

@ -24,7 +24,7 @@ class NewsGateway
*/ */
public function getPaginatedRecentNews(int $page = 1, int $limit = 10): array public function getPaginatedRecentNews(int $page = 1, int $limit = 10): array
{ {
$req = $this->pdo->prepare('SELECT title, LEFT(content, ' . self::EXCERPT_LENGTH . ') content, publication_date FROM news ORDER BY publication_date DESC LIMIT :limit OFFSET :offset;'); $req = $this->pdo->prepare('SELECT id_news, title, LEFT(content, ' . self::EXCERPT_LENGTH . ') content, publication_date FROM news ORDER BY publication_date DESC LIMIT :limit OFFSET :offset;');
$req->bindValue('limit', $limit, PDO::PARAM_INT); $req->bindValue('limit', $limit, PDO::PARAM_INT);
$req->bindValue('offset', ($page - 1) * $limit, PDO::PARAM_INT); $req->bindValue('offset', ($page - 1) * $limit, PDO::PARAM_INT);
if (!$req->execute()) { if (!$req->execute()) {
@ -61,6 +61,6 @@ class NewsGateway
private function createNews(array $data): News private function createNews(array $data): News
{ {
return new News($data['title'], $data['content'], DateTime::createFromFormat('Y-m-d H:i:s', $data['publication_date'])); return new News(intval($data['id_news']), $data['title'], $data['content'], DateTime::createFromFormat('Y-m-d H:i:s', $data['publication_date']));
} }
} }

@ -33,4 +33,12 @@ class UserGateway
$user = $req->fetch(); $user = $req->fetch();
return $user === false ? null : $user; return $user === false ? null : $user;
} }
public function insert(User $user): bool
{
$req = $this->pdo->prepare('INSERT INTO registered_user (login, password, role) VALUES (:login, :password, :role);');
$req->execute(['login' => $user->getLogin(), 'password' => $user->getPasswordHash(), 'role' => $user->getRole()]);
$user->setId(intval($this->pdo->lastInsertId()));
return true;
}
} }

@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Silex\Http; namespace Silex\Http;
use Silex\Router\Router;
class HttpResponse class HttpResponse
{ {
private int $status; private int $status;
@ -24,7 +26,7 @@ class HttpResponse
return new HttpResponse(200, $viewPath, $viewParams); return new HttpResponse(200, $viewPath, $viewParams);
} }
public function render(string $viewBasePath) public function render(Router $router, string $viewBasePath)
{ {
$params = $this->viewParams; $params = $this->viewParams;
ob_start(); ob_start();

@ -8,17 +8,24 @@ use DateTime;
class News class News
{ {
private int $id;
private string $title; private string $title;
private string $content; private string $content;
private DateTime $publicationDate; private DateTime $publicationDate;
public function __construct(string $title, string $content, DateTime $publicationDate) public function __construct(int $id, string $title, string $content, DateTime $publicationDate)
{ {
$this->id = $id;
$this->title = $title; $this->title = $title;
$this->content = $content; $this->content = $content;
$this->publicationDate = $publicationDate; $this->publicationDate = $publicationDate;
} }
public function getId(): int
{
return $this->id;
}
public function getTitle(): string public function getTitle(): string
{ {
return $this->title; return $this->title;

@ -11,11 +11,12 @@ class User
private string $password; private string $password;
private int $role; private int $role;
public static function fromRawPassword(string $login, string $password): User public static function fromRawPassword(string $login, string $password, int $role = 0): User
{ {
$user = new User(); $user = new User();
$user->login = $login; $user->login = $login;
$user->password = password_hash($password, PASSWORD_DEFAULT); $user->password = password_hash($password, PASSWORD_DEFAULT);
$user->role = $role;
return $user; return $user;
} }
@ -38,4 +39,9 @@ class User
{ {
return $this->role; return $this->role;
} }
public function setId(int $id)
{
$this->id_user = $id;
}
} }

@ -56,9 +56,14 @@ class Router
public function url(string $url): string public function url(string $url): string
{ {
if ($this->basePath !== '') {
return "/" . $this->basePath . '/' . $url;
} else {
return $this->basePath . '/' . $url; return $this->basePath . '/' . $url;
} }
}
public function run(DI $di): HttpResponse public function run(DI $di): HttpResponse
{ {
if (!isset($this->routes[$_SERVER['REQUEST_METHOD']])) { if (!isset($this->routes[$_SERVER['REQUEST_METHOD']])) {

@ -45,4 +45,14 @@ class Security
} }
return $this->user; return $this->user;
} }
public function register(User $user): ?User
{
if (!$this->userGateway->insert($user)) {
return null;
}
$this->session[USER] = $user->getId();
$this->user = $user;
return $user;
}
} }

@ -7,6 +7,7 @@
</div> </div>
<h1>Hello world!</h1> <h1>Hello world!</h1>
<?php foreach ($params['news'] as $news) : ?> <?php foreach ($params['news'] as $news) : ?>
<a href="<?= $router->url('news/' . $news->getId()) ?>">
<div class="card"> <div class="card">
<header class="card-header"> <header class="card-header">
<p class="card-header-title"> <p class="card-header-title">
@ -19,18 +20,19 @@
</div> </div>
</div> </div>
</div> </div>
</a>
<?php endforeach ?> <?php endforeach ?>
<nav class="pagination" role="navigation" aria-label="pagination"> <nav class="pagination" role="navigation" aria-label="pagination">
<?php if ($params['page'] > 1) : ?> <?php if ($params['page'] > 1) : ?>
<a class="pagination-previous" href="<?= $params['router']->url('recent/' . ($params['page'] - 1)) ?>">Previous</a> <a class="pagination-previous" href="<?= $router->url('recent/' . ($params['page'] - 1)) ?>">Previous</a>
<?php endif; ?> <?php endif; ?>
<?php if ($params['page'] < $params['nbPages']) : ?> <?php if ($params['page'] < $params['nbPages']) : ?>
<a class="pagination-next" href="<?= $params['router']->url('recent/' . ($params['page'] + 1)) ?>">Next page</a> <a class="pagination-next" href="<?= $router->url('recent/' . ($params['page'] + 1)) ?>">Next page</a>
<?php endif; ?> <?php endif; ?>
<ul class="pagination-list"> <ul class="pagination-list">
<?php if ($params['page'] > 2) : ?> <?php if ($params['page'] > 2) : ?>
<li> <li>
<a class="pagination-link" aria-label="Goto page 1" href="<?= $params['router']->url('recent/1') ?>">1</a> <a class="pagination-link" aria-label="Goto page 1" href="<?= $router->url('recent/1') ?>">1</a>
</li> </li>
<?php if ($params['page'] > 3) : ?> <?php if ($params['page'] > 3) : ?>
<li> <li>
@ -40,7 +42,7 @@
<?php endif; ?> <?php endif; ?>
<?php if ($params['page'] > 1) : ?> <?php if ($params['page'] > 1) : ?>
<li> <li>
<a class="pagination-link" aria-label="Goto page <?= $params['page'] - 1 ?>" href="<?= $params['router']->url('recent/' . ($params['page'] - 1)) ?>"><?= $params['page'] - 1 ?></a> <a class="pagination-link" aria-label="Goto page <?= $params['page'] - 1 ?>" href="<?= $router->url('recent/' . ($params['page'] - 1)) ?>"><?= $params['page'] - 1 ?></a>
</li> </li>
<?php endif; ?> <?php endif; ?>
<li> <li>
@ -48,7 +50,7 @@
</li> </li>
<?php if ($params['page'] < ($params['nbPages'] - 1)) : ?> <?php if ($params['page'] < ($params['nbPages'] - 1)) : ?>
<li> <li>
<a class="pagination-link" aria-label="Goto page <?= $params['page'] + 1 ?>" href="<?= $params['router']->url('recent/' . ($params['page'] + 1)) ?>"><?= $params['page'] + 1 ?></a> <a class="pagination-link" aria-label="Goto page <?= $params['page'] + 1 ?>" href="<?= $router->url('recent/' . ($params['page'] + 1)) ?>"><?= $params['page'] + 1 ?></a>
</li> </li>
<?php if ($params['page'] < ($params['nbPages'] - 2)) : ?> <?php if ($params['page'] < ($params['nbPages'] - 2)) : ?>
<li> <li>
@ -58,7 +60,7 @@
<?php endif; ?> <?php endif; ?>
<?php if ($params['page'] < $params['nbPages']) : ?> <?php if ($params['page'] < $params['nbPages']) : ?>
<li> <li>
<a class="pagination-link" aria-label="Goto page <?= $params['nbPages'] ?>" href="<?= $params['router']->url('recent/' . $params['nbPages']) ?>"><?= $params['nbPages'] ?></a> <a class="pagination-link" aria-label="Goto page <?= $params['nbPages'] ?>" href="<?= $router->url('recent/' . $params['nbPages']) ?>"><?= $params['nbPages'] ?></a>
</li> </li>
<?php endif; ?> <?php endif; ?>
</ul> </ul>

@ -7,10 +7,29 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
</head> </head>
<body> <body>
<section class="section"> <nav class="navbar" role="navigation" aria-label="main navigation">
<div id="navbarBasicExample" class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item">Home</a>
</div>
<div class="navbar-end">
<div class="navbar-item">
<div class="buttons">
<a class="button is-primary" href="<?= $router->url('register') ?>">
<strong>Sign up</strong>
</a>
<a class="button is-light" href="<?= $router->url('login') ?>">Log in</a>
</div>
</div>
</div>
</div>
</nav>
<section class="section">
<div class="container"> <div class="container">
<?= $content ?> <?= $content ?>
</div> </div>
</section> </section>
</body> </body>
</html> </html>

@ -12,13 +12,13 @@
<div class="field"> <div class="field">
<label class="label" for="login">Login</label> <label class="label" for="login">Login</label>
<div class="control"> <div class="control">
<input class="input" type="text" id="login" name="login"> <input class="input" type="text" id="login" name="login" autocomplete="username">
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label class="label" for="password">Password</label> <label class="label" for="password">Password</label>
<div class="control"> <div class="control">
<input class="input" type="password" id="password" name="password"> <input class="input" type="password" id="password" name="password" autocomplete="current-password">
</div> </div>
</div> </div>

@ -0,0 +1,36 @@
<?php if ($params['fail']) : ?>
<article class="message is-danger">
<div class="message-header">
<p>Registration failed</p>
</div>
<div class="message-body">
Login is already taken.
</div>
</article>
<?php endif ?>
<form action="<?= $_SERVER['REQUEST_URI'] ?>" method="post">
<div class="field">
<label class="label" for="login">Login</label>
<div class="control">
<input class="input" type="text" id="login" name="login" autocomplete="username">
</div>
</div>
<div class="field">
<label class="label" for="password">Password</label>
<div class="control">
<input class="input" type="password" id="password" name="password" autocomplete="new-password">
</div>
</div>
<div class="field">
<label class="label" for="password-confirmation">Password confirmation</label>
<div class="control">
<input class="input" type="password" id="password-confirmation" name="password-confirmation" autocomplete="new-password">
</div>
</div>
<div class="field">
<div class="control">
<button class="button is-link">Submit</button>
</div>
</div>
</form>
Loading…
Cancel
Save