Add a flash manager but it still doesn't work properly on the twig templates.

This commit is contained in:
Dave Smith-Hayes 2024-12-06 20:24:07 +00:00
parent c19cde193f
commit 5e4a2289a1
9 changed files with 47 additions and 38 deletions

View File

@ -16,6 +16,7 @@ use Monolog\Logger;
use Odan\Session\PhpSession; use Odan\Session\PhpSession;
use Odan\Session\SessionInterface; use Odan\Session\SessionInterface;
use Odan\Session\SessionManagerInterface; use Odan\Session\SessionManagerInterface;
use Odan\Session\FlashInterface;
use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface; use Psr\Container\ContainerInterface;
@ -27,7 +28,6 @@ use Slim\App;
use Slim\Factory\AppFactory; use Slim\Factory\AppFactory;
use Slim\Psr7\Factory\ResponseFactory; use Slim\Psr7\Factory\ResponseFactory;
use Slovocast\Infrastructure\Session\FlashMessages; use Slovocast\Infrastructure\Session\FlashMessages;
use Slovocast\Infrastructure\Session\FlashMessagesInterface;
use Slovocast\Middleware\SessionMiddleware; use Slovocast\Middleware\SessionMiddleware;
use Twig\Error\LoaderError; use Twig\Error\LoaderError;
@ -133,13 +133,13 @@ class Bootstrap
'session' => function (ContainerInterface $container) { 'session' => function (ContainerInterface $container) {
return $container->get(SessionInterface::class); return $container->get(SessionInterface::class);
}, },
FlashMessagesInterface::class => function (ContainerInterface $container) { FlashInterface::class => function (ContainerInterface $container) {
return new FlashMessages( return new FlashMessages(
$container->get(SessionInterface::class) $container->get(SessionInterface::class)
); );
}, },
'flash' => function (ContainerInterface $container) { 'flash' => function (ContainerInterface $container) {
return $container->get(FlashMessagesInterface::class); return $container->get(FlashInterface::class);
}, },
SessionMiddleware::class => function (ContainerInterface $container) { SessionMiddleware::class => function (ContainerInterface $container) {
return new SessionMiddleware( return new SessionMiddleware(

View File

@ -2,6 +2,7 @@
namespace Slovocast\Controller; namespace Slovocast\Controller;
use Odan\Session\SessionInterface;
use Slovocast\Controller\Controller; use Slovocast\Controller\Controller;
use Slovocast\Infrastructure\Api\Database\DatabaseHandlerInterface; use Slovocast\Infrastructure\Api\Database\DatabaseHandlerInterface;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
@ -9,7 +10,8 @@ use Psr\Http\Message\ResponseInterface as Response;
class HealthCheck extends Controller class HealthCheck extends Controller
{ {
public function __construct( public function __construct(
protected DatabaseHandlerInterface $database protected DatabaseHandlerInterface $database,
protected SessionInterface $session
) { } ) { }
public function handle(): Response public function handle(): Response
@ -17,9 +19,16 @@ class HealthCheck extends Controller
$statement = $this->database->getConnection()->query('SELECT 1'); $statement = $this->database->getConnection()->query('SELECT 1');
$results = $statement->fetchAll(); $results = $statement->fetchAll();
if (!$this->session->has("healthcheck")) {
$this->session->set("healthcheck", true);
}
$activeSession = $this->session->get("healthcheck");
return $this->json([ return $this->json([
'http' => true, 'http' => true,
'database' => (bool) count($results), 'database' => (bool) count($results),
'active_session' => $activeSession,
]); ]);
} }
} }

View File

@ -2,6 +2,7 @@
namespace Slovocast\Controller\User; namespace Slovocast\Controller\User;
use Odan\Session\FlashInterface;
use Odan\Session\SessionInterface; use Odan\Session\SessionInterface;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
@ -16,6 +17,7 @@ class LoginUserAction extends Controller
private UserAuthorizationInterface $auth, private UserAuthorizationInterface $auth,
private UserRepositoryInterface $userRepository, private UserRepositoryInterface $userRepository,
private SessionInterface $session, private SessionInterface $session,
private FlashInterface $flash,
private LoggerInterface $logger, private LoggerInterface $logger,
) { } ) { }
@ -27,24 +29,20 @@ class LoginUserAction extends Controller
$user = $this->userRepository->getFromEmail($credentials['email']); $user = $this->userRepository->getFromEmail($credentials['email']);
} catch (EntityNotFoundException $e) { } catch (EntityNotFoundException $e) {
$this->logger->error("Unable to login user."); $this->logger->error("Unable to login user.");
$this->session $this->flash->add('error', "Unable to login user.");
->getFlash()
->add('error', "Unable to login user.");
return $this->render('user/login.twig')->withStatus(400); return $this->render('user/login.twig')->withStatus(400);
} }
if (!$this->auth->verify($credentials['password'], $user->getPassword())) { if (!$this->auth->verify($credentials['password'], $user->getPassword())) {
$this->logger->error("Unable to verify user password."); $this->logger->error("Unable to verify user password.");
$this->session $this->flash->add('error', "Unable to login user.");
->getFlash()
->add('error', "Unable to login user.");
return $this->render('user/login.twig')->withStatus(400); return $this->render('user/login.twig')->withStatus(400);
} }
// start the session // start the session
$this->session->getFlash()->add('success', "Successfully logged in."); $this->flash->add('success', "Successfully logged in.");
$this->session->set('authenticated', true); $this->session->set('authenticated', true);
$this->session->set('user', $user->toArray()); $this->session->set('user', $user->toArray());
return $this->redirect('/dashboard', 302); return $this->redirect('/dashboard', 302);

View File

@ -2,6 +2,7 @@
namespace Slovocast\Controller\User; namespace Slovocast\Controller\User;
use Odan\Session\FlashInterface;
use Slovocast\Controller\Controller; use Slovocast\Controller\Controller;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Odan\Session\SessionInterface; use Odan\Session\SessionInterface;
@ -9,7 +10,8 @@ use Odan\Session\SessionInterface;
class LogoutUserAction extends Controller class LogoutUserAction extends Controller
{ {
public function __construct( public function __construct(
protected SessionInterface $session protected SessionInterface $session,
protected FlashInterface $flash
) { } ) { }
@ -23,7 +25,7 @@ class LogoutUserAction extends Controller
$this->session->delete('user'); $this->session->delete('user');
} }
$this->session->getFlash()->add('notice', "Successfully logged out."); $this->flash->add('notice', "Successfully logged out.");
return $this->redirect('/', 302); return $this->redirect('/', 302);
} }
} }

View File

@ -29,9 +29,7 @@ class RegisterUserAction extends Controller
if ($success) { if ($success) {
return $this->render('user/success.twig'); return $this->render('user/success.twig');
} else { } else {
$this->session $this->flash->add('error', "Unable to register user.");
->getFlash()
->add('error', "Unable to register user.");
return $this->render('user/register.twig')->withStatus(400); return $this->render('user/register.twig')->withStatus(400);
} }
} }

View File

@ -25,7 +25,7 @@ interface FlashMessagesInterface
/** /**
* @return array<string, array<string>> * @return array<string, array<string>>
*/ */
public function getAll(): array; public function all(): array;
/** /**
* @param string|null * @param string|null

View File

@ -3,8 +3,9 @@
namespace Slovocast\Infrastructure\Session; namespace Slovocast\Infrastructure\Session;
use Odan\Session\SessionInterface; use Odan\Session\SessionInterface;
use Odan\Session\FlashInterface;
class FlashMessages implements FlashMessagesInterface class FlashMessages implements FlashInterface
{ {
const LEVEL_ERROR = "error"; const LEVEL_ERROR = "error";
const LEVEL_NOTICE = "notice"; const LEVEL_NOTICE = "notice";
@ -15,9 +16,7 @@ class FlashMessages implements FlashMessagesInterface
public function __construct( public function __construct(
protected SessionInterface $session protected SessionInterface $session
) { ) {
if (!$this->session->has($this->key)) { $this->session->set($this->key, []);
$this->session->set($this->key, []);
}
} }
/** /**
@ -37,10 +36,22 @@ class FlashMessages implements FlashMessagesInterface
$this->session->set($this->key, $messages); $this->session->set($this->key, $messages);
} }
public function add(string $level, string $message): void public function has(string $key): bool
{
return array_key_exists($key, $this->getMessages());
}
public function set(string $key, array $messages): void
{ {
$messages = $this->getMessages(); $messages = $this->getMessages();
$messages[$level][] = $message; $messages[$key] = $messages;
$this->saveMessages($messages);
}
public function add(string $key, string $message): void
{
$messages = $this->getMessages();
$messages[$key][] = $message;
$this->saveMessages($messages); $this->saveMessages($messages);
} }
@ -58,25 +69,15 @@ class FlashMessages implements FlashMessagesInterface
return $buffer; return $buffer;
} }
public function getAll(): array public function all(): array
{ {
$messages = $this->getMessages(); $messages = $this->getMessages();
$this->clear(); $this->clear();
return $messages; return $messages;
} }
public function clear(?string $level = null): void public function clear(): void
{ {
if (!$level) { $this->session->set($this->key, []);
$this->session->set($this->key, []);
} else {
$messages = $this->getMessages();
if (array_key_exists($level)) {
unset($messages[$level]);
}
$this->saveMessages($messages);
}
} }
} }

View File

@ -3,6 +3,7 @@
namespace Slovocast; namespace Slovocast;
use League\Config\Configuration; use League\Config\Configuration;
use Odan\Session\FlashInterface;
use Odan\Session\SessionInterface; use Odan\Session\SessionInterface;
use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface; use Psr\Container\ContainerInterface;
@ -10,7 +11,6 @@ use Psr\Container\NotFoundExceptionInterface;
use Slim\App; use Slim\App;
use Slim\Views\Twig; use Slim\Views\Twig;
use Slim\Views\TwigMiddleware; use Slim\Views\TwigMiddleware;
use Slovocast\Infrastructure\Session\FlashMessagesInterface;
use Slovocast\Middleware\SessionMiddleware; use Slovocast\Middleware\SessionMiddleware;
use Twig\Error\LoaderError; use Twig\Error\LoaderError;
@ -48,7 +48,7 @@ class Middlewares
$twig->getEnvironment()->addGlobal('site_description', $config->get('site.description')); $twig->getEnvironment()->addGlobal('site_description', $config->get('site.description'));
$session = $container->get(SessionInterface::class); $session = $container->get(SessionInterface::class);
$flash = $container->get(FlashMessagesInterface::class); $flash = $container->get(FlashInterface::class);
$twig->getEnvironment()->addGlobal('session', $session); $twig->getEnvironment()->addGlobal('session', $session);
$twig->getEnvironment()->addGlobal('flash', $flash); $twig->getEnvironment()->addGlobal('flash', $flash);

View File

@ -14,6 +14,7 @@
<label for="description">Description<br> <label for="description">Description<br>
<textarea name="description"></textarea> <textarea name="description"></textarea>
</div> </div>
<div> <div>
<button type="submit">Create</button> <button type="submit">Create</button>
</div> </div>