Merge remote-tracking branch 'MyIgel/rebuild-psr7'
This commit is contained in:
commit
36dafdb68a
|
@ -15,13 +15,20 @@
|
|||
],
|
||||
"require": {
|
||||
"php": ">=7.0.0",
|
||||
"ext-gettext": "*",
|
||||
"ext-json": "*",
|
||||
"ext-PDO": "*",
|
||||
"erusev/parsedown": "^1.6",
|
||||
"illuminate/container": "5.5.*",
|
||||
"illuminate/database": "5.5.*",
|
||||
"illuminate/support": "^5.5",
|
||||
"psr/container": "^1.0",
|
||||
"psr/http-server-middleware": "^1.0",
|
||||
"psr/log": "^1.0",
|
||||
"symfony/http-foundation": "^3.3"
|
||||
"symfony/http-foundation": "^3.3",
|
||||
"symfony/psr-http-message-bridge": "^1.0",
|
||||
"twbs/bootstrap": "^3.3",
|
||||
"zendframework/zend-diactoros": "^1.7"
|
||||
},
|
||||
"require-dev": {
|
||||
"filp/whoops": "^2.1",
|
||||
|
|
|
@ -13,5 +13,15 @@ return [
|
|||
\Engelsystem\Database\DatabaseServiceProvider::class,
|
||||
\Engelsystem\Http\RequestServiceProvider::class,
|
||||
\Engelsystem\Http\SessionServiceProvider::class,
|
||||
\Engelsystem\Http\ResponseServiceProvider::class,
|
||||
\Engelsystem\Http\Psr7ServiceProvider::class,
|
||||
],
|
||||
|
||||
// Application middleware
|
||||
'middleware' => [
|
||||
\Engelsystem\Middleware\SendResponseHandler::class,
|
||||
\Engelsystem\Middleware\ExceptionHandler::class,
|
||||
\Engelsystem\Middleware\LegacyMiddleware::class,
|
||||
\Engelsystem\Middleware\NotFoundResponse::class,
|
||||
],
|
||||
];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
FROM composer AS composer
|
||||
COPY composer.json /app/
|
||||
RUN composer --no-ansi install --no-dev
|
||||
RUN composer --no-ansi install --no-dev --ignore-platform-reqs
|
||||
RUN composer --no-ansi dump-autoload --optimize
|
||||
|
||||
FROM node:8-alpine as themes
|
||||
|
|
|
@ -73,8 +73,6 @@ function success($msg, $immediately = false)
|
|||
*/
|
||||
function alert($class, $msg, $immediately = false)
|
||||
{
|
||||
$session = session();
|
||||
|
||||
if (empty($msg)) {
|
||||
return '';
|
||||
}
|
||||
|
@ -83,6 +81,7 @@ function alert($class, $msg, $immediately = false)
|
|||
return '<div class="alert alert-' . $class . '">' . $msg . '</div>';
|
||||
}
|
||||
|
||||
$session = session();
|
||||
$message = $session->get('msg', '');
|
||||
$message .= alert($class, $msg, true);
|
||||
$session->set('msg', $message);
|
||||
|
|
Binary file not shown.
|
@ -2876,13 +2876,13 @@ msgstr ""
|
|||
"keine Nummer hast, bitte einfach \"-\" angeben."
|
||||
|
||||
#: /Users/msquare/workspace/projects/engelsystem/public/index.php:218
|
||||
msgid "No Access"
|
||||
msgstr "Kein Zugriff"
|
||||
msgid "Page not found"
|
||||
msgstr "Seite nicht gefunden"
|
||||
|
||||
#: /Users/msquare/workspace/projects/engelsystem/public/index.php:219
|
||||
msgid ""
|
||||
"You don't have permission to view this page . You probably have to sign in "
|
||||
"or register in order to gain access!"
|
||||
"This page could not be found or you don't have permission to view it. You "
|
||||
"probably have to sign in or register in order to gain access!"
|
||||
msgstr ""
|
||||
"Du hast keinen Zugriff auf diese Seite. Registriere Dich und logge Dich "
|
||||
"bitte ein, um Zugriff zu erhalten!"
|
||||
"Diese Seite existiert nicht oder Du hast keinen Zugriff. Melde Dich an um Zugriff "
|
||||
"zu erhalten!"
|
||||
|
|
250
public/index.php
250
public/index.php
|
@ -1,247 +1,19 @@
|
|||
<?php
|
||||
|
||||
use Engelsystem\Http\Request;
|
||||
use Engelsystem\Application;
|
||||
use Engelsystem\Middleware\Dispatcher;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
require_once realpath(__DIR__ . '/../includes/engelsystem.php');
|
||||
|
||||
$free_pages = [
|
||||
'admin_event_config',
|
||||
'angeltypes',
|
||||
'api',
|
||||
'atom',
|
||||
'credits',
|
||||
'ical',
|
||||
'login',
|
||||
'public_dashboard',
|
||||
'rooms',
|
||||
'shift_entries',
|
||||
'shifts',
|
||||
'shifts_json_export',
|
||||
'stats',
|
||||
'users',
|
||||
'user_driver_licenses',
|
||||
'user_password_recovery',
|
||||
'user_worklog'
|
||||
];
|
||||
/** @var Application $app */
|
||||
$app = app();
|
||||
|
||||
// Gewünschte Seite/Funktion
|
||||
$page = '';
|
||||
$title = '';
|
||||
$content = '';
|
||||
/** @var ServerRequestInterface $request */
|
||||
$request = $app->get('psr7.request');
|
||||
$middleware = $app->getMiddleware();
|
||||
|
||||
/** @var Request $request */
|
||||
$request = $app->get('request');
|
||||
$page = $request->query->get('p');
|
||||
if (empty($page)) {
|
||||
$page = $request->path();
|
||||
$page = str_replace('-', '_', $page);
|
||||
}
|
||||
if ($page == '/') {
|
||||
$page = isset($user) ? 'news' : 'login';
|
||||
}
|
||||
$dispatcher = new Dispatcher($middleware);
|
||||
$dispatcher->setContainer($app);
|
||||
|
||||
if (
|
||||
preg_match('/^\w*$/i', $page)
|
||||
&& (
|
||||
in_array($page, $free_pages)
|
||||
|| (isset($privileges) && in_array($page, $privileges))
|
||||
)
|
||||
) {
|
||||
$title = $page;
|
||||
|
||||
switch ($page) {
|
||||
case 'api':
|
||||
error('Api disabled temporarily.');
|
||||
redirect(page_link_to());
|
||||
break;
|
||||
case 'ical':
|
||||
require_once realpath(__DIR__ . '/../includes/pages/user_ical.php');
|
||||
user_ical();
|
||||
break;
|
||||
case 'atom':
|
||||
require_once realpath(__DIR__ . '/../includes/pages/user_atom.php');
|
||||
user_atom();
|
||||
break;
|
||||
case 'shifts_json_export':
|
||||
require_once realpath(__DIR__ . '/../includes/controller/shifts_controller.php');
|
||||
shifts_json_export_controller();
|
||||
break;
|
||||
case 'stats':
|
||||
require_once realpath(__DIR__ . '/../includes/pages/guest_stats.php');
|
||||
guest_stats();
|
||||
break;
|
||||
case 'user_password_recovery':
|
||||
require_once realpath(__DIR__ . '/../includes/controller/users_controller.php');
|
||||
$title = user_password_recovery_title();
|
||||
$content = user_password_recovery_controller();
|
||||
break;
|
||||
case 'public_dashboard':
|
||||
list($title, $content) = public_dashboard_controller();
|
||||
break;
|
||||
case 'angeltypes':
|
||||
list($title, $content) = angeltypes_controller();
|
||||
break;
|
||||
case 'shift_entries':
|
||||
list($title, $content) = shift_entries_controller();
|
||||
break;
|
||||
case 'shifts':
|
||||
list($title, $content) = shifts_controller();
|
||||
break;
|
||||
case 'users':
|
||||
list($title, $content) = users_controller();
|
||||
break;
|
||||
case 'user_angeltypes':
|
||||
list($title, $content) = user_angeltypes_controller();
|
||||
break;
|
||||
case 'user_driver_licenses':
|
||||
list($title, $content) = user_driver_licenses_controller();
|
||||
break;
|
||||
case 'shifttypes':
|
||||
list($title, $content) = shifttypes_controller();
|
||||
break;
|
||||
case 'admin_event_config':
|
||||
list($title, $content) = event_config_edit_controller();
|
||||
break;
|
||||
case 'rooms':
|
||||
list($title, $content) = rooms_controller();
|
||||
break;
|
||||
case 'news':
|
||||
$title = news_title();
|
||||
$content = user_news();
|
||||
break;
|
||||
case 'news_comments':
|
||||
require_once realpath(__DIR__ . '/../includes/pages/user_news.php');
|
||||
$title = user_news_comments_title();
|
||||
$content = user_news_comments();
|
||||
break;
|
||||
case 'user_meetings':
|
||||
$title = meetings_title();
|
||||
$content = user_meetings();
|
||||
break;
|
||||
case 'user_myshifts':
|
||||
$title = myshifts_title();
|
||||
$content = user_myshifts();
|
||||
break;
|
||||
case 'user_shifts':
|
||||
$title = shifts_title();
|
||||
$content = user_shifts();
|
||||
break;
|
||||
case 'user_worklog':
|
||||
list($title, $content) = user_worklog_controller();
|
||||
break;
|
||||
case 'user_messages':
|
||||
$title = messages_title();
|
||||
$content = user_messages();
|
||||
break;
|
||||
case 'user_questions':
|
||||
$title = questions_title();
|
||||
$content = user_questions();
|
||||
break;
|
||||
case 'user_settings':
|
||||
$title = settings_title();
|
||||
$content = user_settings();
|
||||
break;
|
||||
case 'login':
|
||||
$title = login_title();
|
||||
$content = guest_login();
|
||||
break;
|
||||
case 'register':
|
||||
$title = register_title();
|
||||
$content = guest_register();
|
||||
break;
|
||||
case 'logout':
|
||||
$title = logout_title();
|
||||
$content = guest_logout();
|
||||
break;
|
||||
case 'admin_questions':
|
||||
$title = admin_questions_title();
|
||||
$content = admin_questions();
|
||||
break;
|
||||
case 'admin_user':
|
||||
$title = admin_user_title();
|
||||
$content = admin_user();
|
||||
break;
|
||||
case 'admin_arrive':
|
||||
$title = admin_arrive_title();
|
||||
$content = admin_arrive();
|
||||
break;
|
||||
case 'admin_active':
|
||||
$title = admin_active_title();
|
||||
$content = admin_active();
|
||||
break;
|
||||
case 'admin_free':
|
||||
$title = admin_free_title();
|
||||
$content = admin_free();
|
||||
break;
|
||||
case 'admin_news':
|
||||
require_once realpath(__DIR__ . '/../includes/pages/admin_news.php');
|
||||
$content = admin_news();
|
||||
break;
|
||||
case 'admin_rooms':
|
||||
$title = admin_rooms_title();
|
||||
$content = admin_rooms();
|
||||
break;
|
||||
case 'admin_groups':
|
||||
$title = admin_groups_title();
|
||||
$content = admin_groups();
|
||||
break;
|
||||
case 'admin_import':
|
||||
$title = admin_import_title();
|
||||
$content = admin_import();
|
||||
break;
|
||||
case 'admin_shifts':
|
||||
$title = admin_shifts_title();
|
||||
$content = admin_shifts();
|
||||
break;
|
||||
case 'admin_log':
|
||||
$title = admin_log_title();
|
||||
$content = admin_log();
|
||||
break;
|
||||
case 'credits':
|
||||
require_once realpath(__DIR__ . '/../includes/pages/guest_credits.php');
|
||||
$title = credits_title();
|
||||
$content = guest_credits();
|
||||
break;
|
||||
default:
|
||||
require_once realpath(__DIR__ . '/../includes/pages/guest_start.php');
|
||||
$content = guest_start();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Wenn schon eingeloggt, keine-Berechtigung-Seite anzeigen
|
||||
if (isset($user)) {
|
||||
$title = _('No Access');
|
||||
$content = _('You don\'t have permission to view this page . You probably have to sign in or register in order to gain access!');
|
||||
} else {
|
||||
// Sonst zur Loginseite leiten
|
||||
redirect(page_link_to('login'));
|
||||
}
|
||||
}
|
||||
|
||||
$event_config = EventConfig();
|
||||
|
||||
$parameters = [
|
||||
'key' => (isset($user) ? $user['api_key'] : ''),
|
||||
];
|
||||
if ($page == 'user_meetings') {
|
||||
$parameters['meetings'] = 1;
|
||||
}
|
||||
|
||||
echo view(__DIR__ . '/../templates/layout.html', [
|
||||
'theme' => isset($user) ? $user['color'] : config('theme'),
|
||||
'title' => $title,
|
||||
'atom_link' => ($page == 'news' || $page == 'user_meetings')
|
||||
? ' <link href="'
|
||||
. page_link_to('atom', $parameters)
|
||||
. '" type = "application/atom+xml" rel = "alternate" title = "Atom Feed">'
|
||||
: '',
|
||||
'start_page_url' => page_link_to('/'),
|
||||
'credits_url' => page_link_to('credits'),
|
||||
'menu' => make_menu(),
|
||||
'content' => msg() . $content,
|
||||
'header_toolbar' => header_toolbar(),
|
||||
'faq_url' => config('faq_url'),
|
||||
'contact_email' => config('contact_email'),
|
||||
'locale' => locale_short(),
|
||||
'event_info' => EventConfig_info($event_config) . ' <br />'
|
||||
]);
|
||||
$dispatcher->handle($request);
|
||||
|
|
|
@ -7,6 +7,7 @@ use Engelsystem\Container\Container;
|
|||
use Engelsystem\Container\ServiceProvider;
|
||||
use Illuminate\Container\Container as IlluminateContainer;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
|
||||
class Application extends Container
|
||||
{
|
||||
|
@ -16,6 +17,9 @@ class Application extends Container
|
|||
/** @var bool */
|
||||
protected $isBootstrapped = false;
|
||||
|
||||
/** @var MiddlewareInterface[]|string[] */
|
||||
protected $middleware;
|
||||
|
||||
/**
|
||||
* Registered service providers
|
||||
*
|
||||
|
@ -85,6 +89,8 @@ class Application extends Container
|
|||
foreach ($config->get('providers', []) as $provider) {
|
||||
$this->register($provider);
|
||||
}
|
||||
|
||||
$this->middleware = $config->get('middleware', []);
|
||||
}
|
||||
|
||||
foreach ($this->serviceProviders as $provider) {
|
||||
|
@ -136,4 +142,12 @@ class Application extends Container
|
|||
{
|
||||
return $this->isBootstrapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MiddlewareInterface[]|string[]
|
||||
*/
|
||||
public function getMiddleware()
|
||||
{
|
||||
return $this->middleware;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,8 +54,10 @@ class Handler
|
|||
|
||||
/**
|
||||
* @param Throwable $e
|
||||
* @param bool $return
|
||||
* @return string
|
||||
*/
|
||||
public function exceptionHandler($e)
|
||||
public function exceptionHandler($e, $return = false)
|
||||
{
|
||||
if (!$this->request instanceof Request) {
|
||||
$this->request = new Request();
|
||||
|
@ -63,8 +65,21 @@ class Handler
|
|||
|
||||
$handler = $this->handler[$this->environment];
|
||||
$handler->report($e);
|
||||
ob_start();
|
||||
$handler->render($this->request, $e);
|
||||
|
||||
if ($return) {
|
||||
$output = ob_get_contents();
|
||||
ob_end_clean();
|
||||
return $output;
|
||||
}
|
||||
|
||||
http_response_code(500);
|
||||
ob_end_flush();
|
||||
|
||||
$this->terminateApplicationImmediately();
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,6 +34,8 @@ class Whoops extends Legacy implements HandlerInterface
|
|||
$whoops = $this->app->make(WhoopsRunner::class);
|
||||
$handler = $this->getPrettyPageHandler($e);
|
||||
$whoops->pushHandler($handler);
|
||||
$whoops->writeToOutput(false);
|
||||
$whoops->allowQuit(false);
|
||||
|
||||
if ($request->isXmlHttpRequest()) {
|
||||
$handler = $this->getJsonResponseHandler();
|
||||
|
|
|
@ -0,0 +1,248 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Http;
|
||||
|
||||
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Zend\Diactoros\Stream;
|
||||
|
||||
/**
|
||||
* @implements \Psr\Http\Message\MessageInterface
|
||||
* @extends \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
trait MessageTrait
|
||||
{
|
||||
/**
|
||||
* Retrieves the HTTP protocol version as a string.
|
||||
*
|
||||
* The string MUST contain only the HTTP version number (e.g., "1.1", "1.0").
|
||||
*
|
||||
* @return string HTTP protocol version.
|
||||
*/
|
||||
public function getProtocolVersion()
|
||||
{
|
||||
return parent::getProtocolVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified HTTP protocol version.
|
||||
*
|
||||
* The version string MUST contain only the HTTP version number (e.g.,
|
||||
* "1.1", "1.0").
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* new protocol version.
|
||||
*
|
||||
* @param string $version HTTP protocol version
|
||||
* @return static
|
||||
*/
|
||||
public function withProtocolVersion($version)
|
||||
{
|
||||
$new = clone $this;
|
||||
if (method_exists($new, 'setProtocolVersion')) {
|
||||
$new->setProtocolVersion($version);
|
||||
} else {
|
||||
$new->server->set('SERVER_PROTOCOL', $version);
|
||||
}
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all message header values.
|
||||
*
|
||||
* The keys represent the header name as it will be sent over the wire, and
|
||||
* each value is an array of strings associated with the header.
|
||||
*
|
||||
* // Represent the headers as a string
|
||||
* foreach ($message->getHeaders() as $name => $values) {
|
||||
* echo $name . ": " . implode(", ", $values);
|
||||
* }
|
||||
*
|
||||
* // Emit headers iteratively:
|
||||
* foreach ($message->getHeaders() as $name => $values) {
|
||||
* foreach ($values as $value) {
|
||||
* header(sprintf('%s: %s', $name, $value), false);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* While header names are not case-sensitive, getHeaders() will preserve the
|
||||
* exact case in which headers were originally specified.
|
||||
*
|
||||
* @return string[][] Returns an associative array of the message's headers. Each
|
||||
* key MUST be a header name, and each value MUST be an array of strings
|
||||
* for that header.
|
||||
*/
|
||||
public function getHeaders()
|
||||
{
|
||||
if (method_exists($this->headers, 'allPreserveCase')) {
|
||||
return $this->headers->allPreserveCase();
|
||||
}
|
||||
|
||||
return $this->headers->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a header exists by the given case-insensitive name.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name.
|
||||
* @return bool Returns true if any header names match the given header
|
||||
* name using a case-insensitive string comparison. Returns false if
|
||||
* no matching header name is found in the message.
|
||||
*/
|
||||
public function hasHeader($name)
|
||||
{
|
||||
return $this->headers->has($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a message header value by the given case-insensitive name.
|
||||
*
|
||||
* This method returns an array of all the header values of the given
|
||||
* case-insensitive header name.
|
||||
*
|
||||
* If the header does not appear in the message, this method MUST return an
|
||||
* empty array.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name.
|
||||
* @return string[] An array of string values as provided for the given
|
||||
* header. If the header does not appear in the message, this method MUST
|
||||
* return an empty array.
|
||||
*/
|
||||
public function getHeader($name)
|
||||
{
|
||||
return $this->headers->get($name, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a comma-separated string of the values for a single header.
|
||||
*
|
||||
* This method returns all of the header values of the given
|
||||
* case-insensitive header name as a string concatenated together using
|
||||
* a comma.
|
||||
*
|
||||
* NOTE: Not all header values may be appropriately represented using
|
||||
* comma concatenation. For such headers, use getHeader() instead
|
||||
* and supply your own delimiter when concatenating.
|
||||
*
|
||||
* If the header does not appear in the message, this method MUST return
|
||||
* an empty string.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name.
|
||||
* @return string A string of values as provided for the given header
|
||||
* concatenated together using a comma. If the header does not appear in
|
||||
* the message, this method MUST return an empty string.
|
||||
*/
|
||||
public function getHeaderLine($name)
|
||||
{
|
||||
return implode(',', $this->getHeader($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the provided value replacing the specified header.
|
||||
*
|
||||
* While header names are case-insensitive, the casing of the header will
|
||||
* be preserved by this function, and returned from getHeaders().
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* new and/or updated header and value.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name.
|
||||
* @param string|string[] $value Header value(s).
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException for invalid header names or values.
|
||||
*/
|
||||
public function withHeader($name, $value)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->headers->set($name, $value);
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified header appended with the given value.
|
||||
*
|
||||
* Existing values for the specified header will be maintained. The new
|
||||
* value(s) will be appended to the existing list. If the header did not
|
||||
* exist previously, it will be added.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* new header and/or value.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name to add.
|
||||
* @param string|string[] $value Header value(s).
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException for invalid header names or values.
|
||||
*/
|
||||
public function withAddedHeader($name, $value)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->headers->set($name, $value, false);
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance without the specified header.
|
||||
*
|
||||
* Header resolution MUST be done without case-sensitivity.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that removes
|
||||
* the named header.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name to remove.
|
||||
* @return static
|
||||
*/
|
||||
public function withoutHeader($name)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->headers->remove($name);
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the body of the message.
|
||||
*
|
||||
* @return StreamInterface Returns the body as a stream.
|
||||
*/
|
||||
public function getBody()
|
||||
{
|
||||
$stream = new Stream('php://memory', 'wb+');
|
||||
$stream->write($this->getContent());
|
||||
$stream->rewind();
|
||||
|
||||
return $stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified message body.
|
||||
*
|
||||
* The body MUST be a StreamInterface object.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return a new instance that has the
|
||||
* new body stream.
|
||||
*
|
||||
* @param StreamInterface $body Body.
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException When the body is not valid.
|
||||
*/
|
||||
public function withBody(StreamInterface $body)
|
||||
{
|
||||
$new = clone $this;
|
||||
|
||||
if (method_exists($new, 'setContent')) {
|
||||
$new->setContent($body);
|
||||
} else {
|
||||
$new->content = $body;
|
||||
}
|
||||
|
||||
return $new;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Http;
|
||||
|
||||
use Engelsystem\Container\ServiceProvider;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
|
||||
|
||||
|
||||
class Psr7ServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register()
|
||||
{
|
||||
/** @var DiactorosFactory $psr7Factory */
|
||||
$psr7Factory = $this->app->make(DiactorosFactory::class);
|
||||
$this->app->instance('psr7.factory', $psr7Factory);
|
||||
|
||||
/** @var Request $request */
|
||||
$request = $this->app->get('request');
|
||||
$this->app->instance('psr7.request', $request);
|
||||
$this->app->bind(ServerRequestInterface::class, 'psr7.request');
|
||||
|
||||
/** @var Response $response */
|
||||
$response = $this->app->get('response');
|
||||
$this->app->instance('psr7.response', $response);
|
||||
$this->app->bind(ResponseInterface::class, 'psr7.response');
|
||||
}
|
||||
}
|
|
@ -2,10 +2,18 @@
|
|||
|
||||
namespace Engelsystem\Http;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile as SymfonyFile;
|
||||
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
|
||||
use Zend\Diactoros\UploadedFile;
|
||||
use Zend\Diactoros\Uri;
|
||||
|
||||
class Request extends SymfonyRequest
|
||||
class Request extends SymfonyRequest implements ServerRequestInterface
|
||||
{
|
||||
use MessageTrait;
|
||||
|
||||
/**
|
||||
* Get POST input
|
||||
*
|
||||
|
@ -64,4 +72,441 @@ class Request extends SymfonyRequest
|
|||
{
|
||||
return rtrim(preg_replace('/\?.*/', '', $this->getUri()), '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the message's request target.
|
||||
*
|
||||
*
|
||||
* Retrieves the message's request-target either as it will appear (for
|
||||
* clients), as it appeared at request (for servers), or as it was
|
||||
* specified for the instance (see withRequestTarget()).
|
||||
*
|
||||
* In most cases, this will be the origin-form of the composed URI,
|
||||
* unless a value was provided to the concrete implementation (see
|
||||
* withRequestTarget() below).
|
||||
*
|
||||
* If no URI is available, and no request-target has been specifically
|
||||
* provided, this method MUST return the string "/".
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRequestTarget()
|
||||
{
|
||||
$query = $this->getQueryString();
|
||||
return '/' . $this->path() . (!empty($query) ? '?' . $query : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specific request-target.
|
||||
*
|
||||
* If the request needs a non-origin-form request-target — e.g., for
|
||||
* specifying an absolute-form, authority-form, or asterisk-form —
|
||||
* this method may be used to create an instance with the specified
|
||||
* request-target, verbatim.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* changed request target.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc7230#section-5.3 (for the various
|
||||
* request-target forms allowed in request messages)
|
||||
* @param mixed $requestTarget
|
||||
* @return static
|
||||
*/
|
||||
public function withRequestTarget($requestTarget)
|
||||
{
|
||||
return $this->create($requestTarget);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the provided HTTP method.
|
||||
*
|
||||
* While HTTP method names are typically all uppercase characters, HTTP
|
||||
* method names are case-sensitive and thus implementations SHOULD NOT
|
||||
* modify the given string.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* changed request method.
|
||||
*
|
||||
* @param string $method Case-sensitive method.
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException for invalid HTTP methods.
|
||||
*/
|
||||
public function withMethod($method)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->setMethod($method);
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance with the provided URI.
|
||||
*
|
||||
* This method MUST update the Host header of the returned request by
|
||||
* default if the URI contains a host component. If the URI does not
|
||||
* contain a host component, any pre-existing Host header MUST be carried
|
||||
* over to the returned request.
|
||||
*
|
||||
* You can opt-in to preserving the original state of the Host header by
|
||||
* setting `$preserveHost` to `true`. When `$preserveHost` is set to
|
||||
* `true`, this method interacts with the Host header in the following ways:
|
||||
*
|
||||
* - If the Host header is missing or empty, and the new URI contains
|
||||
* a host component, this method MUST update the Host header in the returned
|
||||
* request.
|
||||
* - If the Host header is missing or empty, and the new URI does not contain a
|
||||
* host component, this method MUST NOT update the Host header in the returned
|
||||
* request.
|
||||
* - If a Host header is present and non-empty, this method MUST NOT update
|
||||
* the Host header in the returned request.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* new UriInterface instance.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc3986#section-4.3
|
||||
* @param UriInterface $uri New request URI to use.
|
||||
* @param bool $preserveHost Preserve the original state of the Host header.
|
||||
* @return static
|
||||
*/
|
||||
public function withUri(UriInterface $uri, $preserveHost = false)
|
||||
{
|
||||
$new = $this->create($uri);
|
||||
if ($preserveHost) {
|
||||
$new->headers->set('HOST', $this->getHost());
|
||||
}
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the URI instance.
|
||||
*
|
||||
* This method MUST return a UriInterface instance.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc3986#section-4.3
|
||||
* @return string|UriInterface Returns a UriInterface instance
|
||||
* representing the URI of the request.
|
||||
*/
|
||||
public function getUri()
|
||||
{
|
||||
$uri = parent::getUri();
|
||||
|
||||
return new Uri($uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve server parameters.
|
||||
*
|
||||
* Retrieves data related to the incoming request environment,
|
||||
* typically derived from PHP's $_SERVER superglobal. The data IS NOT
|
||||
* REQUIRED to originate from $_SERVER.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getServerParams()
|
||||
{
|
||||
return $this->server->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve cookies.
|
||||
*
|
||||
* Retrieves cookies sent by the client to the server.
|
||||
*
|
||||
* The data MUST be compatible with the structure of the $_COOKIE
|
||||
* superglobal.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCookieParams()
|
||||
{
|
||||
return $this->cookies->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified cookies.
|
||||
*
|
||||
* The data IS NOT REQUIRED to come from the $_COOKIE superglobal, but MUST
|
||||
* be compatible with the structure of $_COOKIE. Typically, this data will
|
||||
* be injected at instantiation.
|
||||
*
|
||||
* This method MUST NOT update the related Cookie header of the request
|
||||
* instance, nor related values in the server params.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* updated cookie values.
|
||||
*
|
||||
* @param array $cookies Array of key/value pairs representing cookies.
|
||||
* @return static
|
||||
*/
|
||||
public function withCookieParams(array $cookies)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->cookies = clone $this->cookies;
|
||||
$new->cookies->replace($cookies);
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve query string arguments.
|
||||
*
|
||||
* Retrieves the deserialized query string arguments, if any.
|
||||
*
|
||||
* Note: the query params might not be in sync with the URI or server
|
||||
* params. If you need to ensure you are only getting the original
|
||||
* values, you may need to parse the query string from `getUri()->getQuery()`
|
||||
* or from the `QUERY_STRING` server param.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getQueryParams()
|
||||
{
|
||||
return $this->query->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified query string arguments.
|
||||
*
|
||||
* These values SHOULD remain immutable over the course of the incoming
|
||||
* request. They MAY be injected during instantiation, such as from PHP's
|
||||
* $_GET superglobal, or MAY be derived from some other value such as the
|
||||
* URI. In cases where the arguments are parsed from the URI, the data
|
||||
* MUST be compatible with what PHP's parse_str() would return for
|
||||
* purposes of how duplicate query parameters are handled, and how nested
|
||||
* sets are handled.
|
||||
*
|
||||
* Setting query string arguments MUST NOT change the URI stored by the
|
||||
* request, nor the values in the server params.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* updated query string arguments.
|
||||
*
|
||||
* @param array $query Array of query string arguments, typically from
|
||||
* $_GET.
|
||||
* @return static
|
||||
*/
|
||||
public function withQueryParams(array $query)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->query = clone $this->query;
|
||||
$new->query->replace($query);
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve normalized file upload data.
|
||||
*
|
||||
* This method returns upload metadata in a normalized tree, with each leaf
|
||||
* an instance of Psr\Http\Message\UploadedFileInterface.
|
||||
*
|
||||
* These values MAY be prepared from $_FILES or the message body during
|
||||
* instantiation, or MAY be injected via withUploadedFiles().
|
||||
*
|
||||
* @return array An array tree of UploadedFileInterface instances; an empty
|
||||
* array MUST be returned if no data is present.
|
||||
*/
|
||||
public function getUploadedFiles()
|
||||
{
|
||||
$files = [];
|
||||
foreach ($this->files as $file) {
|
||||
/** @var SymfonyFile $file */
|
||||
|
||||
$files[] = new UploadedFile(
|
||||
$file->getPath(),
|
||||
$file->getSize(),
|
||||
$file->getError(),
|
||||
$file->getClientOriginalName(),
|
||||
$file->getClientMimeType()
|
||||
);
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with the specified uploaded files.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* updated body parameters.
|
||||
*
|
||||
* @param array $uploadedFiles An array tree of UploadedFileInterface instances.
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException if an invalid structure is provided.
|
||||
*/
|
||||
public function withUploadedFiles(array $uploadedFiles)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->files = clone $this->files;
|
||||
|
||||
$files = [];
|
||||
foreach ($uploadedFiles as $file) {
|
||||
/** @var UploadedFileInterface $file */
|
||||
$filename = tempnam(sys_get_temp_dir(), 'upload');
|
||||
$handle = fopen($filename, "w");
|
||||
fwrite($handle, $file->getStream()->getContents());
|
||||
fclose($handle);
|
||||
|
||||
$files[] = new SymfonyFile(
|
||||
$filename,
|
||||
$file->getClientFilename(),
|
||||
$file->getClientMediaType(),
|
||||
$file->getSize(),
|
||||
$file->getError()
|
||||
);
|
||||
}
|
||||
$new->files->add($files);
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve any parameters provided in the request body.
|
||||
*
|
||||
* If the request Content-Type is either application/x-www-form-urlencoded
|
||||
* or multipart/form-data, and the request method is POST, this method MUST
|
||||
* return the contents of $_POST.
|
||||
*
|
||||
* Otherwise, this method may return any results of deserializing
|
||||
* the request body content; as parsing returns structured content, the
|
||||
* potential types MUST be arrays or objects only. A null value indicates
|
||||
* the absence of body content.
|
||||
*
|
||||
* @return null|array|object The deserialized body parameters, if any.
|
||||
* These will typically be an array or object.
|
||||
*/
|
||||
public function getParsedBody()
|
||||
{
|
||||
return $this->request->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified body parameters.
|
||||
*
|
||||
* These MAY be injected during instantiation.
|
||||
*
|
||||
* If the request Content-Type is either application/x-www-form-urlencoded
|
||||
* or multipart/form-data, and the request method is POST, use this method
|
||||
* ONLY to inject the contents of $_POST.
|
||||
*
|
||||
* The data IS NOT REQUIRED to come from $_POST, but MUST be the results of
|
||||
* deserializing the request body content. Deserialization/parsing returns
|
||||
* structured data, and, as such, this method ONLY accepts arrays or objects,
|
||||
* or a null value if nothing was available to parse.
|
||||
*
|
||||
* As an example, if content negotiation determines that the request data
|
||||
* is a JSON payload, this method could be used to create a request
|
||||
* instance with the deserialized parameters.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* updated body parameters.
|
||||
*
|
||||
* @param null|array|object $data The deserialized body data. This will
|
||||
* typically be in an array or object.
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException if an unsupported argument type is
|
||||
* provided.
|
||||
*/
|
||||
public function withParsedBody($data)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->request = clone $this->request;
|
||||
|
||||
$new->request->replace($data);
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve attributes derived from the request.
|
||||
*
|
||||
* The request "attributes" may be used to allow injection of any
|
||||
* parameters derived from the request: e.g., the results of path
|
||||
* match operations; the results of decrypting cookies; the results of
|
||||
* deserializing non-form-encoded message bodies; etc. Attributes
|
||||
* will be application and request specific, and CAN be mutable.
|
||||
*
|
||||
* @return array Attributes derived from the request.
|
||||
*/
|
||||
public function getAttributes()
|
||||
{
|
||||
return $this->attributes->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a single derived request attribute.
|
||||
*
|
||||
* Retrieves a single derived request attribute as described in
|
||||
* getAttributes(). If the attribute has not been previously set, returns
|
||||
* the default value as provided.
|
||||
*
|
||||
* This method obviates the need for a hasAttribute() method, as it allows
|
||||
* specifying a default value to return if the attribute is not found.
|
||||
*
|
||||
* @see getAttributes()
|
||||
* @param string $name The attribute name.
|
||||
* @param mixed $default Default value to return if the attribute does not exist.
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAttribute($name, $default = null)
|
||||
{
|
||||
return $this->attributes->get($name, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified derived request attribute.
|
||||
*
|
||||
* This method allows setting a single derived request attribute as
|
||||
* described in getAttributes().
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* updated attribute.
|
||||
*
|
||||
* @see getAttributes()
|
||||
* @param string $name The attribute name.
|
||||
* @param mixed $value The value of the attribute.
|
||||
* @return static
|
||||
*/
|
||||
public function withAttribute($name, $value)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->attributes = clone $this->attributes;
|
||||
|
||||
$new->attributes->set($name, $value);
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance that removes the specified derived request attribute.
|
||||
*
|
||||
* This method allows removing a single derived request attribute as
|
||||
* described in getAttributes().
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that removes
|
||||
* the attribute.
|
||||
*
|
||||
* @see getAttributes()
|
||||
* @param string $name The attribute name.
|
||||
* @return static
|
||||
*/
|
||||
public function withoutAttribute($name)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->attributes = clone $this->attributes;
|
||||
|
||||
$new->attributes->remove($name);
|
||||
|
||||
return $new;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Http;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
|
||||
|
||||
class Response extends SymfonyResponse implements ResponseInterface
|
||||
{
|
||||
use MessageTrait;
|
||||
|
||||
/**
|
||||
* Return an instance with the specified status code and, optionally, reason phrase.
|
||||
*
|
||||
* If no reason phrase is specified, implementations MAY choose to default
|
||||
* to the RFC 7231 or IANA recommended reason phrase for the response's
|
||||
* status code.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* updated status and reason phrase.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc7231#section-6
|
||||
* @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||
* @param int $code The 3-digit integer result code to set.
|
||||
* @param string $reasonPhrase The reason phrase to use with the
|
||||
* provided status code; if none is provided, implementations MAY
|
||||
* use the defaults as suggested in the HTTP specification.
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException For invalid status code arguments.
|
||||
*/
|
||||
public function withStatus($code, $reasonPhrase = '')
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->setStatusCode($code, !empty($reasonPhrase) ? $reasonPhrase : null);
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the response reason phrase associated with the status code.
|
||||
*
|
||||
* Because a reason phrase is not a required element in a response
|
||||
* status line, the reason phrase value MAY be null. Implementations MAY
|
||||
* choose to return the default RFC 7231 recommended reason phrase (or those
|
||||
* listed in the IANA HTTP Status Code Registry) for the response's
|
||||
* status code.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc7231#section-6
|
||||
* @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||
* @return string Reason phrase; must return an empty string if none present.
|
||||
*/
|
||||
public function getReasonPhrase()
|
||||
{
|
||||
return $this->statusText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified content.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* updated status and reason phrase.
|
||||
*
|
||||
* @param mixed $content Content that can be cast to string
|
||||
* @return static
|
||||
*/
|
||||
public function withContent($content)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->setContent($content);
|
||||
|
||||
return $new;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Http;
|
||||
|
||||
use Engelsystem\Container\ServiceProvider;
|
||||
|
||||
class ResponseServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register()
|
||||
{
|
||||
$response = $this->app->make(Response::class);
|
||||
$this->app->instance('response', $response);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Middleware;
|
||||
|
||||
use Engelsystem\Application;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class Dispatcher implements MiddlewareInterface, RequestHandlerInterface
|
||||
{
|
||||
/** @var MiddlewareInterface[]|string[] */
|
||||
protected $stack;
|
||||
|
||||
/** @var Application */
|
||||
protected $container;
|
||||
|
||||
/** @var RequestHandlerInterface */
|
||||
protected $next;
|
||||
|
||||
/**
|
||||
* @param MiddlewareInterface[]|string[] $stack
|
||||
* @param Application|null $container
|
||||
*/
|
||||
public function __construct($stack = [], Application $container = null)
|
||||
{
|
||||
$this->stack = $stack;
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* response creation to a handler.
|
||||
*
|
||||
* Could be used to group middleware
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @param RequestHandlerInterface $handler
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function process(
|
||||
ServerRequestInterface $request,
|
||||
RequestHandlerInterface $handler
|
||||
): ResponseInterface {
|
||||
$this->next = $handler;
|
||||
|
||||
return $this->handle($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the request and return a response.
|
||||
*
|
||||
* It calls all configured middleware and handles their response
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$middleware = array_shift($this->stack);
|
||||
|
||||
if (!$middleware) {
|
||||
if ($this->next) {
|
||||
return $this->next->handle($request);
|
||||
}
|
||||
|
||||
throw new LogicException('Middleware queue is empty');
|
||||
}
|
||||
|
||||
if (is_string($middleware)) {
|
||||
$middleware = $this->resolveMiddleware($middleware);
|
||||
}
|
||||
|
||||
if (!$middleware instanceof MiddlewareInterface) {
|
||||
throw new InvalidArgumentException('Middleware is no instance of ' . MiddlewareInterface::class);
|
||||
}
|
||||
|
||||
return $middleware->process($request, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the middleware with the container
|
||||
*
|
||||
* @param string $middleware
|
||||
* @return MiddlewareInterface
|
||||
*/
|
||||
protected function resolveMiddleware($middleware)
|
||||
{
|
||||
if (!$this->container instanceof Application) {
|
||||
throw new InvalidArgumentException('Unable to resolve middleware ' . $middleware);
|
||||
}
|
||||
|
||||
if ($this->container->has($middleware)) {
|
||||
return $this->container->get($middleware);
|
||||
}
|
||||
|
||||
return $this->container->make($middleware);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Application $container
|
||||
*/
|
||||
public function setContainer(Application $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Middleware;
|
||||
|
||||
use Engelsystem\Exceptions\Handler as ExceptionsHandler;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class ExceptionHandler implements MiddlewareInterface
|
||||
{
|
||||
/** @var ContainerInterface */
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*/
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles any exceptions that occurred inside other middleware while returning it to the default response handler
|
||||
*
|
||||
* Should be added at the beginning
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @param RequestHandlerInterface $handler
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function process(
|
||||
ServerRequestInterface $request,
|
||||
RequestHandlerInterface $handler
|
||||
): ResponseInterface {
|
||||
try {
|
||||
return $handler->handle($request);
|
||||
} catch (\Throwable $e) {
|
||||
/** @var ExceptionsHandler $handler */
|
||||
$handler = $this->container->get('error.handler');
|
||||
$content = $handler->exceptionHandler($e, true);
|
||||
|
||||
return response($content, 500);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,296 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Middleware;
|
||||
|
||||
use Engelsystem\Http\Request;
|
||||
use Engelsystem\Http\Response;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class LegacyMiddleware implements MiddlewareInterface
|
||||
{
|
||||
protected $free_pages = [
|
||||
'admin_event_config',
|
||||
'angeltypes',
|
||||
'api',
|
||||
'atom',
|
||||
'credits',
|
||||
'ical',
|
||||
'login',
|
||||
'public_dashboard',
|
||||
'rooms',
|
||||
'shift_entries',
|
||||
'shifts',
|
||||
'shifts_json_export',
|
||||
'shifts_json_export_all',
|
||||
'stats',
|
||||
'users',
|
||||
'user_driver_licenses',
|
||||
'user_password_recovery',
|
||||
'user_worklog'
|
||||
];
|
||||
|
||||
/** @var ContainerInterface */
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*/
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the request the old way
|
||||
*
|
||||
* Should be used before a 404 is send
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @param RequestHandlerInterface $handler
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function process(
|
||||
ServerRequestInterface $request,
|
||||
RequestHandlerInterface $handler
|
||||
): ResponseInterface {
|
||||
global $user;
|
||||
global $privileges;
|
||||
|
||||
/** @var Request $appRequest */
|
||||
$appRequest = $this->container->get('request');
|
||||
$page = $appRequest->query->get('p');
|
||||
if (empty($page)) {
|
||||
$page = $appRequest->path();
|
||||
$page = str_replace('-', '_', $page);
|
||||
}
|
||||
if ($page == '/') {
|
||||
$page = isset($user) ? 'news' : 'login';
|
||||
}
|
||||
|
||||
$title = $content = '';
|
||||
if (
|
||||
preg_match('~^\w+$~i', $page)
|
||||
&& (
|
||||
in_array($page, $this->free_pages)
|
||||
|| (isset($privileges) && in_array($page, $privileges))
|
||||
)
|
||||
) {
|
||||
list($title, $content) = $this->loadPage($page);
|
||||
}
|
||||
|
||||
if (empty($title) and empty($content)) {
|
||||
return $handler->handle($request);
|
||||
}
|
||||
|
||||
return $this->renderPage($page, $title, $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the legacy page content and title
|
||||
*
|
||||
* @param string $page
|
||||
* @return array ['title', 'content']
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function loadPage($page)
|
||||
{
|
||||
$title = ucfirst($page);
|
||||
switch ($page) {
|
||||
/** @noinspection PhpMissingBreakStatementInspection */
|
||||
case 'api':
|
||||
error('Api disabled temporarily.');
|
||||
redirect(page_link_to());
|
||||
/** @noinspection PhpMissingBreakStatementInspection */
|
||||
case 'ical':
|
||||
require_once realpath(__DIR__ . '/../../includes/pages/user_ical.php');
|
||||
user_ical();
|
||||
/** @noinspection PhpMissingBreakStatementInspection */
|
||||
case 'atom':
|
||||
require_once realpath(__DIR__ . '/../../includes/pages/user_atom.php');
|
||||
user_atom();
|
||||
/** @noinspection PhpMissingBreakStatementInspection */
|
||||
case 'shifts_json_export':
|
||||
require_once realpath(__DIR__ . '/../../includes/controller/shifts_controller.php');
|
||||
shifts_json_export_controller();
|
||||
/** @noinspection PhpMissingBreakStatementInspection */
|
||||
case 'shifts_json_export_all':
|
||||
require_once realpath(__DIR__ . '/../../includes/controller/shifts_controller.php');
|
||||
shifts_json_export_all_controller();
|
||||
/** @noinspection PhpMissingBreakStatementInspection */
|
||||
case 'stats':
|
||||
require_once realpath(__DIR__ . '/../../includes/pages/guest_stats.php');
|
||||
guest_stats();
|
||||
case 'user_password_recovery':
|
||||
require_once realpath(__DIR__ . '/../../includes/controller/users_controller.php');
|
||||
$title = user_password_recovery_title();
|
||||
$content = user_password_recovery_controller();
|
||||
return [$title, $content];
|
||||
case 'public_dashboard':
|
||||
return public_dashboard_controller();
|
||||
case 'angeltypes':
|
||||
return angeltypes_controller();
|
||||
case 'shift_entries':
|
||||
return shift_entries_controller();
|
||||
case 'shifts':
|
||||
return shifts_controller();
|
||||
case 'users':
|
||||
return users_controller();
|
||||
case 'user_angeltypes':
|
||||
return user_angeltypes_controller();
|
||||
case 'user_driver_licenses':
|
||||
return user_driver_licenses_controller();
|
||||
case 'shifttypes':
|
||||
list($title, $content) = shifttypes_controller();
|
||||
return [$title, $content];
|
||||
case 'admin_event_config':
|
||||
list($title, $content) = event_config_edit_controller();
|
||||
return [$title, $content];
|
||||
case 'rooms':
|
||||
return rooms_controller();
|
||||
case 'news':
|
||||
$title = news_title();
|
||||
$content = user_news();
|
||||
return [$title, $content];
|
||||
case 'news_comments':
|
||||
require_once realpath(__DIR__ . '/../../includes/pages/user_news.php');
|
||||
$title = user_news_comments_title();
|
||||
$content = user_news_comments();
|
||||
return [$title, $content];
|
||||
case 'user_meetings':
|
||||
$title = meetings_title();
|
||||
$content = user_meetings();
|
||||
return [$title, $content];
|
||||
case 'user_myshifts':
|
||||
$title = myshifts_title();
|
||||
$content = user_myshifts();
|
||||
return [$title, $content];
|
||||
case 'user_shifts':
|
||||
$title = shifts_title();
|
||||
$content = user_shifts();
|
||||
return [$title, $content];
|
||||
case 'user_worklog':
|
||||
return user_worklog_controller();
|
||||
case 'user_messages':
|
||||
$title = messages_title();
|
||||
$content = user_messages();
|
||||
return [$title, $content];
|
||||
case 'user_questions':
|
||||
$title = questions_title();
|
||||
$content = user_questions();
|
||||
return [$title, $content];
|
||||
case 'user_settings':
|
||||
$title = settings_title();
|
||||
$content = user_settings();
|
||||
return [$title, $content];
|
||||
case 'login':
|
||||
$title = login_title();
|
||||
$content = guest_login();
|
||||
return [$title, $content];
|
||||
case 'register':
|
||||
$title = register_title();
|
||||
$content = guest_register();
|
||||
return [$title, $content];
|
||||
case 'logout':
|
||||
$title = logout_title();
|
||||
$content = guest_logout();
|
||||
return [$title, $content];
|
||||
case 'admin_questions':
|
||||
$title = admin_questions_title();
|
||||
$content = admin_questions();
|
||||
return [$title, $content];
|
||||
case 'admin_user':
|
||||
$title = admin_user_title();
|
||||
$content = admin_user();
|
||||
return [$title, $content];
|
||||
case 'admin_arrive':
|
||||
$title = admin_arrive_title();
|
||||
$content = admin_arrive();
|
||||
return [$title, $content];
|
||||
case 'admin_active':
|
||||
$title = admin_active_title();
|
||||
$content = admin_active();
|
||||
return [$title, $content];
|
||||
case 'admin_free':
|
||||
$title = admin_free_title();
|
||||
$content = admin_free();
|
||||
return [$title, $content];
|
||||
case 'admin_news':
|
||||
require_once realpath(__DIR__ . '/../../includes/pages/admin_news.php');
|
||||
$content = admin_news();
|
||||
return [$title, $content];
|
||||
case 'admin_rooms':
|
||||
$title = admin_rooms_title();
|
||||
$content = admin_rooms();
|
||||
return [$title, $content];
|
||||
case 'admin_groups':
|
||||
$title = admin_groups_title();
|
||||
$content = admin_groups();
|
||||
return [$title, $content];
|
||||
case 'admin_import':
|
||||
$title = admin_import_title();
|
||||
$content = admin_import();
|
||||
return [$title, $content];
|
||||
case 'admin_shifts':
|
||||
$title = admin_shifts_title();
|
||||
$content = admin_shifts();
|
||||
return [$title, $content];
|
||||
case 'admin_log':
|
||||
$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');
|
||||
$content = guest_start();
|
||||
return [$title, $content];
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the template
|
||||
*
|
||||
* @param string $page
|
||||
* @param string $title
|
||||
* @param string $content
|
||||
* @return Response
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function renderPage($page, $title, $content)
|
||||
{
|
||||
global $user;
|
||||
$event_config = EventConfig();
|
||||
$parameters = [
|
||||
'key' => (isset($user) ? $user['api_key'] : ''),
|
||||
];
|
||||
if ($page == 'user_meetings') {
|
||||
$parameters['meetings'] = 1;
|
||||
}
|
||||
|
||||
return response(view(__DIR__ . '/../../templates/layout.html', [
|
||||
'theme' => isset($user) ? $user['color'] : config('theme'),
|
||||
'title' => $title,
|
||||
'atom_link' => ($page == 'news' || $page == 'user_meetings')
|
||||
? ' <link href="'
|
||||
. page_link_to('atom', $parameters)
|
||||
. '" type = "application/atom+xml" rel = "alternate" title = "Atom Feed">'
|
||||
: '',
|
||||
'start_page_url' => page_link_to('/'),
|
||||
'credits_url' => page_link_to('credits'),
|
||||
'menu' => make_menu(),
|
||||
'content' => msg() . $content,
|
||||
'header_toolbar' => header_toolbar(),
|
||||
'faq_url' => config('faq_url'),
|
||||
'contact_email' => config('contact_email'),
|
||||
'locale' => locale(),
|
||||
'event_info' => EventConfig_info($event_config) . ' <br />'
|
||||
]));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Middleware;
|
||||
|
||||
use Engelsystem\Http\Response;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class NotFoundResponse implements MiddlewareInterface
|
||||
{
|
||||
/**
|
||||
* Returns a 404: Page not found response
|
||||
*
|
||||
* Should be the last middleware
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @param RequestHandlerInterface $handler
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function process(
|
||||
ServerRequestInterface $request,
|
||||
RequestHandlerInterface $handler
|
||||
): ResponseInterface {
|
||||
$info = _('This page could not be found or you don\'t have permission to view it. You probably have to sign in or register in order to gain access!');
|
||||
|
||||
return $this->renderPage($info);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return Response
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function renderPage($content)
|
||||
{
|
||||
global $user;
|
||||
$event_config = EventConfig();
|
||||
|
||||
return response(view(__DIR__ . '/../../templates/layout.html', [
|
||||
'theme' => isset($user) ? $user['color'] : config('theme'),
|
||||
'title' => _('Page not found'),
|
||||
'atom_link' => '',
|
||||
'start_page_url' => page_link_to('/'),
|
||||
'credits_url' => page_link_to('credits'),
|
||||
'menu' => make_menu(),
|
||||
'content' => msg() . info($content),
|
||||
'header_toolbar' => header_toolbar(),
|
||||
'faq_url' => config('faq_url'),
|
||||
'contact_email' => config('contact_email'),
|
||||
'locale' => locale(),
|
||||
'event_info' => EventConfig_info($event_config) . ' <br />'
|
||||
]), 404);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Middleware;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class SendResponseHandler implements MiddlewareInterface
|
||||
{
|
||||
/**
|
||||
* Send the server response to the client
|
||||
*
|
||||
* This should be the first middleware
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @param RequestHandlerInterface $handler
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function process(
|
||||
ServerRequestInterface $request,
|
||||
RequestHandlerInterface $handler
|
||||
): ResponseInterface {
|
||||
$response = $handler->handle($request);
|
||||
|
||||
if (!$this->headersSent()) {
|
||||
$this->sendHeader(sprintf(
|
||||
'HTTP/%s %s %s',
|
||||
$response->getProtocolVersion(),
|
||||
$response->getStatusCode(),
|
||||
$response->getReasonPhrase()
|
||||
), true, $response->getStatusCode());
|
||||
|
||||
foreach ($response->getHeaders() as $name => $values) {
|
||||
foreach ($values as $value) {
|
||||
$this->sendHeader($name . ': ' . $value, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo $response->getBody();
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if headers have been sent
|
||||
*
|
||||
* @return bool
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function headersSent()
|
||||
{
|
||||
return headers_sent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a raw HTTP header
|
||||
*
|
||||
* @param string $content
|
||||
* @param bool $replace
|
||||
* @param int $code
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function sendHeader($content, $replace = true, $code = null)
|
||||
{
|
||||
header($content, $replace, $code);
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
use Engelsystem\Application;
|
||||
use Engelsystem\Config\Config;
|
||||
use Engelsystem\Http\Request;
|
||||
use Engelsystem\Http\Response;
|
||||
use Engelsystem\Renderer\Renderer;
|
||||
use Engelsystem\Routing\UrlGeneratorInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
|
@ -12,7 +13,7 @@ use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
|||
* Get the global app instance
|
||||
*
|
||||
* @param string $id
|
||||
* @return mixed
|
||||
* @return mixed|Application
|
||||
*/
|
||||
function app($instance_id = null)
|
||||
{
|
||||
|
@ -80,6 +81,27 @@ function request($key = null, $default = null)
|
|||
return $request->input($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return Response
|
||||
*/
|
||||
function response($content = '', $status = 200, $headers = [])
|
||||
{
|
||||
/** @var Response $response */
|
||||
$response = app('psr7.response');
|
||||
$response = $response
|
||||
->withContent($content)
|
||||
->withStatus($status);
|
||||
|
||||
foreach ($headers as $key => $value) {
|
||||
$response = $response->withAddedHeader($key, $value);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Feature;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
abstract class ApplicationFeatureTest extends TestCase
|
||||
{
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
$_SERVER['HTTP_HOST'] = 'foo.bar';
|
||||
require_once __DIR__ . '/../../includes/engelsystem.php';
|
||||
}
|
||||
}
|
|
@ -3,18 +3,13 @@
|
|||
namespace Engelsystem\Test\Feature\Logger;
|
||||
|
||||
use Engelsystem\Logger\EngelsystemLogger;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Engelsystem\Test\Feature\ApplicationFeatureTest;
|
||||
use Psr\Log\InvalidArgumentException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
class EngelsystemLoggerTest extends TestCase
|
||||
class EngelsystemLoggerTest extends ApplicationFeatureTest
|
||||
{
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
require_once __DIR__ . '/../../../includes/engelsystem.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LoggerInterface
|
||||
*/
|
||||
|
|
|
@ -2,16 +2,11 @@
|
|||
|
||||
namespace Engelsystem\Test\Feature\Model;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Engelsystem\Test\Feature\ApplicationFeatureTest;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
class LogEntriesModelTest extends TestCase
|
||||
class LogEntriesModelTest extends ApplicationFeatureTest
|
||||
{
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
require_once __DIR__ . '/../../../includes/engelsystem.php';
|
||||
}
|
||||
|
||||
public function testCreateLogEntry()
|
||||
{
|
||||
LogEntries_clear_all();
|
||||
|
|
|
@ -8,11 +8,6 @@ class RoomModelTest extends TestCase
|
|||
{
|
||||
private $room_id = null;
|
||||
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
require_once __DIR__ . '/../../../includes/engelsystem.php';
|
||||
}
|
||||
|
||||
public function createRoom()
|
||||
{
|
||||
$this->room_id = Room_create('test', false, null, null);
|
||||
|
|
|
@ -9,6 +9,7 @@ use Engelsystem\Container\ServiceProvider;
|
|||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit_Framework_MockObject_MockObject;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use ReflectionClass;
|
||||
|
||||
class ApplicationTest extends TestCase
|
||||
|
@ -118,6 +119,7 @@ class ApplicationTest extends TestCase
|
|||
/**
|
||||
* @covers \Engelsystem\Application::bootstrap
|
||||
* @covers \Engelsystem\Application::isBooted
|
||||
* @covers \Engelsystem\Application::getMiddleware
|
||||
*/
|
||||
public function testBootstrap()
|
||||
{
|
||||
|
@ -137,10 +139,11 @@ class ApplicationTest extends TestCase
|
|||
$config = $this->getMockBuilder(Config::class)
|
||||
->getMock();
|
||||
|
||||
$config->expects($this->once())
|
||||
$middleware = [MiddlewareInterface::class];
|
||||
$config->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->with('providers')
|
||||
->willReturn([$serviceProvider]);
|
||||
->withConsecutive(['providers'], ['middleware'])
|
||||
->willReturnOnConsecutiveCalls([$serviceProvider], $middleware);
|
||||
|
||||
$property = (new ReflectionClass($app))->getProperty('serviceProviders');
|
||||
$property->setAccessible(true);
|
||||
|
@ -149,6 +152,7 @@ class ApplicationTest extends TestCase
|
|||
$app->bootstrap($config);
|
||||
|
||||
$this->assertTrue($app->isBooted());
|
||||
$this->assertEquals($middleware, $app->getMiddleware());
|
||||
|
||||
// Run bootstrap another time to ensure that providers are registered only once
|
||||
$app->bootstrap($config);
|
||||
|
|
|
@ -49,15 +49,19 @@ class HandlerTest extends TestCase
|
|||
public function testExceptionHandler()
|
||||
{
|
||||
$exception = new Exception();
|
||||
$errorMessage = 'Oh noes, an error!';
|
||||
|
||||
/** @var HandlerInterface|Mock $handlerMock */
|
||||
$handlerMock = $this->getMockForAbstractClass(HandlerInterface::class);
|
||||
$handlerMock->expects($this->once())
|
||||
$handlerMock->expects($this->atLeastOnce())
|
||||
->method('report')
|
||||
->with($exception);
|
||||
$handlerMock->expects($this->once())
|
||||
$handlerMock->expects($this->atLeastOnce())
|
||||
->method('render')
|
||||
->with($this->isInstanceOf(Request::class), $exception);
|
||||
->with($this->isInstanceOf(Request::class), $exception)
|
||||
->willReturnCallback(function () use ($errorMessage) {
|
||||
echo $errorMessage;
|
||||
});
|
||||
|
||||
/** @var Handler|Mock $handler */
|
||||
$handler = $this->getMockBuilder(Handler::class)
|
||||
|
@ -68,7 +72,11 @@ class HandlerTest extends TestCase
|
|||
|
||||
$handler->setHandler(Handler::ENV_PRODUCTION, $handlerMock);
|
||||
|
||||
$this->expectOutputString($errorMessage);
|
||||
$handler->exceptionHandler($exception);
|
||||
|
||||
$return = $handler->exceptionHandler($exception, true);
|
||||
$this->assertEquals($errorMessage, $return);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -72,6 +72,14 @@ class WhoopsTest extends TestCase
|
|||
[$prettyPageHandler],
|
||||
[$jsonResponseHandler]
|
||||
);
|
||||
$whoopsRunner
|
||||
->expects($this->once())
|
||||
->method('writeToOutput')
|
||||
->with(false);
|
||||
$whoopsRunner
|
||||
->expects($this->once())
|
||||
->method('allowQuit')
|
||||
->with(false);
|
||||
$whoopsRunner
|
||||
->expects($this->once())
|
||||
->method('handleException')
|
||||
|
|
|
@ -6,6 +6,7 @@ use Engelsystem\Application;
|
|||
use Engelsystem\Config\Config;
|
||||
use Engelsystem\Container\Container;
|
||||
use Engelsystem\Http\Request;
|
||||
use Engelsystem\Http\Response;
|
||||
use Engelsystem\Renderer\Renderer;
|
||||
use Engelsystem\Routing\UrlGeneratorInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
@ -126,6 +127,33 @@ class HelpersTest extends TestCase
|
|||
$this->assertEquals('requestValue', request('requestKey'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \response
|
||||
*/
|
||||
public function testResponse()
|
||||
{
|
||||
/** @var MockObject|Response $response */
|
||||
$response = $this->getMockBuilder(Response::class)->getMock();
|
||||
$this->getAppMock('psr7.response', $response);
|
||||
|
||||
$response->expects($this->once())
|
||||
->method('withContent')
|
||||
->with('Lorem Ipsum?')
|
||||
->willReturn($response);
|
||||
|
||||
$response->expects($this->once())
|
||||
->method('withStatus')
|
||||
->with(501)
|
||||
->willReturn($response);
|
||||
|
||||
$response->expects($this->exactly(2))
|
||||
->method('withAddedHeader')
|
||||
->withConsecutive(['lor', 'em'], ['foo', 'bar'])
|
||||
->willReturn($response);
|
||||
|
||||
$this->assertEquals($response, response('Lorem Ipsum?', 501, ['lor' => 'em', 'foo' => 'bar',]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \session
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Http;
|
||||
|
||||
use Engelsystem\Test\Unit\Http\Stub\MessageTraitRequestImplementation;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Zend\Diactoros\Stream;
|
||||
|
||||
class MessageTraitRequestTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Http\MessageTrait::withProtocolVersion
|
||||
*/
|
||||
public function testWithProtocolVersion()
|
||||
{
|
||||
$message = new MessageTraitRequestImplementation();
|
||||
$newMessage = $message->withProtocolVersion('0.1');
|
||||
$this->assertNotEquals($message, $newMessage);
|
||||
$this->assertEquals('0.1', $newMessage->getProtocolVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\MessageTrait::getHeaders
|
||||
*/
|
||||
public function testGetHeaders()
|
||||
{
|
||||
$message = new MessageTraitRequestImplementation();
|
||||
$newMessage = $message->withHeader('lorem', 'ipsum');
|
||||
|
||||
$this->assertNotEquals($message, $newMessage);
|
||||
$this->assertArraySubset(['lorem' => ['ipsum']], $newMessage->getHeaders());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\MessageTrait::withBody
|
||||
*/
|
||||
public function testWithBody()
|
||||
{
|
||||
/** @var Stream $stream */
|
||||
$stream = new Stream('php://memory', 'wb+');
|
||||
$stream->write('Test content');
|
||||
$stream->rewind();
|
||||
|
||||
$message = new MessageTraitRequestImplementation();
|
||||
$newMessage = $message->withBody($stream);
|
||||
|
||||
$this->assertNotEquals($message, $newMessage);
|
||||
$this->assertEquals('Test content', $newMessage->getContent());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Http;
|
||||
|
||||
use Engelsystem\Test\Unit\Http\Stub\MessageTraitResponseImplementation;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Http\Message\MessageInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
|
||||
use Zend\Diactoros\Stream;
|
||||
|
||||
class MessageTraitResponseTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Http\MessageTrait
|
||||
*/
|
||||
public function testCreate()
|
||||
{
|
||||
$message = new MessageTraitResponseImplementation();
|
||||
$this->assertInstanceOf(MessageInterface::class, $message);
|
||||
$this->assertInstanceOf(SymfonyResponse::class, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\MessageTrait::getProtocolVersion
|
||||
* @covers \Engelsystem\Http\MessageTrait::withProtocolVersion
|
||||
*/
|
||||
public function testGetProtocolVersion()
|
||||
{
|
||||
$message = new MessageTraitResponseImplementation();
|
||||
$newMessage = $message->withProtocolVersion('0.1');
|
||||
$this->assertNotEquals($message, $newMessage);
|
||||
$this->assertEquals('0.1', $newMessage->getProtocolVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\MessageTrait::getHeaders
|
||||
*/
|
||||
public function testGetHeaders()
|
||||
{
|
||||
$message = new MessageTraitResponseImplementation();
|
||||
$newMessage = $message->withHeader('Foo', 'bar');
|
||||
|
||||
$this->assertNotEquals($message, $newMessage);
|
||||
$this->assertArraySubset(['Foo' => ['bar']], $newMessage->getHeaders());
|
||||
|
||||
$newMessage = $message->withHeader('lorem', ['ipsum', 'dolor']);
|
||||
$this->assertArraySubset(['lorem' => ['ipsum', 'dolor']], $newMessage->getHeaders());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\MessageTrait::hasHeader
|
||||
*/
|
||||
public function testHasHeader()
|
||||
{
|
||||
$message = new MessageTraitResponseImplementation();
|
||||
$this->assertFalse($message->hasHeader('test'));
|
||||
|
||||
$newMessage = $message->withHeader('test', '12345');
|
||||
$this->assertTrue($newMessage->hasHeader('Test'));
|
||||
$this->assertTrue($newMessage->hasHeader('test'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\MessageTrait::getHeader
|
||||
*/
|
||||
public function testGetHeader()
|
||||
{
|
||||
$message = new MessageTraitResponseImplementation();
|
||||
$newMessage = $message->withHeader('foo', 'bar');
|
||||
|
||||
$this->assertEquals(['bar'], $newMessage->getHeader('Foo'));
|
||||
$this->assertEquals([], $newMessage->getHeader('LoremIpsum'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\MessageTrait::getHeaderLine
|
||||
*/
|
||||
public function testGetHeaderLine()
|
||||
{
|
||||
$message = new MessageTraitResponseImplementation();
|
||||
$newMessage = $message->withHeader('foo', ['bar', 'bla']);
|
||||
|
||||
$this->assertEquals('', $newMessage->getHeaderLine('Lorem-Ipsum'));
|
||||
$this->assertEquals('bar,bla', $newMessage->getHeaderLine('Foo'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\MessageTrait::withHeader
|
||||
*/
|
||||
public function testWithHeader()
|
||||
{
|
||||
$message = new MessageTraitResponseImplementation();
|
||||
$newMessage = $message->withHeader('foo', 'bar');
|
||||
|
||||
$this->assertNotEquals($message, $newMessage);
|
||||
$this->assertArraySubset(['foo' => ['bar']], $newMessage->getHeaders());
|
||||
|
||||
$newMessage = $newMessage->withHeader('Foo', ['lorem', 'ipsum']);
|
||||
$this->assertArraySubset(['Foo' => ['lorem', 'ipsum']], $newMessage->getHeaders());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\MessageTrait::withAddedHeader
|
||||
*/
|
||||
public function testWithAddedHeader()
|
||||
{
|
||||
$message = new MessageTraitResponseImplementation();
|
||||
$newMessage = $message->withHeader('foo', 'bar');
|
||||
|
||||
$this->assertNotEquals($message, $newMessage);
|
||||
$this->assertArraySubset(['foo' => ['bar']], $newMessage->getHeaders());
|
||||
|
||||
$newMessage = $newMessage->withAddedHeader('Foo', ['lorem', 'ipsum']);
|
||||
$this->assertArraySubset(['Foo' => ['bar', 'lorem', 'ipsum']], $newMessage->getHeaders());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\MessageTrait::withoutHeader
|
||||
*/
|
||||
public function testWithoutHeader()
|
||||
{
|
||||
$message = (new MessageTraitResponseImplementation())->withHeader('foo', 'bar');
|
||||
$this->assertTrue($message->hasHeader('foo'));
|
||||
|
||||
$newMessage = $message->withoutHeader('Foo');
|
||||
$this->assertNotEquals($message, $newMessage);
|
||||
$this->assertFalse($newMessage->hasHeader('foo'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\MessageTrait::getBody
|
||||
*/
|
||||
public function testGetBody()
|
||||
{
|
||||
$message = (new MessageTraitResponseImplementation())->setContent('Foo bar!');
|
||||
$body = $message->getBody();
|
||||
|
||||
$this->assertInstanceOf(StreamInterface::class, $body);
|
||||
$this->assertEquals('Foo bar!', $body->getContents());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\MessageTrait::withBody
|
||||
*/
|
||||
public function testWithBody()
|
||||
{
|
||||
/** @var Stream $stream */
|
||||
$stream = new Stream('php://memory', 'wb+');
|
||||
$stream->write('Test content');
|
||||
$stream->rewind();
|
||||
|
||||
$message = new MessageTraitResponseImplementation();
|
||||
$newMessage = $message->withBody($stream);
|
||||
|
||||
$this->assertNotEquals($message, $newMessage);
|
||||
$this->assertEquals('Test content', $newMessage->getContent());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Http;
|
||||
|
||||
use Engelsystem\Http\Psr7ServiceProvider;
|
||||
use Engelsystem\Http\Request;
|
||||
use Engelsystem\Http\Response;
|
||||
use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface as RequestInterface;
|
||||
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
|
||||
|
||||
class Psr7ServiceProviderTest extends ServiceProviderTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Psr7ServiceProvider::register()
|
||||
*/
|
||||
public function testRegister()
|
||||
{
|
||||
/** @var MockObject|DiactorosFactory $psr7Factory */
|
||||
$psr7Factory = $this->createMock(DiactorosFactory::class);
|
||||
/** @var MockObject|Request $request */
|
||||
$request = $this->createMock(Request::class);
|
||||
/** @var MockObject|Response $response */
|
||||
$response = $this->createMock(Response::class);
|
||||
/** @var MockObject|RequestInterface $psr7request */
|
||||
$psr7request = $this->createMock(Request::class);
|
||||
/** @var MockObject|ResponseInterface $psr7response */
|
||||
$psr7response = $this->createMock(Response::class);
|
||||
|
||||
$app = $this->getApp(['make', 'instance', 'get', 'bind']);
|
||||
$this->setExpects($app, 'make', [DiactorosFactory::class], $psr7Factory);
|
||||
|
||||
$app->expects($this->atLeastOnce())
|
||||
->method('get')
|
||||
->withConsecutive(['request'], ['response'])
|
||||
->willReturnOnConsecutiveCalls($request, $response);
|
||||
$app->expects($this->atLeastOnce())
|
||||
->method('instance')
|
||||
->withConsecutive(
|
||||
['psr7.factory', $psr7Factory],
|
||||
['psr7.request', $psr7request],
|
||||
['psr7.response', $psr7response]
|
||||
);
|
||||
$app->expects($this->atLeastOnce())
|
||||
->method('bind')
|
||||
->withConsecutive(
|
||||
[RequestInterface::class, 'psr7.request'],
|
||||
[ResponseInterface::class, 'psr7.response']
|
||||
);
|
||||
|
||||
$serviceProvider = new Psr7ServiceProvider($app);
|
||||
$serviceProvider->register();
|
||||
}
|
||||
}
|
|
@ -5,9 +5,24 @@ namespace Engelsystem\Test\Unit\Http;
|
|||
use Engelsystem\Http\Request;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile as SymfonyFile;
|
||||
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
|
||||
|
||||
class RequestTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request
|
||||
*/
|
||||
public function testCreate()
|
||||
{
|
||||
$response = new Request();
|
||||
$this->assertInstanceOf(SymfonyRequest::class, $response);
|
||||
$this->assertInstanceOf(RequestInterface::class, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::postData
|
||||
*/
|
||||
|
@ -96,4 +111,272 @@ class RequestTest extends TestCase
|
|||
$this->assertEquals('http://foo.bar/bla/foo', $request->url());
|
||||
$this->assertEquals('https://lorem.ipsum/dolor/sit', $request->url());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::getRequestTarget
|
||||
*/
|
||||
public function testGetRequestTarget()
|
||||
{
|
||||
/** @var Request|MockObject $request */
|
||||
$request = $this
|
||||
->getMockBuilder(Request::class)
|
||||
->setMethods(['getQueryString', 'path'])
|
||||
->getMock();
|
||||
|
||||
$request->expects($this->exactly(2))
|
||||
->method('getQueryString')
|
||||
->willReturnOnConsecutiveCalls(null, 'foo=bar&lorem=ipsum');
|
||||
$request->expects($this->exactly(2))
|
||||
->method('path')
|
||||
->willReturn('foo/bar');
|
||||
|
||||
$this->assertEquals('/foo/bar', $request->getRequestTarget());
|
||||
$this->assertEquals('/foo/bar?foo=bar&lorem=ipsum', $request->getRequestTarget());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::withRequestTarget
|
||||
*/
|
||||
public function testWithRequestTarget()
|
||||
{
|
||||
$request = new Request();
|
||||
foreach (
|
||||
[
|
||||
'*',
|
||||
'/foo/bar',
|
||||
'https://lorem.ipsum/test?lor=em'
|
||||
] as $target
|
||||
) {
|
||||
$new = $request->withRequestTarget($target);
|
||||
$this->assertNotEquals($request, $new);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::withMethod
|
||||
*/
|
||||
public function testWithMethod()
|
||||
{
|
||||
$request = new Request();
|
||||
|
||||
$new = $request->withMethod('PUT');
|
||||
|
||||
$this->assertNotEquals($request, $new);
|
||||
$this->assertEquals('PUT', $new->getMethod());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::withUri
|
||||
*/
|
||||
public function testWithUri()
|
||||
{
|
||||
/** @var UriInterface|MockObject $uri */
|
||||
$uri = $this->getMockForAbstractClass(UriInterface::class);
|
||||
|
||||
$uri->expects($this->atLeastOnce())
|
||||
->method('__toString')
|
||||
->willReturn('http://foo.bar/bla?foo=bar');
|
||||
|
||||
$request = Request::create('http://lor.em/');
|
||||
|
||||
$new = $request->withUri($uri);
|
||||
$this->assertNotEquals($request, $new);
|
||||
$this->assertEquals('http://foo.bar/bla?foo=bar', (string)$new->getUri());
|
||||
|
||||
$new = $request->withUri($uri, true);
|
||||
$this->assertEquals('http://lor.em/bla?foo=bar', (string)$new->getUri());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::getUri
|
||||
*/
|
||||
public function testGetUri()
|
||||
{
|
||||
$request = Request::create('http://lor.em/test?bla=foo');
|
||||
|
||||
$uri = $request->getUri();
|
||||
$this->assertInstanceOf(UriInterface::class, $uri);
|
||||
$this->assertEquals('http://lor.em/test?bla=foo', (string)$uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::getServerParams
|
||||
*/
|
||||
public function testGetServerParams()
|
||||
{
|
||||
$server = ['foo' => 'bar'];
|
||||
$request = new Request([], [], [], [], [], $server);
|
||||
|
||||
$this->assertEquals($server, $request->getServerParams());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::getCookieParams
|
||||
*/
|
||||
public function testGetCookieParams()
|
||||
{
|
||||
$cookies = ['session' => 'LoremIpsumDolorSit'];
|
||||
$request = new Request([], [], [], $cookies);
|
||||
|
||||
$this->assertEquals($cookies, $request->getCookieParams());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::withCookieParams
|
||||
*/
|
||||
public function testWithCookieParams()
|
||||
{
|
||||
$cookies = ['lor' => 'em'];
|
||||
$request = new Request();
|
||||
|
||||
$new = $request->withCookieParams($cookies);
|
||||
|
||||
$this->assertNotEquals($request, $new);
|
||||
$this->assertEquals($cookies, $new->getCookieParams());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::getQueryParams
|
||||
*/
|
||||
public function testGetQueryParams()
|
||||
{
|
||||
$params = ['foo' => 'baz'];
|
||||
$request = new Request($params);
|
||||
|
||||
$this->assertEquals($params, $request->getQueryParams());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::withQueryParams
|
||||
*/
|
||||
public function testWithQueryParams()
|
||||
{
|
||||
$params = ['test' => 'ing'];
|
||||
$request = new Request();
|
||||
|
||||
$new = $request->withQueryParams($params);
|
||||
|
||||
$this->assertNotEquals($request, $new);
|
||||
$this->assertEquals($params, $new->getQueryParams());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::getUploadedFiles
|
||||
*/
|
||||
public function testGetUploadedFiles()
|
||||
{
|
||||
$filename = tempnam(sys_get_temp_dir(), 'test');
|
||||
file_put_contents($filename, 'LoremIpsum!');
|
||||
$files = [new SymfonyFile($filename, 'foo.html', 'text/html', 11)];
|
||||
$request = new Request([], [], [], [], $files);
|
||||
|
||||
$uploadedFiles = $request->getUploadedFiles();
|
||||
$this->assertNotEmpty($uploadedFiles);
|
||||
|
||||
/** @var UploadedFileInterface $file */
|
||||
$file = $uploadedFiles[0];
|
||||
$this->assertInstanceOf(UploadedFileInterface::class, $file);
|
||||
$this->assertEquals('foo.html', $file->getClientFilename());
|
||||
$this->assertEquals('text/html', $file->getClientMediaType());
|
||||
$this->assertEquals(11, $file->getSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::withUploadedFiles
|
||||
*/
|
||||
public function testWithUploadedFiles()
|
||||
{
|
||||
$filename = tempnam(sys_get_temp_dir(), 'test');
|
||||
file_put_contents($filename, 'LoremIpsum!');
|
||||
$file = new \Zend\Diactoros\UploadedFile($filename, 11, UPLOAD_ERR_OK, 'test.txt', 'text/plain');
|
||||
|
||||
$request = new Request();
|
||||
$new = $request->withUploadedFiles([$file]);
|
||||
$uploadedFiles = $new->getUploadedFiles();
|
||||
$this->assertNotEquals($request, $new);
|
||||
$this->assertNotEmpty($uploadedFiles);
|
||||
|
||||
/** @var UploadedFileInterface $file */
|
||||
$file = $uploadedFiles[0];
|
||||
$this->assertEquals('test.txt', $file->getClientFilename());
|
||||
$this->assertEquals('text/plain', $file->getClientMediaType());
|
||||
$this->assertEquals(11, $file->getSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::getParsedBody
|
||||
*/
|
||||
public function testGetParsedBody()
|
||||
{
|
||||
$body = ['foo' => 'lorem'];
|
||||
$request = new Request();
|
||||
$request->request->add($body);
|
||||
|
||||
$this->assertEquals($body, $request->getParsedBody());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::withParsedBody
|
||||
*/
|
||||
public function testWithParsedBody()
|
||||
{
|
||||
$data = ['test' => 'er'];
|
||||
$request = new Request();
|
||||
|
||||
$new = $request->withParsedBody($data);
|
||||
|
||||
$this->assertNotEquals($request, $new);
|
||||
$this->assertEquals($data, $new->getParsedBody());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::getAttributes
|
||||
*/
|
||||
public function testGetAttributes()
|
||||
{
|
||||
$attributes = ['foo' => 'lorem', 'ipsum' => 'dolor'];
|
||||
$request = new Request([], [], $attributes);
|
||||
|
||||
$this->assertEquals($attributes, $request->getAttributes());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::getAttribute
|
||||
*/
|
||||
public function testGetAttribute()
|
||||
{
|
||||
$attributes = ['foo' => 'lorem', 'ipsum' => 'dolor'];
|
||||
$request = new Request([], [], $attributes);
|
||||
|
||||
$this->assertEquals($attributes['ipsum'], $request->getAttribute('ipsum'));
|
||||
$this->assertEquals(null, $request->getAttribute('dolor'));
|
||||
$this->assertEquals(1234, $request->getAttribute('test', 1234));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::withAttribute
|
||||
*/
|
||||
public function testWithAttribute()
|
||||
{
|
||||
$request = new Request();
|
||||
|
||||
$new = $request->withAttribute('lorem', 'ipsum');
|
||||
|
||||
$this->assertNotEquals($request, $new);
|
||||
$this->assertEquals('ipsum', $new->getAttribute('lorem'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Request::withoutAttribute
|
||||
*/
|
||||
public function testWithoutAttribute()
|
||||
{
|
||||
$attributes = ['foo' => 'lorem', 'ipsum' => 'dolor'];
|
||||
$request = new Request([], [], $attributes);
|
||||
|
||||
$new = $request->withoutAttribute('ipsum');
|
||||
|
||||
$this->assertNotEquals($request, $new);
|
||||
$this->assertEquals(['foo' => 'lorem'], $new->getAttributes());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Http;
|
||||
|
||||
use Engelsystem\Http\Response;
|
||||
use Engelsystem\Http\ResponseServiceProvider;
|
||||
use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||
|
||||
class ResponseServiceProviderTest extends ServiceProviderTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Http\ResponseServiceProvider::register()
|
||||
*/
|
||||
public function testRegister()
|
||||
{
|
||||
/** @var MockObject|Response $response */
|
||||
$response = $this->getMockBuilder(Response::class)
|
||||
->getMock();
|
||||
|
||||
$app = $this->getApp();
|
||||
|
||||
$this->setExpects($app, 'make', [Response::class], $response);
|
||||
$this->setExpects($app, 'instance', ['response', $response]);
|
||||
|
||||
$serviceProvider = new ResponseServiceProvider($app);
|
||||
$serviceProvider->register();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Http;
|
||||
|
||||
use Engelsystem\Http\Response;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
|
||||
|
||||
class ResponseTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Response
|
||||
*/
|
||||
public function testCreate()
|
||||
{
|
||||
$response = new Response();
|
||||
$this->assertInstanceOf(SymfonyResponse::class, $response);
|
||||
$this->assertInstanceOf(ResponseInterface::class, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Response::withStatus
|
||||
* @covers \Engelsystem\Http\Response::getReasonPhrase
|
||||
*/
|
||||
public function testWithStatus()
|
||||
{
|
||||
$response = new Response();
|
||||
$newResponse = $response->withStatus(503);
|
||||
$this->assertNotEquals($response, $newResponse);
|
||||
$this->assertNotEquals('', $newResponse->getReasonPhrase());
|
||||
$this->assertEquals(503, $newResponse->getStatusCode());
|
||||
|
||||
$newResponse = $response->withStatus(503, 'Foo');
|
||||
$this->assertEquals('Foo', $newResponse->getReasonPhrase());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Response::withContent
|
||||
*/
|
||||
public function testWithContent()
|
||||
{
|
||||
$response = new Response();
|
||||
$newResponse = $response->withContent('Lorem Ipsum?');
|
||||
|
||||
$this->assertNotEquals($response, $newResponse);
|
||||
$this->assertEquals('Lorem Ipsum?', $newResponse->getContent());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Http\Stub;
|
||||
|
||||
use Engelsystem\Http\MessageTrait;
|
||||
use Psr\Http\Message\MessageInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class MessageTraitRequestImplementation extends Request implements MessageInterface
|
||||
{
|
||||
use MessageTrait;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Http\Stub;
|
||||
|
||||
use Engelsystem\Http\MessageTrait;
|
||||
use Psr\Http\Message\MessageInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class MessageTraitResponseImplementation extends Response implements MessageInterface
|
||||
{
|
||||
use MessageTrait;
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Middleware;
|
||||
|
||||
use Engelsystem\Application;
|
||||
use Engelsystem\Middleware\Dispatcher;
|
||||
use Engelsystem\Test\Unit\Middleware\Stub\NotARealMiddleware;
|
||||
use Engelsystem\Test\Unit\Middleware\Stub\ReturnResponseMiddleware;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use ReflectionClass as Reflection;
|
||||
|
||||
class DispatcherTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\Dispatcher::__construct
|
||||
*/
|
||||
public function testInit()
|
||||
{
|
||||
/** @var Application|MockObject $container */
|
||||
$container = $this->createMock(Application::class);
|
||||
|
||||
$dispatcher = new Dispatcher([], $container);
|
||||
$this->assertInstanceOf(MiddlewareInterface::class, $dispatcher);
|
||||
$this->assertInstanceOf(RequestHandlerInterface::class, $dispatcher);
|
||||
|
||||
$reflection = new Reflection(get_class($dispatcher));
|
||||
$property = $reflection->getProperty('container');
|
||||
$property->setAccessible(true);
|
||||
$this->assertEquals($container, $property->getValue($dispatcher));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\Dispatcher::process
|
||||
*/
|
||||
public function testProcess()
|
||||
{
|
||||
/** @var ServerRequestInterface|MockObject $request */
|
||||
$request = $this->createMock(ServerRequestInterface::class);
|
||||
/** @var ResponseInterface|MockObject $response */
|
||||
$response = $this->createMock(ResponseInterface::class);
|
||||
/** @var RequestHandlerInterface|MockObject $handler */
|
||||
$handler = $this->createMock(RequestHandlerInterface::class);
|
||||
|
||||
/** @var Dispatcher|MockObject $dispatcher */
|
||||
$dispatcher = $this->getMockBuilder(Dispatcher::class)
|
||||
->setMethods(['handle'])
|
||||
->getMock();
|
||||
|
||||
$dispatcher->expects($this->once())
|
||||
->method('handle')
|
||||
->willReturn($response);
|
||||
|
||||
$return = $dispatcher->process($request, $handler);
|
||||
$this->assertEquals($response, $return);
|
||||
|
||||
$reflection = new Reflection(get_class($dispatcher));
|
||||
$property = $reflection->getProperty('next');
|
||||
$property->setAccessible(true);
|
||||
|
||||
$this->assertEquals($handler, $property->getValue($dispatcher));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\Dispatcher::handle
|
||||
*/
|
||||
public function testHandle()
|
||||
{
|
||||
/** @var ServerRequestInterface|MockObject $request */
|
||||
$request = $this->createMock(ServerRequestInterface::class);
|
||||
/** @var ResponseInterface|MockObject $response */
|
||||
$response = $this->createMock(ResponseInterface::class);
|
||||
/** @var MiddlewareInterface|MockObject $middleware */
|
||||
$middleware = $this->createMock(MiddlewareInterface::class);
|
||||
|
||||
$dispatcher = new Dispatcher([$middleware]);
|
||||
$middleware->expects($this->once())
|
||||
->method('process')
|
||||
->with($request, $dispatcher)
|
||||
->willReturn($response);
|
||||
|
||||
$return = $dispatcher->handle($request);
|
||||
$this->assertEquals($response, $return);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\Dispatcher::handle
|
||||
*/
|
||||
public function testHandleNext()
|
||||
{
|
||||
/** @var ServerRequestInterface|MockObject $request */
|
||||
$request = $this->createMock(ServerRequestInterface::class);
|
||||
/** @var ResponseInterface|MockObject $response */
|
||||
$response = $this->createMock(ResponseInterface::class);
|
||||
/** @var RequestHandlerInterface|MockObject $handler */
|
||||
$handler = $this->createMock(RequestHandlerInterface::class);
|
||||
|
||||
$dispatcher = new Dispatcher();
|
||||
$handler->expects($this->once())
|
||||
->method('handle')
|
||||
->with($request)
|
||||
->willReturn($response);
|
||||
|
||||
$reflection = new Reflection(get_class($dispatcher));
|
||||
$property = $reflection->getProperty('next');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($dispatcher, $handler);
|
||||
|
||||
$return = $dispatcher->handle($request);
|
||||
$this->assertEquals($response, $return);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\Dispatcher::handle
|
||||
*/
|
||||
public function testHandleNoMiddleware()
|
||||
{
|
||||
/** @var ServerRequestInterface|MockObject $request */
|
||||
$request = $this->createMock(ServerRequestInterface::class);
|
||||
|
||||
$this->expectException(LogicException::class);
|
||||
|
||||
$dispatcher = new Dispatcher();
|
||||
$dispatcher->handle($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\Dispatcher::handle
|
||||
*/
|
||||
public function testHandleNoRealMiddleware()
|
||||
{
|
||||
/** @var ServerRequestInterface|MockObject $request */
|
||||
$request = $this->createMock(ServerRequestInterface::class);
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$dispatcher = new Dispatcher([new NotARealMiddleware()]);
|
||||
$dispatcher->handle($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\Dispatcher::handle
|
||||
*/
|
||||
public function testHandleCallResolve()
|
||||
{
|
||||
/** @var ServerRequestInterface|MockObject $request */
|
||||
$request = $this->createMock(ServerRequestInterface::class);
|
||||
/** @var ResponseInterface|MockObject $response */
|
||||
$response = $this->createMock(ResponseInterface::class);
|
||||
/** @var MiddlewareInterface|MockObject $middleware */
|
||||
$middleware = $this->createMock(MiddlewareInterface::class);
|
||||
|
||||
/** @var Dispatcher|MockObject $dispatcher */
|
||||
$dispatcher = $this->getMockBuilder(Dispatcher::class)
|
||||
->setConstructorArgs([[MiddlewareInterface::class]])
|
||||
->setMethods(['resolveMiddleware'])
|
||||
->getMock();
|
||||
|
||||
$dispatcher->expects($this->once())
|
||||
->method('resolveMiddleware')
|
||||
->with(MiddlewareInterface::class)
|
||||
->willReturn($middleware);
|
||||
|
||||
$middleware->expects($this->once())
|
||||
->method('process')
|
||||
->with($request, $dispatcher)
|
||||
->willReturn($response);
|
||||
|
||||
$return = $dispatcher->handle($request);
|
||||
$this->assertEquals($response, $return);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\Dispatcher::resolveMiddleware
|
||||
* @covers \Engelsystem\Middleware\Dispatcher::setContainer
|
||||
*/
|
||||
public function testResolveMiddleware()
|
||||
{
|
||||
/** @var Application|MockObject $container */
|
||||
$container = $this->createMock(Application::class);
|
||||
/** @var ServerRequestInterface|MockObject $request */
|
||||
$request = $this->createMock(ServerRequestInterface::class);
|
||||
/** @var ResponseInterface|MockObject $response */
|
||||
$response = $this->createMock(ResponseInterface::class);
|
||||
|
||||
$returnResponseMiddleware = new ReturnResponseMiddleware($response);
|
||||
|
||||
$container->expects($this->exactly(2))
|
||||
->method('has')
|
||||
->withConsecutive([ReturnResponseMiddleware::class], ['middleware'])
|
||||
->willReturnOnConsecutiveCalls(false, true);
|
||||
|
||||
$container->expects($this->once())
|
||||
->method('make')
|
||||
->with(ReturnResponseMiddleware::class)
|
||||
->willReturn($returnResponseMiddleware);
|
||||
|
||||
$container->expects($this->once())
|
||||
->method('get')
|
||||
->with('middleware')
|
||||
->willReturn($returnResponseMiddleware);
|
||||
|
||||
$dispatcher = new Dispatcher([ReturnResponseMiddleware::class]);
|
||||
$dispatcher->setContainer($container);
|
||||
$dispatcher->handle($request);
|
||||
|
||||
$dispatcher = new Dispatcher(['middleware'], $container);
|
||||
$dispatcher->handle($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\Dispatcher::resolveMiddleware
|
||||
*/
|
||||
public function testResolveMiddlewareNoContainer()
|
||||
{
|
||||
/** @var ServerRequestInterface|MockObject $request */
|
||||
$request = $this->createMock(ServerRequestInterface::class);
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$dispatcher = new Dispatcher([ReturnResponseMiddleware::class]);
|
||||
$dispatcher->handle($request);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Middleware;
|
||||
|
||||
use Engelsystem\Application;
|
||||
use Engelsystem\Exceptions\Handler;
|
||||
use Engelsystem\Http\Response;
|
||||
use Engelsystem\Middleware\ExceptionHandler;
|
||||
use Engelsystem\Test\Unit\Middleware\Stub\ExceptionMiddlewareHandler;
|
||||
use Engelsystem\Test\Unit\Middleware\Stub\ReturnResponseMiddlewareHandler;
|
||||
use Illuminate\Contracts\Container\Container as ContainerInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class ExceptionHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\ExceptionHandler::__construct
|
||||
* @covers \Engelsystem\Middleware\ExceptionHandler::process
|
||||
*/
|
||||
public function testRegister()
|
||||
{
|
||||
/** @var MockObject|ContainerInterface $container */
|
||||
$container = $this->getMockForAbstractClass(ContainerInterface::class);
|
||||
/** @var MockObject|ServerRequestInterface $request */
|
||||
$request = $this->getMockBuilder(ServerRequestInterface::class)->getMock();
|
||||
/** @var MockObject|ResponseInterface $response */
|
||||
$response = $this->getMockBuilder(Response::class)->getMock();
|
||||
/** @var MockObject|Handler $errorHandler */
|
||||
$errorHandler = $this->getMockBuilder(Handler::class)->getMock();
|
||||
$returnResponseHandler = new ReturnResponseMiddlewareHandler($response);
|
||||
$throwExceptionHandler = new ExceptionMiddlewareHandler();
|
||||
|
||||
Application::setInstance($container);
|
||||
|
||||
$container->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->withConsecutive(['error.handler'], ['psr7.response'])
|
||||
->willReturnOnConsecutiveCalls($errorHandler, $response);
|
||||
|
||||
$response->expects($this->once())
|
||||
->method('withContent')
|
||||
->willReturn($response);
|
||||
$response->expects($this->once())
|
||||
->method('withStatus')
|
||||
->with(500)
|
||||
->willReturn($response);
|
||||
|
||||
$handler = new ExceptionHandler($container);
|
||||
$return = $handler->process($request, $returnResponseHandler);
|
||||
$this->assertEquals($response, $return);
|
||||
|
||||
$return = $handler->process($request, $throwExceptionHandler);
|
||||
$this->assertEquals($response, $return);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Middleware;
|
||||
|
||||
use Engelsystem\Http\Request;
|
||||
use Engelsystem\Middleware\LegacyMiddleware;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
|
||||
class LegacyMiddlewareTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\LegacyMiddleware::__construct
|
||||
* @covers \Engelsystem\Middleware\LegacyMiddleware::process
|
||||
*/
|
||||
public function testRegister()
|
||||
{
|
||||
/** @var ContainerInterface|MockObject $container */
|
||||
$container = $this->getMockForAbstractClass(ContainerInterface::class);
|
||||
/** @var LegacyMiddleware|MockObject $middleware */
|
||||
$middleware = $this->getMockBuilder(LegacyMiddleware::class)
|
||||
->setConstructorArgs([$container])
|
||||
->setMethods(['loadPage', 'renderPage'])
|
||||
->getMock();
|
||||
/** @var Request|MockObject $defaultRequest */
|
||||
$defaultRequest = $this->createMock(Request::class);
|
||||
/** @var ParameterBag|MockObject $parameters */
|
||||
$parameters = $this->createMock(ParameterBag::class);
|
||||
/** @var ResponseInterface|MockObject $response */
|
||||
$response = $this->getMockForAbstractClass(ResponseInterface::class);
|
||||
/** @var RequestHandlerInterface|MockObject $handler */
|
||||
$handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
|
||||
/** @var ServerRequestInterface|MockObject $request */
|
||||
$request = $this->getMockForAbstractClass(ServerRequestInterface::class);
|
||||
|
||||
$middleware->expects($this->exactly(2))
|
||||
->method('loadPage')
|
||||
->withConsecutive(['user_worklog'], ['login'])
|
||||
->willReturnOnConsecutiveCalls(
|
||||
['title', 'content'],
|
||||
['title2', 'content2']
|
||||
);
|
||||
|
||||
$middleware->expects($this->exactly(2))
|
||||
->method('renderPage')
|
||||
->withConsecutive(
|
||||
['user_worklog', 'title', 'content'],
|
||||
['login', 'title2', 'content2']
|
||||
)
|
||||
->willReturn($response);
|
||||
|
||||
$container->expects($this->atLeastOnce())
|
||||
->method('get')
|
||||
->with('request')
|
||||
->willReturn($defaultRequest);
|
||||
|
||||
$defaultRequest->query = $parameters;
|
||||
$defaultRequest->expects($this->once())
|
||||
->method('path')
|
||||
->willReturn('user-worklog');
|
||||
|
||||
$parameters->expects($this->exactly(3))
|
||||
->method('get')
|
||||
->with('p')
|
||||
->willReturnOnConsecutiveCalls(
|
||||
null,
|
||||
'foo',
|
||||
'/'
|
||||
);
|
||||
|
||||
$handler->expects($this->once())
|
||||
->method('handle')
|
||||
->with($request)
|
||||
->willReturn($response);
|
||||
|
||||
$middleware->process($request, $handler);
|
||||
$middleware->process($request, $handler);
|
||||
$middleware->process($request, $handler);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Middleware;
|
||||
|
||||
use Engelsystem\Middleware\NotFoundResponse;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class NotFoundResponseTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\NotFoundResponse::process
|
||||
*/
|
||||
public function testRegister()
|
||||
{
|
||||
/** @var NotFoundResponse|MockObject $middleware */
|
||||
$middleware = $this->getMockBuilder(NotFoundResponse::class)
|
||||
->setMethods(['renderPage'])
|
||||
->getMock();
|
||||
/** @var ResponseInterface|MockObject $response */
|
||||
$response = $this->getMockForAbstractClass(ResponseInterface::class);
|
||||
/** @var RequestHandlerInterface|MockObject $handler */
|
||||
$handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
|
||||
/** @var ServerRequestInterface|MockObject $request */
|
||||
$request = $this->getMockForAbstractClass(ServerRequestInterface::class);
|
||||
|
||||
$middleware->expects($this->once())
|
||||
->method('renderPage')
|
||||
->willReturn($response);
|
||||
|
||||
$handler->expects($this->never())
|
||||
->method('handle');
|
||||
|
||||
$middleware->process($request, $handler);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Middleware;
|
||||
|
||||
use Engelsystem\Middleware\SendResponseHandler;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class SendResponseHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\SendResponseHandler::process
|
||||
*/
|
||||
public function testRegister()
|
||||
{
|
||||
/** @var SendResponseHandler|MockObject $middleware */
|
||||
$middleware = $this->getMockBuilder(SendResponseHandler::class)
|
||||
->setMethods(['headersSent', 'sendHeader'])
|
||||
->getMock();
|
||||
/** @var ServerRequestInterface|MockObject $request */
|
||||
$request = $this->getMockForAbstractClass(ServerRequestInterface::class);
|
||||
/** @var ResponseInterface|MockObject $response */
|
||||
$response = $this->getMockForAbstractClass(ResponseInterface::class);
|
||||
/** @var RequestHandlerInterface|MockObject $handler */
|
||||
$handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
|
||||
|
||||
$middleware->expects($this->atLeastOnce())
|
||||
->method('headersSent')
|
||||
->willReturnOnConsecutiveCalls(true, false);
|
||||
|
||||
$middleware->expects($this->exactly(4))
|
||||
->method('sendHeader')
|
||||
->withConsecutive(
|
||||
['HTTP/0.7 505 Something went wrong!', true, 505],
|
||||
['Foo: bar', false],
|
||||
['lorem: ipsum', false],
|
||||
['lorem: dolor', false]
|
||||
);
|
||||
|
||||
$handler->expects($this->exactly(2))
|
||||
->method('handle')
|
||||
->with($request)
|
||||
->willReturn($response);
|
||||
|
||||
$response->expects($this->exactly(2))
|
||||
->method('getBody')
|
||||
->willReturn('Lorem Ipsum!');
|
||||
|
||||
$response->expects($this->atLeastOnce())
|
||||
->method('getProtocolVersion')
|
||||
->willReturn('0.7');
|
||||
|
||||
$response->expects($this->atLeastOnce())
|
||||
->method('getStatusCode')
|
||||
->willReturn(505);
|
||||
|
||||
$response->expects($this->once())
|
||||
->method('getReasonPhrase')
|
||||
->willReturn('Something went wrong!');
|
||||
$response->expects($this->once())
|
||||
->method('getHeaders')
|
||||
->willReturn(['Foo' => ['bar'], 'lorem' => ['ipsum', 'dolor']]);
|
||||
|
||||
$this->expectOutputString('Lorem Ipsum!Lorem Ipsum!');
|
||||
$middleware->process($request, $handler);
|
||||
$middleware->process($request, $handler);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Middleware\Stub;
|
||||
|
||||
use Exception;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class ExceptionMiddlewareHandler implements RequestHandlerInterface
|
||||
{
|
||||
/**
|
||||
* Throws an exception
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @return ResponseInterface
|
||||
* @throws Exception
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
throw new Exception('Boooom!');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Middleware\Stub;
|
||||
|
||||
class NotARealMiddleware
|
||||
{
|
||||
// I'm not a middleware!
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Middleware\Stub;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class ReturnResponseMiddleware implements MiddlewareInterface
|
||||
{
|
||||
/** @var ResponseInterface */
|
||||
protected $response;
|
||||
|
||||
public function __construct(ResponseInterface $response)
|
||||
{
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* response creation to a handler.
|
||||
*
|
||||
* Could be used to group middleware
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @param RequestHandlerInterface $handler
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function process(
|
||||
ServerRequestInterface $request,
|
||||
RequestHandlerInterface $handler
|
||||
): ResponseInterface {
|
||||
return $this->response;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Middleware\Stub;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class ReturnResponseMiddlewareHandler implements RequestHandlerInterface
|
||||
{
|
||||
/** @var ResponseInterface */
|
||||
protected $response;
|
||||
|
||||
public function __construct(ResponseInterface $response)
|
||||
{
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a given response
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @return ResponseInterface
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue