Created
July 6, 2022 12:51
-
-
Save settermjd/ed1c3d0325cfc08704b4e5428fafff9a to your computer and use it in GitHub Desktop.
Laminas Article Code Listings
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace User\Entity; | |
class User | |
{ | |
private readonly int $id; | |
private readonly string $emailAddress; | |
private readonly string $firstName; | |
private readonly string $lastName; | |
private readonly string $password; | |
private readonly ?string $resetPasswordId; | |
public function __get(string $property) | |
{ | |
return match($property) { | |
'id', 'emailAddress', 'firstName', 'lastName', 'password', 'resetPasswordId' => $this->$property, | |
'fullName' => sprintf( | |
"%s %s", | |
$this->firstName, | |
$this->lastName | |
) | |
}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace User\Handler; | |
use Laminas\Diactoros\Response\RedirectResponse; | |
use Mezzio\Session\SessionInterface; | |
use Mezzio\Session\SessionMiddleware; | |
use Psr\Http\Message\ResponseInterface; | |
use Psr\Http\Message\ServerRequestInterface; | |
use Psr\Http\Server\RequestHandlerInterface; | |
class LogoutHandler implements RequestHandlerInterface | |
{ | |
public function handle(ServerRequestInterface $request) : ResponseInterface | |
{ | |
/** @var ?SessionInterface $session */ | |
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE); | |
$session->clear(); | |
$session->regenerate(); | |
return new RedirectResponse('/login'); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** @var SessionInterface $session */ | |
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE); | |
$this->templateRenderer->addDefaultParam( | |
TemplateRendererInterface::TEMPLATE_ALL, | |
'authUser', | |
$session->get(UserInterface::class) | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php if ($this->authUser !== null): ?> | |
<a href="/logout">Logout</a> | |
<?php endif ?> | |
<?php if ($this->authUser === null && $this->matchedRouteName !== 'user.login'): ?> | |
<a href="/login">Login</a> | |
<?php endif ?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace User\Handler; | |
use User\Database\UsersTableGateway; | |
use Laminas\Diactoros\Response\RedirectResponse; | |
use Laminas\Filter\{StringTrim,StripNewlines,StripTags}; | |
use Laminas\InputFilter\{Input,InputFilter}; | |
use Laminas\Validator\EmailAddress; | |
use Mezzio\Flash\{FlashMessageMiddleware,FlashMessagesInterface}; | |
use Mezzio\Session\{SessionInterface,SessionMiddleware}; | |
use Psr\Http\Message\{ResponseInterface,ServerRequestInterface}; | |
use Psr\Http\Server\RequestHandlerInterface; | |
use Laminas\Diactoros\Response\HtmlResponse; | |
use Mezzio\Template\TemplateRendererInterface; | |
class RegistrationHandler implements RequestHandlerInterface | |
{ | |
private InputFilter $inputFilter; | |
public function __construct( | |
private readonly TemplateRendererInterface $renderer, | |
private readonly UsersTableGateway $userService | |
){ | |
$emailInput = new Input('email_address'); | |
$emailInput | |
->getValidatorChain() | |
->attach(new EmailAddress()); | |
$emailInput | |
->getFilterChain() | |
->attach(new StripTags()) | |
->attach(new StripNewlines()) | |
->attach(new StringTrim()); | |
$passwordInput = new Input('password'); | |
$firstNameInput = new Input('first_name'); | |
$lastNameInput = new Input('last_name'); | |
$this->inputFilter = new InputFilter(); | |
$this->inputFilter | |
->add($emailInput) | |
->add($passwordInput) | |
->add($firstNameInput) | |
->add($lastNameInput); | |
} | |
public function handle(ServerRequestInterface $request) : ResponseInterface | |
{ | |
if (strtoupper($request->getMethod()) === 'GET') { | |
return new HtmlResponse($this->renderer->render('user::registration')); | |
} | |
/** @var ?FlashMessagesInterface $flashMessages */ | |
$flashMessages = $request->getAttribute(FlashMessageMiddleware::FLASH_ATTRIBUTE); | |
$this->inputFilter->setData($request->getParsedBody()); | |
if (! $this->inputFilter->isValid()) { | |
$flashMessages->flash( | |
"message", | |
"One or more of the fields is invalid", | |
); | |
return new RedirectResponse('/register'); | |
} | |
$result = $this->userService->createUser($this->inputFilter->getValues()); | |
if ($result) { | |
$user = $this->userService->findByEmail($this->inputFilter->getValue('email_address')); | |
/** @var ?SessionInterface $session */ | |
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE); | |
$session->set('user_id', $user->id); | |
} | |
return new RedirectResponse('/login'); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public function createUser(array $userData): bool | |
{ | |
return (bool)$this->insert( | |
[ | |
'email_address' => $userData['email_address'], | |
'password' => $this->getPasswordHash($userData['password']), | |
'first_name' => $userData['first_name'], | |
'last_name' => $userData['last_name'], | |
] | |
); | |
} | |
public function getPasswordHash(string $password): string | |
{ | |
return password_hash( | |
$password, | |
PASSWORD_DEFAULT, | |
$options = [ | |
'cost' => 14, | |
] | |
); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php $this->headTitle('Register'); ?> | |
<div class="mb-4 p-2 w-auto"> | |
<h1 class="text-center"><a href="/">Register for an account</a></h1> | |
<div class="grid gap-4 mt-8 border-2 bg-white border-slate-200 p-8 rounded-lg w-7/12 mx-auto"> | |
<div class="py-2 px-4"> | |
<form id="register" | |
class="grid grid-cols-1 gap-2" | |
method="post" | |
action="/register"> | |
<div class="w-full mb-4"> | |
<label>Email Address:</label> | |
<input type="text" | |
name="email_address"> | |
</div> | |
<div class="w-full mb-4"> | |
<label>Password:</label> | |
<input type="password" | |
name="password"> | |
</div> | |
<div class="w-full mb-4"> | |
<label>First name:</label> | |
<input type="text" | |
name="first_name"> | |
</div> | |
<div class="w-full mb-4"> | |
<label>Last Name:</label> | |
<input type="text" | |
name="last_name"> | |
</div> | |
<div class="w-full"> | |
<input type="submit" | |
class="submit cursor-pointer" | |
name="submit" | |
value="Register"> | |
</div> | |
</form> | |
</div> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public function sendAccountCreatedEmail(string $toAddress, string $toName, string $baseUrl) | |
{ | |
$body =<<<EOF | |
Your account has been created with the username: %s. | |
You can login here: %s. | |
Your awesome support team. | |
EOF; | |
$this->mail | |
->setBody(sprintf($body, $baseUrl)) | |
->addTo($toAddress, $toName) | |
->setSubject("Your password has been created"); | |
$this->transport->send($this->mail); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace User\Handler; | |
use User\Database\UsersTableGateway; | |
use App\Service\Email\UserNotificationService; | |
use Laminas\Diactoros\Response\RedirectResponse; | |
use Laminas\Filter\StringTrim; | |
use Laminas\Filter\StripNewlines; | |
use Laminas\Filter\StripTags; | |
use Laminas\InputFilter\Input; | |
use Laminas\InputFilter\InputFilter; | |
use Laminas\Validator\EmailAddress; | |
use Mezzio\Flash\FlashMessageMiddleware; | |
use Mezzio\Flash\FlashMessagesInterface; | |
use Mezzio\Helper\ServerUrlHelper; | |
use Mezzio\Router\RouterInterface; | |
use Psr\Http\Message\ResponseInterface; | |
use Psr\Http\Message\ServerRequestInterface; | |
use Psr\Http\Server\RequestHandlerInterface; | |
use Laminas\Diactoros\Response\HtmlResponse; | |
use Mezzio\Template\TemplateRendererInterface; | |
use Ramsey\Uuid\Uuid; | |
class ForgotPasswordHandler implements RequestHandlerInterface | |
{ | |
private InputFilter $inputFilter; | |
public function __construct( | |
private readonly TemplateRendererInterface $renderer, | |
private readonly UsersTableGateway $userService, | |
private readonly UserNotificationService $userNotificationService | |
){ | |
$emailInput = new Input('email_address'); | |
$emailInput | |
->getValidatorChain() | |
->attach(new EmailAddress()); | |
$emailInput | |
->getFilterChain() | |
->attach(new StripTags()) | |
->attach(new StripNewlines()) | |
->attach(new StringTrim()); | |
$this->inputFilter = new InputFilter(); | |
$this->inputFilter->add($emailInput); | |
} | |
public function handle(ServerRequestInterface $request) : ResponseInterface | |
{ | |
$data = []; | |
/** @var ?FlashMessagesInterface $flashMessages */ | |
$flashMessages = $request->getAttribute(FlashMessageMiddleware::FLASH_ATTRIBUTE); | |
if (strtoupper($request->getMethod()) === 'POST') { | |
$formData = $request->getParsedBody(); | |
$this->inputFilter->setData($formData); | |
if (! $this->inputFilter->isValid()) { | |
$flashMessages->flash( | |
"message", | |
"Email address was invalid" | |
); | |
return new RedirectResponse($this->generateUri($request, 'user.forgot-password')); | |
} | |
$user = $this->userService->findByEmail($formData['email_address']); | |
if ($user !== null) { | |
$uuid = Uuid::uuid4(); | |
$this->userService->addForgotPasswordFlag($user->getEmailAddress(), $uuid->toString()); | |
$this->userNotificationService->sendResetPasswordEmail( | |
$user, | |
$this->generateUri($request, 'user.reset-password', ['id' => $uuid->toString()], []) | |
); | |
$flashMessages->flashNow( | |
"message", | |
"A reset password email has been sent to the registered email address." | |
); | |
return new RedirectResponse( | |
$this->generateUri($request, 'user.forgot-password') | |
); | |
} | |
} | |
$data['message'] = $flashMessages->getFlash("message"); | |
return new HtmlResponse($this->renderer->render('user::forgot-password', $data)); | |
} | |
protected function generateUri( | |
ServerRequestInterface $request, | |
string $routeName, | |
array $substitutions = [], | |
array $options = [] | |
): string | |
{ | |
/** @var ?ServerUrlHelper $urlHelper */ | |
$urlHelper = $request->getAttribute(ServerUrlHelper::class); | |
/** @var ?RouterInterface $router */ | |
$router = $request->getAttribute(RouterInterface::class); | |
return $urlHelper->generate( | |
$router->generateUri($routeName, $substitutions, $options) | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php $this->headTitle('Forgot Password'); ?> | |
<div class="mb-4 p-2"> | |
<h1 class="text-center"><a href="/">Forgot Your Password? That's Okay.</a></h1> | |
<div class="grid gap-4 mt-8 border-2 bg-white border-slate-200 p-8 rounded-lg w-7/12 mx-auto"> | |
<?= $this->partial('user::message'); ?> | |
<div class="py-2 px-4"> | |
<form id="forgot-password" | |
class="grid grid-cols-1 gap-2" | |
method="post" | |
action="/forgot-password"> | |
<div class="w-full"> | |
<label for="email_address">Email Address:</label> | |
<input type="email" | |
name="email_address" | |
id="email_address" | |
placeholder="your email address"> | |
</div> | |
<div class="w-full"> | |
<input type="submit" | |
class="submit cursor-pointer" | |
name="submit" | |
value="Email me a password reset link"> | |
</div> | |
</form> | |
</div> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$app->route( | |
'/forgot-password', | |
[ | |
App\Middleware\UrlBuilderMiddleware::class, | |
User\Handler\ForgotPasswordHandler::class, | |
], | |
['get', 'post'], | |
'user.forgot-password' | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace User\Database; | |
use User\Entity\User; | |
use Laminas\Db\Adapter\Adapter; | |
use Laminas\Db\ResultSet\HydratingResultSet; | |
use Laminas\Db\TableGateway\AbstractTableGateway; | |
use Laminas\Hydrator\ReflectionHydrator; | |
use Laminas\Hydrator\NamingStrategy\MapNamingStrategy; | |
class UsersTableGateway extends AbstractTableGateway | |
{ | |
public function __construct(Adapter $adapter) | |
{ | |
$this->table = 'users'; | |
$this->adapter = $adapter; | |
$resultSetPrototype = new HydratingResultSet(); | |
$hydrator = new ReflectionHydrator(); | |
$hydrator->setNamingStrategy( | |
MapNamingStrategy::createFromAsymmetricMap( | |
[ | |
'firstName' => 'first_name', | |
'lastName' => 'last_name', | |
'emailAddress' => 'email_address', | |
], | |
[ | |
'first_name' => 'firstName', | |
'last_name' => 'lastName', | |
'email_address' => 'emailAddress' | |
], | |
) | |
); | |
$resultSetPrototype->setHydrator($hydrator); | |
$resultSetPrototype->setObjectPrototype(new User()); | |
$this->resultSetPrototype = $resultSetPrototype; | |
$this->initialize(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public function sendResetPasswordEmail(User $user, string $resetPasswordUrl) | |
{ | |
$body =<<<EOF | |
We got a request to change the password for the account with the email address: %s. | |
If you don't want to reset your password, you can ignore this email. | |
Open %s to reset your password. | |
EOF; | |
$this->mail | |
->setBody(sprintf($body, $user->emailAddress, $resetPasswordUrl)) | |
->addTo($user->emailAddress, $user->fullName) | |
->setSubject("Reset your password"); | |
$this->transport->send($this->mail); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace User\Handler; | |
use User\Database\UsersTableGateway; | |
use App\Service\Email\UserNotificationService; | |
use Laminas\Diactoros\Response\RedirectResponse; | |
use Laminas\Filter\{StringTrim,StripNewlines,StripTags}; | |
use Laminas\InputFilter\{Input,InputFilter}; | |
use Laminas\Validator\Identical; | |
use Mezzio\Flash\{FlashMessageMiddleware,FlashMessagesInterface}; | |
use Mezzio\Helper\ServerUrlHelper; | |
use Mezzio\Router\RouterInterface; | |
use Psr\Http\Message\{ResponseInterface,ServerRequestInterface}; | |
use Psr\Http\Server\RequestHandlerInterface; | |
use Laminas\Diactoros\Response\HtmlResponse; | |
use Mezzio\Template\TemplateRendererInterface; | |
class ResetPasswordHandler implements RequestHandlerInterface | |
{ | |
private InputFilter $inputFilter; | |
public function __construct( | |
private readonly TemplateRendererInterface $renderer, | |
private readonly UsersTableGateway $userService, | |
private readonly UserNotificationService $userNotificationService, | |
private readonly RouterInterface $router, | |
private readonly ServerUrlHelper $serverUrlHelper, | |
){ | |
$password = new Input('password'); | |
$password | |
->getFilterChain() | |
->attach(new StripTags()) | |
->attach(new StripNewlines()) | |
->attach(new StringTrim()); | |
$confirmPassword = new Input('confirm_password'); | |
$confirmPassword | |
->getValidatorChain() | |
->attach(new Identical([ | |
'token' => 'password' | |
])); | |
$confirmPassword | |
->getFilterChain() | |
->attach(new StripTags()) | |
->attach(new StripNewlines()) | |
->attach(new StringTrim()); | |
$this->inputFilter = new InputFilter(); | |
$this->inputFilter | |
->add($password) | |
->add($confirmPassword); | |
} | |
public function handle(ServerRequestInterface $request) : ResponseInterface | |
{ | |
$resetId = $request->getAttribute('id'); | |
$data = [ | |
'reset_id' => $resetId, | |
]; | |
/** @var FlashMessagesInterface $flashMessages */ | |
$flashMessages = $request->getAttribute(FlashMessageMiddleware::FLASH_ATTRIBUTE); | |
$user = $this->userService->findByResetPasswordId($resetId); | |
if ($user === null) { | |
$flashMessages->flash("message", "No reset password request is available for that user."); | |
return new RedirectResponse('/'); | |
} | |
if (strtoupper($request->getMethod()) === 'POST') { | |
$this->inputFilter->setData($request->getParsedBody()); | |
if (! $this->inputFilter->isValid()) { | |
$flashMessages->flash( | |
"message", | |
"The passwords do not match", | |
); | |
return new RedirectResponse('/reset-password/' . $resetId); | |
} | |
$emailUrl = $this->serverUrlHelper->generate($this->router->generateUri('home')); | |
$this->userService->resetPassword($user->getEmailAddress(), $this->inputFilter->getValue('password')); | |
$this->userNotificationService | |
->sendResetPasswordConfirmationEmail( | |
$user->getEmailAddress(), | |
$user->getFullName(), | |
$emailUrl, | |
); | |
$flashMessages->flash("message", "Password has been reset."); | |
return new RedirectResponse('/'); | |
} | |
return new HtmlResponse($this->renderer->render( | |
'user::reset-password', | |
$data | |
)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public function addForgotPasswordFlag(string $emailAddress, string $resetPasswordId): bool | |
{ | |
return (bool)$this->update( | |
[ | |
'reset_password_id' => $resetPasswordId, | |
], | |
[ | |
'email_address' => $emailAddress, | |
] | |
); | |
} | |
public function resetPassword(string $emailAddress, string $password): bool | |
{ | |
return (bool)$this->update( | |
[ | |
'reset_password_id' => null, | |
'password' => $this->getPasswordHash($password), | |
], | |
[ | |
'email_address' => $emailAddress, | |
] | |
); | |
} | |
public function findByResetPasswordId(string $resetPasswordId): ?User | |
{ | |
$users = $this->select([ | |
'reset_password_id' => $resetPasswordId, | |
]); | |
if ($users->count()) { | |
return $users->current(); | |
} | |
return null; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php $this->headTitle('Forgot Password'); ?> | |
<div class="mb-4 p-2"> | |
<h1 class="text-center"><a href="/">Reset Your Password</a></h1> | |
<?php $this->partial('user::message'); ?> | |
<div class="grid gap-4 mt-8 border-2 bg-white border-slate-200 p-8 rounded-lg w-4/5 w-auto"> | |
<div> | |
<form id="linkedin-post-scheduler" | |
class="grid grid-cols-1 gap-2" | |
method="post" | |
action="/reset-password/<?= $this->reset_id; ?>"> | |
<div class="w-full"> | |
<label>Password:</label> | |
<input type="password" name="password"> | |
</div> | |
<div class="w-full"> | |
<label>Confirm Password</label> | |
<input type="password" name="confirm_password"> | |
</div> | |
<div class="w-full"> | |
<input type="hidden" name="reset_id" value="<?= $this->reset_id; ?>"> | |
<input type="submit" | |
class="submit cursor-pointer" | |
name="submit" | |
value="Reset My Password"> | |
</div> | |
</form> | |
</div> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public function sendResetPasswordConfirmationEmail( | |
string $toAddress, string $toName, string $baseUrl) | |
{ | |
$body =<<<EOF | |
Your password has now been reset. | |
You can login here: %s | |
Your awesome support team. | |
EOF; | |
$this->mail | |
->setBody(sprintf($body, $baseUrl)) | |
->addTo($toAddress, $toName) | |
->setSubject("Your password has been reset"); | |
$this->transport->send($this->mail); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace User\Handler; | |
use User\Database\UsersTableGateway; | |
use User\Entity\User; | |
use Mezzio\Authentication\UserInterface; | |
use Mezzio\Session\{SessionInterface,SessionMiddleware}; | |
use Psr\Http\Message\{ResponseInterface,ServerRequestInterface}; | |
use Psr\Http\Server\RequestHandlerInterface; | |
use Laminas\Diactoros\Response\HtmlResponse; | |
use Mezzio\Template\TemplateRendererInterface; | |
class UserProfileHandler implements RequestHandlerInterface | |
{ | |
public function __construct( | |
private readonly TemplateRendererInterface $renderer, | |
private readonly UsersTableGateway $userService | |
){} | |
public function handle(ServerRequestInterface $request) : ResponseInterface | |
{ | |
/** @var ?SessionInterface $session */ | |
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE); | |
/** @var ?UserInterface $user */ | |
$authUser = $session->get(UserInterface::class); | |
/** @var ?User $user */ | |
$user = $this | |
->userService | |
->findByEmail($authUser['username']); | |
return new HtmlResponse($this->renderer->render( | |
'user::user-profile', | |
[ | |
'user' => $user, | |
] | |
)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public function findByEmail(string $emailAddress): ?User | |
{ | |
$users = $this->select([ | |
'email_address' => $emailAddress | |
]); | |
if ($users->count()) { | |
return $users->current(); | |
} | |
return null; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php $this->headTitle('Home'); ?> | |
<div class="mb-4 p-2"> | |
<h1 class="text-center"><a href="/">User Profile</a></h1> | |
<?php $this->partial('user::message'); ?> | |
<div class="grid gap-4 mt-8 border-2 bg-white border-slate-200 p-8 rounded-lg w-4/5 w-auto"> | |
<div> | |
<div class="w-full border-2 rounded-lg border-slate-100 text-white p-8"> | |
<div class="w-4/5"> | |
<div class="mb-4"> | |
<img src="/images/icons/avatar-icon-generic.png"> | |
<!-- Image Credit: https://duckduckgo.com/?q=generic+gravatar+logo&t=h_&iax=images&ia=images&iai=http%3A%2F%2Fgetdrawings.com%2Ffree-icon-bw%2Fgeneric-avatar-icon-3.png --> | |
</div> | |
<p class="mb-0 font-bold text-purple-800"><?= $this->user->fullName; ?></p> | |
<p class="mb-2 mt-0"><?= $this->user->emailAddress; ?></p></div> | |
</div> | |
</div> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace User\Handler; | |
use Laminas\Diactoros\Response\RedirectResponse; | |
use Laminas\Filter\{StringTrim,StripNewlines,StripTags}; | |
use Laminas\InputFilter\{Input,InputFilter}; | |
use Laminas\Validator\{EmailAddress,StringLength}; | |
use Mezzio\Authentication\AuthenticationInterface; | |
use Mezzio\Authentication\UserInterface; | |
use Mezzio\Flash\{FlashMessageMiddleware,FlashMessagesInterface}; | |
use Mezzio\Session\{SessionInterface,SessionMiddleware}; | |
use Psr\Http\Message\{ResponseInterface,ServerRequestInterface}; | |
use Psr\Http\Server\RequestHandlerInterface; | |
use Laminas\Diactoros\Response\HtmlResponse; | |
use Mezzio\Template\TemplateRendererInterface; | |
class LoginHandler implements RequestHandlerInterface | |
{ | |
public function __construct( | |
private readonly TemplateRendererInterface $renderer, | |
private readonly AuthenticationInterface $adapter | |
) { | |
$emailInput = new Input('email_address'); | |
$emailInput | |
->getValidatorChain() | |
->attach(new EmailAddress()); | |
$emailInput | |
->getFilterChain() | |
->attach(new StripTags()) | |
->attach(new StripNewlines()) | |
->attach(new StringTrim()); | |
$passwordInput = new Input('password'); | |
$passwordInput | |
->getValidatorChain() | |
->attach(new StringLength([ | |
'min' => 5, | |
'max' => 64, | |
])); | |
$passwordInput | |
->getFilterChain() | |
->attach(new StripTags()) | |
->attach(new StripNewlines()) | |
->attach(new StringTrim()); | |
$this->inputFilter = new InputFilter(); | |
$this->inputFilter | |
->add($emailInput) | |
->add($passwordInput); | |
} | |
public function handle(ServerRequestInterface $request) : ResponseInterface | |
{ | |
$data = []; | |
/** @var ?FlashMessagesInterface $flashMessages */ | |
$flashMessages = $request->getAttribute(FlashMessageMiddleware::FLASH_ATTRIBUTE); | |
if (strtoupper($request->getMethod()) === 'POST') { | |
$this->inputFilter->setData($request->getParsedBody()); | |
if (! $this->inputFilter->isValid()) { | |
$flashMessages->flash( | |
"message", | |
sprintf( | |
"Either the email address or password was invalid. Reason: %s", | |
var_export($this->inputFilter->getMessages(), TRUE) | |
) | |
); | |
return new RedirectResponse('/login'); | |
} | |
/** @var ?SessionInterface $session */ | |
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE); | |
$session->unset(UserInterface::class); | |
if ($this->adapter->authenticate($request)) { | |
return new RedirectResponse('/'); | |
} | |
} | |
$data['message'] = $flashMessages->getFlash("message"); | |
return new HtmlResponse($this->renderer->render( | |
'user::login', | |
$data | |
)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
return [ | |
'authentication' => [ | |
'redirect' => '/login', | |
'username' => 'email_address', | |
'password' => 'password', | |
'pdo' => [ | |
'dsn' => 'sqlite:' . __DIR__ . '/../../data/database/db.sqlite3', | |
'table' => 'users', | |
'field' => [ | |
'identity' => 'email_address', | |
'password' => 'password', | |
], | |
], | |
], | |
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace User\Handler; | |
use Laminas\Diactoros\Response\RedirectResponse; | |
use Laminas\Filter\{StringTrim,StripNewlines,StripTags}; | |
use Laminas\InputFilter\{Input,InputFilter}; | |
use Laminas\Validator\{EmailAddress,StringLength}; | |
use Mezzio\Authentication\AuthenticationInterface; | |
use Mezzio\Authentication\UserInterface; | |
use Mezzio\Flash\{FlashMessageMiddleware,FlashMessagesInterface}; | |
use Mezzio\Session\{SessionInterface,SessionMiddleware}; | |
use Psr\Http\Message\{ResponseInterface,ServerRequestInterface}; | |
use Psr\Http\Server\RequestHandlerInterface; | |
use Laminas\Diactoros\Response\HtmlResponse; | |
use Mezzio\Template\TemplateRendererInterface; | |
class LoginHandler implements RequestHandlerInterface | |
{ | |
public function __construct( | |
private readonly TemplateRendererInterface $renderer, | |
private readonly AuthenticationInterface $adapter | |
) { | |
$emailInput = new Input('email_address'); | |
$emailInput | |
->getValidatorChain() | |
->attach(new EmailAddress()); | |
$emailInput | |
->getFilterChain() | |
->attach(new StripTags()) | |
->attach(new StripNewlines()) | |
->attach(new StringTrim()); | |
$passwordInput = new Input('password'); | |
$passwordInput | |
->getValidatorChain() | |
->attach(new StringLength([ | |
'min' => 5, | |
'max' => 64, | |
])); | |
$passwordInput | |
->getFilterChain() | |
->attach(new StripTags()) | |
->attach(new StripNewlines()) | |
->attach(new StringTrim()); | |
$this->inputFilter = new InputFilter(); | |
$this->inputFilter | |
->add($emailInput) | |
->add($passwordInput); | |
} | |
public function handle(ServerRequestInterface $request) : ResponseInterface | |
{ | |
$data = []; | |
/** @var ?FlashMessagesInterface $flashMessages */ | |
$flashMessages = $request->getAttribute(FlashMessageMiddleware::FLASH_ATTRIBUTE); | |
if (strtoupper($request->getMethod()) === 'POST') { | |
$this->inputFilter->setData($request->getParsedBody()); | |
if (! $this->inputFilter->isValid()) { | |
$flashMessages->flash( | |
"message", | |
sprintf( | |
"Either the email address or password was invalid. Reason: %s", | |
var_export($this->inputFilter->getMessages(), TRUE) | |
) | |
); | |
return new RedirectResponse('/login'); | |
} | |
/** @var ?SessionInterface $session */ | |
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE); | |
$session->unset(UserInterface::class); | |
if ($this->adapter->authenticate($request)) { | |
return new RedirectResponse('/'); | |
} | |
} | |
$data['message'] = $flashMessages->getFlash("message"); | |
return new HtmlResponse($this->renderer->render( | |
'user::login', | |
$data | |
)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
return [ | |
'authentication' => [ | |
'redirect' => '/login', | |
'username' => 'email_address', | |
'password' => 'password', | |
'pdo' => [ | |
'dsn' => 'sqlite:' . __DIR__ . '/../../data/database/db.sqlite3', | |
'table' => 'users', | |
'field' => [ | |
'identity' => 'email_address', | |
'password' => 'password', | |
], | |
], | |
], | |
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php $this->headTitle('Log In'); ?> | |
<div class="mb-4 p-2 w-auto"> | |
<h1 class="text-center">Log in to your account</h1> | |
<?= $this->partial('user::message'); ?> | |
<div class="grid gap-4 mt-8 border-2 bg-white border-slate-200 p-8 rounded-lg w-7/12 mx-auto"> | |
<div class="py-2 px-4"> | |
<form id="login" | |
class="grid grid-cols-1 gap-2" | |
method="post" | |
action="/login"> | |
<div class="w-full mb-4"> | |
<label for="email_address">Email Address:</label> | |
<input type="email" | |
name="email_address" | |
id="email_address"> | |
</div> | |
<div class="w-full mb-4"> | |
<label for="password">Password:</label> | |
<input type="password" | |
name="password" | |
id="password"> | |
</div> | |
<div class="w-full"> | |
<input type="submit" | |
class="submit cursor-pointer" | |
name="submit" | |
value="Sign In"> | |
</div> | |
</form> | |
</div> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php if ($this->message): ?> | |
<div class="border-2 border-slate-200 bg-white p-8 font-bold drop-shadow-lg rounded-lg"> | |
<?= $this->message; ?> | |
</div> | |
<?php endif; ?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$app->route( | |
'/login', | |
User\Handler\LoginHandler::class, | |
['get', 'post'], | |
'user.login' | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment