add chapter 12 solutions
This commit is contained in:
parent
f857fa4752
commit
ebbcc6e7f6
23 changed files with 1998 additions and 0 deletions
31
implementation/12/src/Action/Hello.php
Normal file
31
implementation/12/src/Action/Hello.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Lubian\NoFramework\Action;
|
||||
|
||||
use Lubian\NoFramework\Service\Time\Clock;
|
||||
use Lubian\NoFramework\Template\Renderer;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
final class Hello
|
||||
{
|
||||
public function __invoke(
|
||||
ResponseInterface $response,
|
||||
Clock $clock,
|
||||
Renderer $renderer,
|
||||
string $name = 'Stranger',
|
||||
): ResponseInterface {
|
||||
$data = [
|
||||
'name' => $name,
|
||||
'time' => $clock->now()
|
||||
->format('H:i:s'),
|
||||
];
|
||||
|
||||
$content = $renderer->render('hello', $data,);
|
||||
|
||||
$body = $response->getBody();
|
||||
$body->write($content);
|
||||
|
||||
return $response->withBody($body)
|
||||
->withStatus(200);
|
||||
}
|
||||
}
|
24
implementation/12/src/Action/Other.php
Normal file
24
implementation/12/src/Action/Other.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Lubian\NoFramework\Action;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
final class Other implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(private readonly ResponseInterface $response)
|
||||
{
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$body = $this->response->getBody();
|
||||
|
||||
$body->write('This works too!');
|
||||
|
||||
return $this->response->withBody($body)
|
||||
->withStatus(200);
|
||||
}
|
||||
}
|
109
implementation/12/src/Bootstrap.php
Normal file
109
implementation/12/src/Bootstrap.php
Normal file
|
@ -0,0 +1,109 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Lubian\NoFramework;
|
||||
|
||||
use FastRoute\Dispatcher;
|
||||
use Invoker\InvokerInterface;
|
||||
use Laminas\Diactoros\Response;
|
||||
use Lubian\NoFramework\Exception\InternalServerError;
|
||||
use Lubian\NoFramework\Exception\MethodNotAllowed;
|
||||
use Lubian\NoFramework\Exception\NotFound;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Throwable;
|
||||
use Whoops\Handler\PrettyPageHandler;
|
||||
use Whoops\Run;
|
||||
|
||||
use function assert;
|
||||
use function error_log;
|
||||
use function error_reporting;
|
||||
use function getenv;
|
||||
use function header;
|
||||
use function sprintf;
|
||||
use function strtolower;
|
||||
|
||||
use const E_ALL;
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$config = require __DIR__ . '/../config/settings.php';
|
||||
assert($config instanceof Configuration);
|
||||
$environment = $config->environment;
|
||||
|
||||
error_reporting(E_ALL);
|
||||
|
||||
$whoops = new Run;
|
||||
|
||||
if ($environment === 'dev') {
|
||||
$whoops->pushHandler(new PrettyPageHandler);
|
||||
} else {
|
||||
$whoops->pushHandler(function (Throwable $t) {
|
||||
error_log('ERROR: ' . $t->getMessage(), $t->getCode());
|
||||
echo 'Oooopsie';
|
||||
});
|
||||
}
|
||||
|
||||
$whoops->register();
|
||||
|
||||
$container = require __DIR__ . '/../config/container.php';
|
||||
assert($container instanceof ContainerInterface);
|
||||
|
||||
$request = $container->get(ServerRequestInterface::class);
|
||||
assert($request instanceof ServerRequestInterface);
|
||||
|
||||
$dispatcher = $container->get(Dispatcher::class);
|
||||
assert($dispatcher instanceof Dispatcher);
|
||||
|
||||
$routeInfo = $dispatcher->dispatch($request->getMethod(), $request->getUri() ->getPath(),);
|
||||
|
||||
try {
|
||||
switch ($routeInfo[0]) {
|
||||
case Dispatcher::FOUND:
|
||||
$routeTarget = $routeInfo[1];
|
||||
$args = $routeInfo[2];
|
||||
foreach ($routeInfo[2] as $attributeName => $attributeValue) {
|
||||
$request = $request->withAttribute($attributeName, $attributeValue);
|
||||
}
|
||||
$args['request'] = $request;
|
||||
$invoker = $container->get(InvokerInterface::class);
|
||||
assert($invoker instanceof InvokerInterface);
|
||||
$response = $invoker->call($routeTarget, $args);
|
||||
assert($response instanceof ResponseInterface);
|
||||
break;
|
||||
case Dispatcher::METHOD_NOT_ALLOWED:
|
||||
throw new MethodNotAllowed;
|
||||
case Dispatcher::NOT_FOUND:
|
||||
default:
|
||||
throw new NotFound;
|
||||
}
|
||||
} catch (MethodNotAllowed) {
|
||||
$response = (new Response)->withStatus(405);
|
||||
$response->getBody()
|
||||
->write('Method not Allowed');
|
||||
} catch (NotFound) {
|
||||
$response = (new Response)->withStatus(404);
|
||||
$response->getBody()
|
||||
->write('Not Found');
|
||||
} catch (Throwable $t) {
|
||||
throw new InternalServerError($t->getMessage(), $t->getCode(), $t);
|
||||
}
|
||||
|
||||
foreach ($response->getHeaders() as $name => $values) {
|
||||
$first = strtolower($name) !== 'set-cookie';
|
||||
foreach ($values as $value) {
|
||||
$header = sprintf('%s: %s', $name, $value);
|
||||
header($header, $first);
|
||||
$first = false;
|
||||
}
|
||||
}
|
||||
|
||||
$statusLine = sprintf(
|
||||
'HTTP/%s %s %s',
|
||||
$response->getProtocolVersion(),
|
||||
$response->getStatusCode(),
|
||||
$response->getReasonPhrase()
|
||||
);
|
||||
header($statusLine, true, $response->getStatusCode());
|
||||
|
||||
echo $response->getBody();
|
14
implementation/12/src/Configuration.php
Normal file
14
implementation/12/src/Configuration.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Lubian\NoFramework;
|
||||
|
||||
final class Configuration
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string $environment = 'dev',
|
||||
public readonly string $routesFile = __DIR__ . '/../config/routes.php',
|
||||
public readonly string $templateDir = __DIR__ . '/../templates',
|
||||
public readonly string $templateExtension = '.html',
|
||||
) {
|
||||
}
|
||||
}
|
9
implementation/12/src/Exception/InternalServerError.php
Normal file
9
implementation/12/src/Exception/InternalServerError.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Lubian\NoFramework\Exception;
|
||||
|
||||
use Exception;
|
||||
|
||||
final class InternalServerError extends Exception
|
||||
{
|
||||
}
|
9
implementation/12/src/Exception/MethodNotAllowed.php
Normal file
9
implementation/12/src/Exception/MethodNotAllowed.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Lubian\NoFramework\Exception;
|
||||
|
||||
use Exception;
|
||||
|
||||
final class MethodNotAllowed extends Exception
|
||||
{
|
||||
}
|
9
implementation/12/src/Exception/NotFound.php
Normal file
9
implementation/12/src/Exception/NotFound.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Lubian\NoFramework\Exception;
|
||||
|
||||
use Exception;
|
||||
|
||||
final class NotFound extends Exception
|
||||
{
|
||||
}
|
10
implementation/12/src/Service/Time/Clock.php
Normal file
10
implementation/12/src/Service/Time/Clock.php
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Lubian\NoFramework\Service\Time;
|
||||
|
||||
use DateTimeImmutable;
|
||||
|
||||
interface Clock
|
||||
{
|
||||
public function now(): DateTimeImmutable;
|
||||
}
|
13
implementation/12/src/Service/Time/SystemClock.php
Normal file
13
implementation/12/src/Service/Time/SystemClock.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Lubian\NoFramework\Service\Time;
|
||||
|
||||
use DateTimeImmutable;
|
||||
|
||||
final class SystemClock implements Clock
|
||||
{
|
||||
public function now(): DateTimeImmutable
|
||||
{
|
||||
return new DateTimeImmutable;
|
||||
}
|
||||
}
|
17
implementation/12/src/Template/MustacheRenderer.php
Normal file
17
implementation/12/src/Template/MustacheRenderer.php
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Lubian\NoFramework\Template;
|
||||
|
||||
use Mustache_Engine;
|
||||
|
||||
final class MustacheRenderer implements Renderer
|
||||
{
|
||||
public function __construct(private readonly Mustache_Engine $engine)
|
||||
{
|
||||
}
|
||||
|
||||
public function render(string $template, array $data): string
|
||||
{
|
||||
return $this->engine->render($template, $data);
|
||||
}
|
||||
}
|
11
implementation/12/src/Template/Renderer.php
Normal file
11
implementation/12/src/Template/Renderer.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Lubian\NoFramework\Template;
|
||||
|
||||
interface Renderer
|
||||
{
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public function render(string $template, array $data): string;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue