Compare commits

..

3 Commits

Author SHA1 Message Date
5e0579463c
Merge pull request 'feature/get-rid-of-container-usage' (#11) from feature/get-rid-of-container-usage into master
All checks were successful
soko-web/pipeline/head This commit looks good
Reviewed-on: #11
2023-04-19 23:35:03 +02:00
4fe463fcc5
do not use app container in classes
All checks were successful
soko-web/pipeline/pr-master This commit looks good
2023-04-19 23:26:24 +02:00
0f87a9c6e3
add interfaces for route and route collection 2023-04-19 22:15:49 +02:00
13 changed files with 103 additions and 34 deletions

View File

@ -3,12 +3,3 @@
require 'vendor/autoload.php'; require 'vendor/autoload.php';
const ROOT = __DIR__; const ROOT = __DIR__;
class Container
{
static SokoWeb\Interfaces\Database\IConnection $dbConnection;
static SokoWeb\Interfaces\Database\IAuditLogger $auditLogger;
static SokoWeb\Routing\RouteCollection $routeCollection;
static SokoWeb\Interfaces\Session\ISessionHandler $sessionHandler;
static SokoWeb\Interfaces\Request\IRequest $request;
}

View File

@ -0,0 +1,20 @@
<?php namespace SokoWeb\Interfaces\PersistentData;
use Generator;
use SokoWeb\Database\Query\Select;
use SokoWeb\PersistentData\Model\Model;
interface IPersistentDataManager
{
public function selectFromDb(Select $select, string $type, bool $useRelations = false, array $withRelations = []);
public function selectMultipleFromDb(Select $select, string $type, bool $useRelations = false, array $withRelations = []): Generator;
public function selectFromDbById($id, string $type, bool $useRelations = false);
public function loadRelationsFromDb(Model $model, bool $recursive): void;
public function saveToDb(Model $model): void;
public function deleteFromDb(Model $model): void;
}

View File

@ -6,7 +6,7 @@ interface IRedirect
const TEMPORARY = 2; const TEMPORARY = 2;
public function getUrl(): string; public function getTarget(): string;
public function getHttpCode(): int; public function getHttpCode(): int;
} }

View File

@ -0,0 +1,12 @@
<?php namespace SokoWeb\Interfaces\Routing;
interface IRoute
{
public function getId(): string;
public function getHandler(): array;
public function generateLink(array $parameters = []): string;
public function testAgainst(array $path): ?array;
}

View File

@ -0,0 +1,16 @@
<?php namespace SokoWeb\Interfaces\Routing;
use Closure;
interface IRouteCollection
{
public function get(string $id, string $pattern, array $handler): void;
public function post(string $id, string $pattern, array $handler): void;
public function group(string $pattern, Closure $group): void;
public function getRoute(string $id): ?IRoute;
public function match(string $method, string $uri): ?array;
}

View File

@ -3,11 +3,24 @@
use Generator; use Generator;
use SokoWeb\Database\Query\Modify; use SokoWeb\Database\Query\Modify;
use SokoWeb\Database\Query\Select; use SokoWeb\Database\Query\Select;
use SokoWeb\Interfaces\Database\IConnection;
use SokoWeb\Interfaces\Database\IAuditLogger;
use SokoWeb\Interfaces\Database\IResultSet; use SokoWeb\Interfaces\Database\IResultSet;
use SokoWeb\Interfaces\PersistentData\IPersistentDataManager;
use SokoWeb\PersistentData\Model\Model; use SokoWeb\PersistentData\Model\Model;
class PersistentDataManager class PersistentDataManager implements IPersistentDataManager
{ {
private IConnection $dbConnection;
private IAuditLogger $auditLogger;
public function __construct(IConnection $dbConnection, IAuditLogger $auditLogger)
{
$this->dbConnection = $dbConnection;
$this->auditLogger = $auditLogger;
}
public function selectFromDb(Select $select, string $type, bool $useRelations = false, array $withRelations = []) public function selectFromDb(Select $select, string $type, bool $useRelations = false, array $withRelations = [])
{ {
$select = $this->createSelect($select, $type, $useRelations, $withRelations); $select = $this->createSelect($select, $type, $useRelations, $withRelations);
@ -39,7 +52,7 @@ class PersistentDataManager
public function selectFromDbById($id, string $type, bool $useRelations = false) public function selectFromDbById($id, string $type, bool $useRelations = false)
{ {
$select = new Select(\Container::$dbConnection); $select = new Select($this->dbConnection);
$select->whereId($id); $select->whereId($id);
return $this->selectFromDb($select, $type, $useRelations); return $this->selectFromDb($select, $type, $useRelations);
@ -117,7 +130,7 @@ class PersistentDataManager
$modified = $model->toArray(); $modified = $model->toArray();
$id = $model->getId(); $id = $model->getId();
$modify = new Modify(\Container::$dbConnection, $model::getTable(), \Container::$auditLogger); $modify = new Modify($this->dbConnection, $model::getTable(), $this->auditLogger);
if ($id !== null) { if ($id !== null) {
$original = $model->getSnapshot(); $original = $model->getSnapshot();
@ -149,7 +162,7 @@ class PersistentDataManager
public function deleteFromDb(Model $model): void public function deleteFromDb(Model $model): void
{ {
$modify = new Modify(\Container::$dbConnection, $model::getTable(), \Container::$auditLogger); $modify = new Modify($this->dbConnection, $model::getTable(), $this->auditLogger);
$modify->setId($model->getId()); $modify->setId($model->getId());
$modify->fill($model->toArray()); $modify->fill($model->toArray());
$modify->delete(); $modify->delete();

View File

@ -64,7 +64,7 @@ class HttpResponse
list($route, $params) = $match; list($route, $params) = $match;
$this->request->setParsedRouteParams($params); $this->request->setParsedRouteParams($params);
$handler = $route->getHandler(); $handler = $route->getHandler();
$controller = new $handler[0]($this->request); $controller = new $handler[0]();
if ( if (
$controller instanceof IAuthenticationRequired && $controller instanceof IAuthenticationRequired &&
@ -103,7 +103,7 @@ class HttpResponse
header('Content-Type: ' . $response->getContentType() . '; charset=UTF-8'); header('Content-Type: ' . $response->getContentType() . '; charset=UTF-8');
$response->render(); $response->render();
} elseif ($response instanceof IRedirect) { } elseif ($response instanceof IRedirect) {
header('Location: ' . $response->getUrl(), true, $response->getHttpCode()); header('Location: ' . $this->getRedirectUrl($response), true, $response->getHttpCode());
} else { } else {
$this->render404(); $this->render404();
} }
@ -113,7 +113,7 @@ class HttpResponse
{ {
$this->request->session()->set('redirect_after_login', $this->rawUrl); $this->request->session()->set('redirect_after_login', $this->rawUrl);
$response = new Redirect($this->routeCollection->getRoute($this->appConfig['loginRouteId'])->generateLink(), IRedirect::TEMPORARY); $response = new Redirect($this->routeCollection->getRoute($this->appConfig['loginRouteId'])->generateLink(), IRedirect::TEMPORARY);
header('Location: ' . $response->getUrl(), true, $response->getHttpCode()); header('Location: ' . $this->getRedirectUrl($response), true, $response->getHttpCode());
} }
private function renderAntiCsrfError(): void private function renderAntiCsrfError(): void
@ -142,4 +142,13 @@ class HttpResponse
header('Content-Type: text/html; charset=UTF-8', true, 500); header('Content-Type: text/html; charset=UTF-8', true, 500);
$content->render(); $content->render();
} }
private function getRedirectUrl(IRedirect $redirect): string
{
$url = $redirect->getTarget();
if (preg_match('/^http(s)?/', $url) !== 1) {
$url = $this->request->getBase() . $url;
}
return $url;
}
} }

View File

@ -14,15 +14,9 @@ class Redirect implements IRedirect
$this->type = $type; $this->type = $type;
} }
public function getUrl(): string public function getTarget(): string
{ {
if (preg_match('/^http(s)?/', $this->target) === 1) { return $this->target;
$link = $this->target;
} else {
$link = \Container::$request->getBase() . $this->target;
}
return $link;
} }
public function getHttpCode(): int public function getHttpCode(): int

View File

@ -1,6 +1,8 @@
<?php namespace SokoWeb\Routing; <?php namespace SokoWeb\Routing;
class Route use SokoWeb\Interfaces\Routing\IRoute;
class Route implements IRoute
{ {
private string $id; private string $id;

View File

@ -1,8 +1,10 @@
<?php namespace SokoWeb\Routing; <?php namespace SokoWeb\Routing;
use Closure; use Closure;
use SokoWeb\Interfaces\Routing\IRoute;
use SokoWeb\Interfaces\Routing\IRouteCollection;
class RouteCollection class RouteCollection implements IRouteCollection
{ {
private array $routes = []; private array $routes = [];
@ -32,7 +34,7 @@ class RouteCollection
array_pop($this->groupStack); array_pop($this->groupStack);
} }
public function getRoute(string $id): ?Route public function getRoute(string $id): ?IRoute
{ {
if (!isset($this->routes[$id])) { if (!isset($this->routes[$id])) {
return null; return null;

View File

@ -3,15 +3,23 @@
use DateTime; use DateTime;
use SokoWeb\Database\Query\Modify; use SokoWeb\Database\Query\Modify;
use SokoWeb\Database\Query\Select; use SokoWeb\Database\Query\Select;
use SokoWeb\Interfaces\Database\IConnection;
use SokoWeb\Interfaces\Database\IResultSet; use SokoWeb\Interfaces\Database\IResultSet;
use SokoWeb\Interfaces\Session\ISessionHandler; use SokoWeb\Interfaces\Session\ISessionHandler;
class DatabaseSessionHandler implements ISessionHandler class DatabaseSessionHandler implements ISessionHandler
{ {
private IConnection $dbConnection;
private bool $exists = false; private bool $exists = false;
private bool $written = false; private bool $written = false;
public function __construct(IConnection $dbConnection)
{
$this->dbConnection = $dbConnection;
}
public function open($savePath, $sessionName): bool public function open($savePath, $sessionName): bool
{ {
return true; return true;
@ -24,7 +32,7 @@ class DatabaseSessionHandler implements ISessionHandler
public function read($id): string public function read($id): string
{ {
$select = new Select(\Container::$dbConnection, 'sessions'); $select = new Select($this->dbConnection, 'sessions');
$select->columns(['data']); $select->columns(['data']);
$select->whereId(substr($id, 0, 32)); $select->whereId(substr($id, 0, 32));
@ -41,7 +49,7 @@ class DatabaseSessionHandler implements ISessionHandler
public function write($id, $data): bool public function write($id, $data): bool
{ {
$modify = new Modify(\Container::$dbConnection, 'sessions'); $modify = new Modify($this->dbConnection, 'sessions');
if ($this->exists) { if ($this->exists) {
$modify->setId(substr($id, 0, 32)); $modify->setId(substr($id, 0, 32));
@ -60,7 +68,7 @@ class DatabaseSessionHandler implements ISessionHandler
public function destroy($id): bool public function destroy($id): bool
{ {
$modify = new Modify(\Container::$dbConnection, 'sessions'); $modify = new Modify($this->dbConnection, 'sessions');
$modify->setId(substr($id, 0, 32)); $modify->setId(substr($id, 0, 32));
$modify->delete(); $modify->delete();
@ -93,7 +101,7 @@ class DatabaseSessionHandler implements ISessionHandler
return true; return true;
} }
$modify = new Modify(\Container::$dbConnection, 'sessions'); $modify = new Modify($this->dbConnection, 'sessions');
$modify->setId(substr($id, 0, 32)); $modify->setId(substr($id, 0, 32));
$modify->set('updated', (new DateTime())->format('Y-m-d H:i:s')); $modify->set('updated', (new DateTime())->format('Y-m-d H:i:s'));

View File

@ -16,10 +16,12 @@ class Container
{ {
static SokoWeb\Interfaces\Database\IConnection $dbConnection; static SokoWeb\Interfaces\Database\IConnection $dbConnection;
static SokoWeb\Interfaces\Database\IAuditLogger $auditLogger; static SokoWeb\Interfaces\Database\IAuditLogger $auditLogger;
static SokoWeb\Routing\RouteCollection $routeCollection; static SokoWeb\Interfaces\PersistentData\IPersistentDataManager $persistentDataManager;
static SokoWeb\Interfaces\Routing\IRouteCollection $routeCollection;
static SokoWeb\Interfaces\Session\ISessionHandler $sessionHandler; static SokoWeb\Interfaces\Session\ISessionHandler $sessionHandler;
static SokoWeb\Interfaces\Request\IRequest $request; static SokoWeb\Interfaces\Request\IRequest $request;
} }
Container::$dbConnection = new SokoWeb\Database\Mysql\Connection($_ENV['DB_HOST'], $_ENV['DB_USER'], $_ENV['DB_PASSWORD'], $_ENV['DB_NAME']); Container::$dbConnection = new SokoWeb\Database\Mysql\Connection($_ENV['DB_HOST'], $_ENV['DB_USER'], $_ENV['DB_PASSWORD'], $_ENV['DB_NAME']);
Container::$auditLogger = new {app}\Database\AuditLogger(Container::$dbConnection, 'audit_log'); Container::$auditLogger = new {app}\Database\AuditLogger(Container::$dbConnection, 'audit_log');
Container::$persistentDataManager = new SokoWeb\PersistentData\PersistentDataManager(Container::$dbConnection, Container::$auditLogger);

View File

@ -14,7 +14,7 @@ Container::$routeCollection = new SokoWeb\Routing\RouteCollection();
Container::$routeCollection->get('index', '', [{app}\Controller\HomeController::class, 'getIndex']); Container::$routeCollection->get('index', '', [{app}\Controller\HomeController::class, 'getIndex']);
if (isset($_COOKIE['COOKIES_CONSENT'])) { if (isset($_COOKIE['COOKIES_CONSENT'])) {
Container::$sessionHandler = new SokoWeb\Session\DatabaseSessionHandler(); Container::$sessionHandler = new SokoWeb\Session\DatabaseSessionHandler(Container::$dbConnection);
session_set_save_handler(Container::$sessionHandler, true); session_set_save_handler(Container::$sessionHandler, true);
session_start([ session_start([