Merge pull request #915 from acelaya-forks/feature/remove-plates

Feature/remove plates
This commit is contained in:
Alejandro Celaya 2020-11-22 18:42:19 +01:00 committed by GitHub
commit 74108a19e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 96 additions and 168 deletions

View File

@ -9,7 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this
* [#869](https://github.com/shlinkio/shlink/issues/869) Added support for Mercure Hub 0.10. * [#869](https://github.com/shlinkio/shlink/issues/869) Added support for Mercure Hub 0.10.
### Changed ### Changed
* *Nothing* * [#912](https://github.com/shlinkio/shlink/issues/912) Changed error templates to be plain html files, removing the dependency on `league/plates` package.
### Deprecated ### Deprecated
* *Nothing* * *Nothing*

View File

@ -38,7 +38,6 @@
"mezzio/mezzio": "^3.2", "mezzio/mezzio": "^3.2",
"mezzio/mezzio-fastroute": "^3.0", "mezzio/mezzio-fastroute": "^3.0",
"mezzio/mezzio-helpers": "^5.3", "mezzio/mezzio-helpers": "^5.3",
"mezzio/mezzio-platesrenderer": "^2.1",
"mezzio/mezzio-problem-details": "^1.1", "mezzio/mezzio-problem-details": "^1.1",
"mezzio/mezzio-swoole": "^2.6.4", "mezzio/mezzio-swoole": "^2.6.4",
"monolog/monolog": "^2.0", "monolog/monolog": "^2.0",

View File

@ -1,17 +0,0 @@
<?php
declare(strict_types=1);
return [
'templates' => [
'extension' => 'phtml',
],
'plates' => [
'extensions' => [
// extension service names or instances
],
],
];

View File

@ -15,7 +15,6 @@ return (new ConfigAggregator\ConfigAggregator([
Mezzio\ConfigProvider::class, Mezzio\ConfigProvider::class,
Mezzio\Router\ConfigProvider::class, Mezzio\Router\ConfigProvider::class,
Mezzio\Router\FastRouteRouter\ConfigProvider::class, Mezzio\Router\FastRouteRouter\ConfigProvider::class,
Mezzio\Plates\ConfigProvider::class,
Mezzio\Swoole\ConfigProvider::class, Mezzio\Swoole\ConfigProvider::class,
ProblemDetails\ConfigProvider::class, ProblemDetails\ConfigProvider::class,
Diactoros\ConfigProvider::class, Diactoros\ConfigProvider::class,

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI; namespace ShlinkioTest\Shlink\CLI;
use Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\CLI\ConfigProvider; use Shlinkio\Shlink\CLI\ConfigProvider;
@ -21,7 +22,9 @@ class ConfigProviderTest extends TestCase
{ {
$config = ($this->configProvider)(); $config = ($this->configProvider)();
self::assertCount(3, $config);
self::assertArrayHasKey('cli', $config); self::assertArrayHasKey('cli', $config);
self::assertArrayHasKey('dependencies', $config); self::assertArrayHasKey('dependencies', $config);
self::assertArrayHasKey(ConfigAbstractFactory::class, $config);
} }
} }

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Core; namespace Shlinkio\Shlink\Core;
use Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory; use Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory;
use Mezzio\Template\TemplateRendererInterface; use Laminas\ServiceManager\Factory\InvokableFactory;
use Psr\EventDispatcher\EventDispatcherInterface; use Psr\EventDispatcher\EventDispatcherInterface;
use Shlinkio\Shlink\Core\ErrorHandler; use Shlinkio\Shlink\Core\ErrorHandler;
use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions; use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions;
@ -16,7 +16,7 @@ return [
'dependencies' => [ 'dependencies' => [
'factories' => [ 'factories' => [
ErrorHandler\NotFoundRedirectHandler::class => ConfigAbstractFactory::class, ErrorHandler\NotFoundRedirectHandler::class => ConfigAbstractFactory::class,
ErrorHandler\NotFoundTemplateHandler::class => ConfigAbstractFactory::class, ErrorHandler\NotFoundTemplateHandler::class => InvokableFactory::class,
Options\AppOptions::class => ConfigAbstractFactory::class, Options\AppOptions::class => ConfigAbstractFactory::class,
Options\DeleteShortUrlsOptions::class => ConfigAbstractFactory::class, Options\DeleteShortUrlsOptions::class => ConfigAbstractFactory::class,
@ -60,7 +60,6 @@ return [
Util\RedirectResponseHelper::class, Util\RedirectResponseHelper::class,
'config.router.base_path', 'config.router.base_path',
], ],
ErrorHandler\NotFoundTemplateHandler::class => [TemplateRendererInterface::class],
Options\AppOptions::class => ['config.app_options'], Options\AppOptions::class => ['config.app_options'],
Options\DeleteShortUrlsOptions::class => ['config.delete_short_urls'], Options\DeleteShortUrlsOptions::class => ['config.delete_short_urls'],

View File

@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
return [
'mezzio' => [
'error_handler' => [
'template_404' => 'ShlinkCore::error/404',
'template_error' => 'ShlinkCore::error/error',
],
],
];

View File

@ -1,13 +0,0 @@
<?php
declare(strict_types=1);
return [
'templates' => [
'paths' => [
'ShlinkCore' => __DIR__ . '/../templates',
],
],
];

View File

@ -4,40 +4,37 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Core\ErrorHandler; namespace Shlinkio\Shlink\Core\ErrorHandler;
use Closure;
use Fig\Http\Message\StatusCodeInterface; use Fig\Http\Message\StatusCodeInterface;
use InvalidArgumentException;
use Laminas\Diactoros\Response; use Laminas\Diactoros\Response;
use Mezzio\Router\RouteResult; use Mezzio\Router\RouteResult;
use Mezzio\Template\TemplateRendererInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface; use Psr\Http\Server\RequestHandlerInterface;
use function file_get_contents;
use function sprintf;
class NotFoundTemplateHandler implements RequestHandlerInterface class NotFoundTemplateHandler implements RequestHandlerInterface
{ {
public const NOT_FOUND_TEMPLATE = 'ShlinkCore::error/404'; private const TEMPLATES_BASE_DIR = __DIR__ . '/../../templates';
public const INVALID_SHORT_CODE_TEMPLATE = 'ShlinkCore::invalid-short-code'; public const NOT_FOUND_TEMPLATE = '404.html';
public const INVALID_SHORT_CODE_TEMPLATE = 'invalid-short-code.html';
private Closure $readFile;
private TemplateRendererInterface $renderer; public function __construct(?callable $readFile = null)
public function __construct(TemplateRendererInterface $renderer)
{ {
$this->renderer = $renderer; $this->readFile = $readFile ? Closure::fromCallable($readFile) : fn (string $file) => file_get_contents($file);
} }
/**
* Dispatch the next available middleware and return the response.
*
*
* @throws InvalidArgumentException
*/
public function handle(ServerRequestInterface $request): ResponseInterface public function handle(ServerRequestInterface $request): ResponseInterface
{ {
/** @var RouteResult $routeResult */ /** @var RouteResult $routeResult */
$routeResult = $request->getAttribute(RouteResult::class, RouteResult::fromRouteFailure(null)); $routeResult = $request->getAttribute(RouteResult::class) ?? RouteResult::fromRouteFailure(null);
$status = StatusCodeInterface::STATUS_NOT_FOUND; $status = StatusCodeInterface::STATUS_NOT_FOUND;
$template = $routeResult->isFailure() ? self::NOT_FOUND_TEMPLATE : self::INVALID_SHORT_CODE_TEMPLATE; $template = $routeResult->isFailure() ? self::NOT_FOUND_TEMPLATE : self::INVALID_SHORT_CODE_TEMPLATE;
return new Response\HtmlResponse($this->renderer->render($template), $status); $templateContent = ($this->readFile)(sprintf('%s/%s', self::TEMPLATES_BASE_DIR, $template));
return new Response\HtmlResponse($templateContent, $status);
} }
} }

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Not Found | Shlink</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="shortcut icon" href="/favicon.ico">
<style>
html, body {height: 100%}
.app {height: 100vh; display: flex; align-items: center; justify-content: center; flex-flow: column;}
p {margin-bottom: 20px;}
body {text-align: center;}
</style>
</head>
<body>
<div class="app">
<main class="container">
<h1>404</h1>
<hr>
<h3>Page not found.</h3>
<p>The page you requested could not be found.</p>
</main>
</div>
</body>
</html>

View File

@ -1,19 +0,0 @@
<?php $this->layout('ShlinkCore::layout/default') ?>
<?php $this->start('title') ?>
Not Found
<?php $this->end() ?>
<?php $this->start('stylesheets') ?>
<style>
p {margin-bottom: 20px;}
body {text-align: center;}
</style>
<?php $this->end() ?>
<?php $this->start('main') ?>
<h1>404</h1>
<hr>
<h3>Page not found.</h3>
<p>The page you requested could not be found.</p>
<?php $this->end() ?>

View File

@ -1,25 +0,0 @@
<?php $this->layout('ShlinkCore::layout/default') ?>
<?php $this->start('title') ?>
<?= $this->e($status . ' ' . $reason) ?>
<?php $this->end() ?>
<?php $this->start('stylesheets') ?>
<style>
p {margin-bottom: 20px;}
body {text-align: center;}
</style>
<?php $this->end() ?>
<?php $this->start('main') ?>
<h1>Oops!</h1>
<hr>
<?php if ($status !== 404): ?>
<p><?= sprintf('We encountered a %s %s error.', $status, $reason) ?></p>
<?php else: ?>
<p>'This short URL doesn't seem to be valid.</p>
<p>'Make sure you included all the characters, with no extra punctuation.</p>
<?php endif; ?>
<?php $this->end() ?>

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Invalid Short URL | Shlink</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="shortcut icon" href="/favicon.ico">
<style>
html, body {height: 100%}
.app {height: 100vh; display: flex; align-items: center; justify-content: center; flex-flow: column;}
p {margin-bottom: 20px;}
body {text-align: center;}
</style>
</head>
<body>
<div class="app">
<main class="container">
<h1>Oops!</h1>
<hr>
<p>This short URL doesn't seem to be valid.</p>
<p>Make sure you included all the characters, with no extra punctuation.</p>
</main>
</div>
</body>
</html>

View File

@ -1,19 +0,0 @@
<?php $this->layout('ShlinkCore::layout/default') ?>
<?php $this->start('title') ?>
Invalid Short URL
<?php $this->end() ?>
<?php $this->start('stylesheets') ?>
<style>
p {margin-bottom: 20px;}
body {text-align: center;}
</style>
<?php $this->end() ?>
<?php $this->start('main') ?>
<h1>Oops!</h1>
<hr>
<p>This short URL doesn't seem to be valid.</p>
<p>Make sure you included all the characters, with no extra punctuation.</p>
<?php $this->end() ?>

View File

@ -1,23 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title><?= $this->section('title', '') ?> | Shlink</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="shortcut icon" href="/favicon.ico">
<style>
html, body {height: 100%}
.app {height: 100vh; display: flex; align-items: center; justify-content: center; flex-flow: column;}
</style>
<?= $this->section('stylesheets', '') ?>
</head>
<body>
<div class="app">
<main class="container">
<?= $this->section('main', '') ?>
</main>
</div>
</body>
</html>

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\Core; namespace ShlinkioTest\Shlink\Core;
use Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\Core\ConfigProvider; use Shlinkio\Shlink\Core\ConfigProvider;
@ -19,11 +20,13 @@ class ConfigProviderTest extends TestCase
/** @test */ /** @test */
public function properConfigIsReturned(): void public function properConfigIsReturned(): void
{ {
$config = $this->configProvider->__invoke(); $config = ($this->configProvider)();
self::assertCount(5, $config);
self::assertArrayHasKey('routes', $config); self::assertArrayHasKey('routes', $config);
self::assertArrayHasKey('dependencies', $config); self::assertArrayHasKey('dependencies', $config);
self::assertArrayHasKey('templates', $config); self::assertArrayHasKey('entity_manager', $config);
self::assertArrayHasKey('mezzio', $config); self::assertArrayHasKey('events', $config);
self::assertArrayHasKey(ConfigAbstractFactory::class, $config);
} }
} }

View File

@ -4,29 +4,30 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\Core\ErrorHandler; namespace ShlinkioTest\Shlink\Core\ErrorHandler;
use Closure;
use Laminas\Diactoros\Response; use Laminas\Diactoros\Response;
use Laminas\Diactoros\ServerRequestFactory; use Laminas\Diactoros\ServerRequestFactory;
use Mezzio\Router\Route; use Mezzio\Router\Route;
use Mezzio\Router\RouteResult; use Mezzio\Router\RouteResult;
use Mezzio\Template\TemplateRendererInterface;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\MiddlewareInterface;
use Shlinkio\Shlink\Core\ErrorHandler\NotFoundTemplateHandler; use Shlinkio\Shlink\Core\ErrorHandler\NotFoundTemplateHandler;
class NotFoundTemplateHandlerTest extends TestCase class NotFoundTemplateHandlerTest extends TestCase
{ {
use ProphecyTrait;
private NotFoundTemplateHandler $handler; private NotFoundTemplateHandler $handler;
private ObjectProphecy $renderer; private Closure $readFile;
private bool $readFileCalled;
public function setUp(): void public function setUp(): void
{ {
$this->renderer = $this->prophesize(TemplateRendererInterface::class); $this->readFileCalled = false;
$this->handler = new NotFoundTemplateHandler($this->renderer->reveal()); $this->readFile = function (string $fileName): string {
$this->readFileCalled = true;
return $fileName;
};
$this->handler = new NotFoundTemplateHandler($this->readFile);
} }
/** /**
@ -35,13 +36,11 @@ class NotFoundTemplateHandlerTest extends TestCase
*/ */
public function properErrorTemplateIsRendered(ServerRequestInterface $request, string $expectedTemplate): void public function properErrorTemplateIsRendered(ServerRequestInterface $request, string $expectedTemplate): void
{ {
$request = $request->withHeader('Accept', 'text/html'); $resp = $this->handler->handle($request->withHeader('Accept', 'text/html'));
$render = $this->renderer->render($expectedTemplate)->willReturn('');
$resp = $this->handler->handle($request);
self::assertInstanceOf(Response\HtmlResponse::class, $resp); self::assertInstanceOf(Response\HtmlResponse::class, $resp);
$render->shouldHaveBeenCalledOnce(); self::assertStringContainsString($expectedTemplate, (string) $resp->getBody());
self::assertTrue($this->readFileCalled);
} }
public function provideTemplates(): iterable public function provideTemplates(): iterable

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\Rest; namespace ShlinkioTest\Shlink\Rest;
use Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\Rest\ConfigProvider; use Shlinkio\Shlink\Rest\ConfigProvider;
@ -21,8 +22,12 @@ class ConfigProviderTest extends TestCase
{ {
$config = ($this->configProvider)(); $config = ($this->configProvider)();
self::assertCount(5, $config);
self::assertArrayHasKey('routes', $config); self::assertArrayHasKey('routes', $config);
self::assertArrayHasKey('dependencies', $config); self::assertArrayHasKey('dependencies', $config);
self::assertArrayHasKey('auth', $config);
self::assertArrayHasKey('entity_manager', $config);
self::assertArrayHasKey(ConfigAbstractFactory::class, $config);
} }
/** /**