summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/routes.php9
-rw-r--r--includes/pages/guest_credits.php17
-rw-r--r--src/Controllers/BaseController.php8
-rw-r--r--src/Controllers/CreditsController.php24
-rw-r--r--src/Middleware/LegacyMiddleware.php6
-rw-r--r--src/Middleware/RequestHandler.php31
-rw-r--r--templates/layouts/app.twig34
-rw-r--r--templates/pages/credits.html36
-rw-r--r--templates/pages/credits.twig42
-rw-r--r--tests/Unit/Controllers/CreditsControllerTest.php28
-rw-r--r--tests/Unit/Middleware/RequestHandlerTest.php77
11 files changed, 222 insertions, 90 deletions
diff --git a/config/routes.php b/config/routes.php
index 5296dbc7..2267bc88 100644
--- a/config/routes.php
+++ b/config/routes.php
@@ -1,14 +1,7 @@
<?php
use FastRoute\RouteCollector;
-use Psr\Http\Message\ServerRequestInterface;
/** @var RouteCollector $route */
-/** Demo route endpoint, TODO: Remove */
-$route->addRoute('GET', '/hello/{name}', function ($request) {
- /** @var ServerRequestInterface $request */
- $name = $request->getAttribute('name');
-
- return response(sprintf('Hello %s!', htmlspecialchars($name)));
-});
+$route->get('/credits', 'CreditsController@index');
diff --git a/includes/pages/guest_credits.php b/includes/pages/guest_credits.php
deleted file mode 100644
index 5f90c97c..00000000
--- a/includes/pages/guest_credits.php
+++ /dev/null
@@ -1,17 +0,0 @@
-<?php
-
-/**
- * @return string
- */
-function credits_title()
-{
- return __('Credits');
-}
-
-/**
- * @return string
- */
-function guest_credits()
-{
- return view(__DIR__ . '/../../templates/pages/credits.html');
-}
diff --git a/src/Controllers/BaseController.php b/src/Controllers/BaseController.php
new file mode 100644
index 00000000..6a27a066
--- /dev/null
+++ b/src/Controllers/BaseController.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Engelsystem\Controllers;
+
+abstract class BaseController
+{
+
+}
diff --git a/src/Controllers/CreditsController.php b/src/Controllers/CreditsController.php
new file mode 100644
index 00000000..568811c7
--- /dev/null
+++ b/src/Controllers/CreditsController.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Engelsystem\Controllers;
+
+use Engelsystem\Http\Response;
+
+class CreditsController extends BaseController
+{
+ /** @var Response */
+ protected $response;
+
+ public function __construct(Response $response)
+ {
+ $this->response = $response;
+ }
+
+ /**
+ * @return Response
+ */
+ public function index()
+ {
+ return $this->response->withView('pages/credits.twig');
+ }
+}
diff --git a/src/Middleware/LegacyMiddleware.php b/src/Middleware/LegacyMiddleware.php
index f8c2a205..ebf456eb 100644
--- a/src/Middleware/LegacyMiddleware.php
+++ b/src/Middleware/LegacyMiddleware.php
@@ -18,7 +18,6 @@ class LegacyMiddleware implements MiddlewareInterface
'angeltypes',
'api',
'atom',
- 'credits',
'ical',
'login',
'public_dashboard',
@@ -249,11 +248,6 @@ class LegacyMiddleware implements MiddlewareInterface
$title = admin_log_title();
$content = admin_log();
return [$title, $content];
- case 'credits':
- require_once realpath(__DIR__ . '/../../includes/pages/guest_credits.php');
- $title = credits_title();
- $content = guest_credits();
- return [$title, $content];
}
require_once realpath(__DIR__ . '/../../includes/pages/guest_start.php');
diff --git a/src/Middleware/RequestHandler.php b/src/Middleware/RequestHandler.php
index e1381abf..ebe1ff9e 100644
--- a/src/Middleware/RequestHandler.php
+++ b/src/Middleware/RequestHandler.php
@@ -35,7 +35,7 @@ class RequestHandler implements MiddlewareInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$requestHandler = $request->getAttribute('route-request-handler');
- $requestHandler = $this->resolveMiddleware($requestHandler);
+ $requestHandler = $this->resolveRequestHandler($requestHandler);
if ($requestHandler instanceof MiddlewareInterface) {
return $requestHandler->process($request, $handler);
@@ -47,4 +47,33 @@ class RequestHandler implements MiddlewareInterface
throw new InvalidArgumentException('Unable to process request handler of type ' . gettype($requestHandler));
}
+
+ /**
+ * @param string|callable|MiddlewareInterface|RequestHandlerInterface $handler
+ * @return MiddlewareInterface|RequestHandlerInterface
+ */
+ protected function resolveRequestHandler($handler)
+ {
+ if (is_string($handler) && strpos($handler, '@') !== false) {
+ list($class, $method) = explode('@', $handler, 2);
+ if (!class_exists($class) && !$this->container->has($class)) {
+ $class = sprintf('Engelsystem\\Controllers\\%s', $class);
+ }
+
+ $handler = [$class, $method];
+ }
+
+ if (
+ is_array($handler)
+ && is_string($handler[0])
+ && (
+ class_exists($handler[0])
+ || $this->container->has($handler[0])
+ )
+ ) {
+ $handler[0] = $this->container->make($handler[0]);
+ }
+
+ return $this->resolveMiddleware($handler);
+ }
}
diff --git a/templates/layouts/app.twig b/templates/layouts/app.twig
index 20ea853b..4868a714 100644
--- a/templates/layouts/app.twig
+++ b/templates/layouts/app.twig
@@ -28,8 +28,10 @@
{% endblock %}
<div class="container-fluid">
- <div class="row">
- {% block content %}{{ content|raw }}{% endblock %}
+ <div class="row" id="content">
+ {% block content %}
+ {{ content|raw }}
+ {% endblock %}
</div>
<div class="row" id="footer">
{% block footer %}
@@ -38,19 +40,21 @@
</div>
</div>
- <script type="text/javascript" src="vendor/bootstrap/js/bootstrap.min.js"></script>
- <script type="text/javascript" src="vendor/bootstrap-datepicker-1.7.1/js/bootstrap-datepicker.min.js"></script>
- <script type="text/javascript" src="vendor/bootstrap-datepicker-1.7.1/locales/bootstrap-datepicker.de.min.js"></script>
- <script type="text/javascript" src="vendor/Chart.min.js"></script>
- <script type="text/javascript" src="js/forms.js"></script>
- <script type="text/javascript" src="vendor/moment-with-locales.min.js"></script>
- <script type="text/javascript">
- $(function () {
- moment.locale("{{ session_get('locale')|escape('js') }}");
- });
- </script>
- <script type="text/javascript" src="js/moment-countdown.js"></script>
- <script type="text/javascript" src="js/sticky-headers.js"></script>
+ {% block scripts %}
+ <script type="text/javascript" src="vendor/bootstrap/js/bootstrap.min.js"></script>
+ <script type="text/javascript" src="vendor/bootstrap-datepicker-1.7.1/js/bootstrap-datepicker.min.js"></script>
+ <script type="text/javascript" src="vendor/bootstrap-datepicker-1.7.1/locales/bootstrap-datepicker.de.min.js"></script>
+ <script type="text/javascript" src="vendor/Chart.min.js"></script>
+ <script type="text/javascript" src="js/forms.js"></script>
+ <script type="text/javascript" src="vendor/moment-with-locales.min.js"></script>
+ <script type="text/javascript">
+ $(function () {
+ moment.locale("{{ session_get('locale')|escape('js') }}");
+ });
+ </script>
+ <script type="text/javascript" src="js/moment-countdown.js"></script>
+ <script type="text/javascript" src="js/sticky-headers.js"></script>
+ {% endblock %}
{% endblock %}
</body>
diff --git a/templates/pages/credits.html b/templates/pages/credits.html
deleted file mode 100644
index 4e247113..00000000
--- a/templates/pages/credits.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<div class="container">
- <h1>Credits</h1>
- <div class="row">
- <div class="col-md-4">
- <h2>Source code</h2>
- <p>
- The original system was written by <a href="https://github.com/cookieBerlin/engelsystem">cookie</a>.
- It was then completely rewritten and enhanced by
- <a href="https://notrademark.de">msquare</a> (maintainer),
- <a href="https://myigel.name">MyIgel</a>,
- <a href="https://mortzu.de">mortzu</a>,
- <a href="https://jplitza.de">jplitza</a> and
- <a href="https://github.com/gnomus">gnomus</a>.
- </p>
- <p>
- Please look at the <a href="https://github.com/engelsystem/engelsystem/graphs/contributors">
- contributor list on github</a> for a more complete version.
- </p>
- </div>
- <div class="col-md-4">
- <h2>Hosting</h2>
- <p>
- Webspace, development platform and domain on <a href="https://engelsystem.de">engelsystem.de</a>
- is currently provided by <a href="https://www.wybt.net/">would you buy this?</a> (ichdasich)
- and adminstrated by <a href="https://mortzu.de">mortzu</a>,
- <a href="http://derf.homelinux.org">derf</a> and ichdasich.
- </p>
- </div>
- <div class="col-md-4">
- <h2>Translation</h2>
- <p>
- Many thanks for the german translation: <a href="http://e7p.de">e7p</a>
- </p>
- </div>
- </div>
-</div>
diff --git a/templates/pages/credits.twig b/templates/pages/credits.twig
new file mode 100644
index 00000000..ff2bf873
--- /dev/null
+++ b/templates/pages/credits.twig
@@ -0,0 +1,42 @@
+{% extends "layouts/app.twig" %}
+
+{% block title %}{{ __('Credits') }}{% endblock %}
+
+{% block content %}
+ <div class="container">
+ <h1>Credits</h1>
+ <div class="row">
+ <div class="col-md-4">
+ <h2>Source code</h2>
+ <p>
+ The original system was written by <a href="https://github.com/cookieBerlin/engelsystem">cookie</a>.
+ It was then completely rewritten and enhanced by
+ <a href="https://notrademark.de">msquare</a> (maintainer),
+ <a href="https://myigel.name">MyIgel</a>,
+ <a href="https://mortzu.de">mortzu</a>,
+ <a href="https://jplitza.de">jplitza</a> and
+ <a href="https://github.com/gnomus">gnomus</a>.
+ </p>
+ <p>
+ Please look at the <a href="https://github.com/engelsystem/engelsystem/graphs/contributors">
+ contributor list on github</a> for a more complete version.
+ </p>
+ </div>
+ <div class="col-md-4">
+ <h2>Hosting</h2>
+ <p>
+ Webspace, development platform and domain on <a href="https://engelsystem.de">engelsystem.de</a>
+ is currently provided by <a href="https://www.wybt.net/">would you buy this?</a> (ichdasich)
+ and adminstrated by <a href="https://mortzu.de">mortzu</a>,
+ <a href="http://derf.homelinux.org">derf</a> and ichdasich.
+ </p>
+ </div>
+ <div class="col-md-4">
+ <h2>Translation</h2>
+ <p>
+ Many thanks for the german translation: <a href="http://e7p.de">e7p</a>
+ </p>
+ </div>
+ </div>
+ </div>
+{% endblock %}
diff --git a/tests/Unit/Controllers/CreditsControllerTest.php b/tests/Unit/Controllers/CreditsControllerTest.php
new file mode 100644
index 00000000..6f0200f2
--- /dev/null
+++ b/tests/Unit/Controllers/CreditsControllerTest.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Unit\Controllers;
+
+use Engelsystem\Controllers\CreditsController;
+use Engelsystem\Http\Response;
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+
+class CreditsControllerTest extends TestCase
+{
+ /**
+ * @covers \Engelsystem\Controllers\CreditsController::__construct
+ * @covers \Engelsystem\Controllers\CreditsController::index
+ */
+ public function testIndex()
+ {
+ /** @var Response|MockObject $response */
+ $response = $this->createMock(Response::class);
+
+ $response->expects($this->once())
+ ->method('withView')
+ ->with('pages/credits.twig');
+
+ $controller = new CreditsController($response);
+ $controller->index();
+ }
+}
diff --git a/tests/Unit/Middleware/RequestHandlerTest.php b/tests/Unit/Middleware/RequestHandlerTest.php
index 896b55c3..b1ffbd33 100644
--- a/tests/Unit/Middleware/RequestHandlerTest.php
+++ b/tests/Unit/Middleware/RequestHandlerTest.php
@@ -38,15 +38,12 @@ class RequestHandlerTest extends TestCase
public function testProcess()
{
/** @var Application|MockObject $container */
- $container = $this->createMock(Application::class);
/** @var ServerRequestInterface|MockObject $request */
- $request = $this->getMockForAbstractClass(ServerRequestInterface::class);
/** @var RequestHandlerInterface|MockObject $handler */
- $handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
/** @var ResponseInterface|MockObject $response */
- $response = $this->getMockForAbstractClass(ResponseInterface::class);
+ /** @var MiddlewareInterface|MockObject $middlewareInterface */
+ list($container, $request, $handler, $response, $middlewareInterface) = $this->getMocks();
- $middlewareInterface = $this->getMockForAbstractClass(MiddlewareInterface::class);
$requestHandlerInterface = $this->getMockForAbstractClass(RequestHandlerInterface::class);
$request->expects($this->exactly(3))
@@ -57,10 +54,10 @@ class RequestHandlerTest extends TestCase
/** @var RequestHandler|MockObject $middleware */
$middleware = $this->getMockBuilder(RequestHandler::class)
->setConstructorArgs([$container])
- ->setMethods(['resolveMiddleware'])
+ ->setMethods(['resolveRequestHandler'])
->getMock();
$middleware->expects($this->exactly(3))
- ->method('resolveMiddleware')
+ ->method('resolveRequestHandler')
->with('FooBarClass')
->willReturnOnConsecutiveCalls(
$middlewareInterface,
@@ -86,4 +83,70 @@ class RequestHandlerTest extends TestCase
$this->expectException(InvalidArgumentException::class);
$middleware->process($request, $handler);
}
+
+ /**
+ * @covers \Engelsystem\Middleware\RequestHandler::resolveRequestHandler
+ */
+ public function testResolveRequestHandler()
+ {
+ /** @var Application|MockObject $container */
+ /** @var ServerRequestInterface|MockObject $request */
+ /** @var RequestHandlerInterface|MockObject $handler */
+ /** @var ResponseInterface|MockObject $response */
+ /** @var MiddlewareInterface|MockObject $middlewareInterface */
+ list($container, $request, $handler, $response, $middlewareInterface) = $this->getMocks();
+
+ $className = 'Engelsystem\\Controllers\\FooBarTestController';
+
+ $request->expects($this->exactly(1))
+ ->method('getAttribute')
+ ->with('route-request-handler')
+ ->willReturn('FooBarTestController@showStuff');
+
+ /** @var RequestHandler|MockObject $middleware */
+ $middleware = $this->getMockBuilder(RequestHandler::class)
+ ->setConstructorArgs([$container])
+ ->setMethods(['resolveMiddleware'])
+ ->getMock();
+ $middleware->expects($this->once())
+ ->method('resolveMiddleware')
+ ->with([$middlewareInterface, 'showStuff'])
+ ->willReturn($middlewareInterface);
+
+ $middlewareInterface->expects($this->once())
+ ->method('process')
+ ->with($request, $handler)
+ ->willReturn($response);
+
+ $container->expects($this->exactly(2))
+ ->method('has')
+ ->withConsecutive(['FooBarTestController'], [$className])
+ ->willReturnOnConsecutiveCalls(false, true);
+ $container->expects($this->once())
+ ->method('make')
+ ->with($className)
+ ->willReturn($middlewareInterface);
+
+ $return = $middleware->process($request, $handler);
+ $this->assertEquals($return, $response);
+ }
+
+ /**
+ * @return array
+ */
+ protected function getMocks(): array
+ {
+ /** @var Application|MockObject $container */
+ $container = $this->createMock(Application::class);
+ /** @var ServerRequestInterface|MockObject $request */
+ $request = $this->getMockForAbstractClass(ServerRequestInterface::class);
+ /** @var RequestHandlerInterface|MockObject $handler */
+ $handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
+ /** @var ResponseInterface|MockObject $response */
+ $response = $this->getMockForAbstractClass(ResponseInterface::class);
+ /** @var MiddlewareInterface $middlewareInterface */
+ $middlewareInterface = $this->getMockForAbstractClass(MiddlewareInterface::class);
+
+ return array($container, $request, $handler, $response, $middlewareInterface);
+ }
}