simplify actions, move ViewHttpResponse into src/App
continuous-integration/drone/push Build is passing Details

pull/22/head
maxime.batista 1 year ago
parent de75577f3d
commit d20cfd2486

@ -5,20 +5,16 @@ require "../../vendor/autoload.php";
require "../../sql/database.php"; require "../../sql/database.php";
require "../utils.php"; require "../utils.php";
use IQBall\Api\ApiAction; use IQBall\Api\API;
use IQBall\Api\Controller\APIAuthController;
use IQBall\Api\Controller\APITacticController;
use IQBall\Core\Action;
use IQBall\Core\Connection; use IQBall\Core\Connection;
use IQBall\Api\APIAuthController;
use IQBall\Api\APITacticController;
use IQBall\Core\Data\Account; use IQBall\Core\Data\Account;
use IQBall\Core\Gateway\AccountGateway; use IQBall\Core\Gateway\AccountGateway;
use IQBall\Core\Gateway\TacticInfoGateway; use IQBall\Core\Gateway\TacticInfoGateway;
use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Http\JsonHttpResponse;
use IQBall\Core\Http\ViewHttpResponse;
use IQBall\Core\Model\AuthModel; use IQBall\Core\Model\AuthModel;
use IQBall\Core\Model\TacticModel; use IQBall\Core\Model\TacticModel;
use IQBall\Core\Session\PhpSessionHandle;
use IQBall\Core\Validation\ValidationFail;
function getTacticController(): APITacticController { function getTacticController(): APITacticController {
return new APITacticController(new TacticModel(new TacticInfoGateway(new Connection(get_database())))); return new APITacticController(new TacticModel(new TacticInfoGateway(new Connection(get_database()))));
@ -32,68 +28,10 @@ function getRoutes(): AltoRouter {
$router = new AltoRouter(); $router = new AltoRouter();
$router->setBasePath(get_public_path() . "/api"); $router->setBasePath(get_public_path() . "/api");
$router->map("POST", "/tactic/[i:id]/edit/name", ApiAction::auth(fn(int $id, Account $acc) => getTacticController()->updateName($id, $acc))); $router->map("POST", "/tactic/[i:id]/edit/name", Action::auth(fn(int $id, Account $acc) => getTacticController()->updateName($id, $acc)));
$router->map("GET", "/tactic/[i:id]", ApiAction::auth(fn(int $id, Account $acc) => getTacticController()->getTacticInfo($id, $acc))); $router->map("POST", "/auth", Action::noAuth(fn() => getAuthController()->authorize()));
$router->map("POST", "/tactic/new", ApiAction::auth(fn(Account $acc) => getTacticController()->newTactic($acc)));
$router->map("POST", "/auth", ApiAction::noAuth(fn() => getAuthController()->authorize()));
return $router; return $router;
} }
/** Api::render(API::handleMatch(getRoutes()->match()));
* @param mixed[] $match
* @return HttpResponse
* @throws Exception
*/
function handleMatch(array $match): HttpResponse {
if (!$match) {
return new JsonHttpResponse([ValidationFail::notFound("not found")]);
}
$action = $match['target'];
if (!$action instanceof ApiAction) {
throw new Exception("routed action is not an AppAction object.");
}
$auth = null;
if ($action->isAuthRequired()) {
$auth = tryGetAuthorization();
if ($auth == null) {
return new JsonHttpResponse([ValidationFail::unauthorized("Missing or invalid 'Authorization' header.")]);
}
}
return $action->run($match['params'], $auth);
}
function tryGetAuthorization(): ?Account {
$headers = getallheaders();
// If no authorization header is set, try fallback to php session.
if (!isset($headers['Authorization'])) {
$session = PhpSessionHandle::init();
return $session->getAccount();
}
$token = $headers['Authorization'];
$gateway = new AccountGateway(new Connection(get_database()));
return $gateway->getAccountFromToken($token);
}
function render(HttpResponse $response): void {
http_response_code($response->getCode());
foreach ($response->getHeaders() as $header => $value) {
header("$header: $value");
}
if ($response instanceof JsonHttpResponse) {
header('Content-type: application/json');
echo $response->getJson();
} elseif ($response instanceof ViewHttpResponse) {
throw new Exception("API returned a view http response.");
}
}
render(handleMatch(getRoutes()->match()));

@ -7,32 +7,22 @@ require "../sql/database.php";
require "../src/utils.php"; require "../src/utils.php";
require "../src/App/react-display.php"; require "../src/App/react-display.php";
use IQBall\App\AppAction; use IQBall\App\App;
use IQBall\App\Controller\AuthController; use IQBall\App\Controller\AuthController;
use IQBall\App\Controller\EditorController; use IQBall\App\Controller\EditorController;
use IQBall\App\Controller\TeamController; use IQBall\App\Controller\TeamController;
use IQBall\App\Controller\UserController; use IQBall\App\Controller\UserController;
use IQBall\App\Controller\VisualizerController; use IQBall\App\Controller\VisualizerController;
use IQBall\Core\Action;
use IQBall\Core\Connection; use IQBall\Core\Connection;
use IQBall\Core\Gateway\AccountGateway; use IQBall\Core\Gateway\AccountGateway;
use IQBall\Core\Gateway\TacticInfoGateway; use IQBall\Core\Gateway\TacticInfoGateway;
use IQBall\Core\Gateway\TeamGateway; use IQBall\Core\Gateway\TeamGateway;
use IQBall\Core\Http\HttpCodes;
use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Http\JsonHttpResponse;
use IQBall\Core\Http\ViewHttpResponse;
use IQBall\Core\Model\AuthModel; use IQBall\Core\Model\AuthModel;
use IQBall\Core\Model\TacticModel; use IQBall\Core\Model\TacticModel;
use IQBall\Core\Model\TeamModel; use IQBall\Core\Model\TeamModel;
use IQBall\Core\Session\MutableSessionHandle;
use IQBall\Core\Session\PhpSessionHandle; use IQBall\Core\Session\PhpSessionHandle;
use IQBall\Core\Session\SessionHandle; use IQBall\Core\Session\SessionHandle;
use IQBall\Core\Validation\ValidationFail;
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
use Twig\Loader\FilesystemLoader;
function getConnection(): Connection { function getConnection(): Connection {
return new Connection(get_database()); return new Connection(get_database());
@ -65,96 +55,37 @@ function getRoutes(): AltoRouter {
$ar->setBasePath($basePath); $ar->setBasePath($basePath);
//authentication //authentication
$ar->map("GET", "/login", AppAction::noAuth(fn() => getAuthController()->displayLogin())); $ar->map("GET", "/login", Action::noAuth(fn() => getAuthController()->displayLogin()));
$ar->map("GET", "/register", AppAction::noAuth(fn() => getAuthController()->displayRegister())); $ar->map("GET", "/register", Action::noAuth(fn() => getAuthController()->displayRegister()));
$ar->map("POST", "/login", AppAction::noAuth(fn(SessionHandle $s) => getAuthController()->confirmLogin($_POST, $s))); $ar->map("POST", "/login", Action::noAuth(fn(SessionHandle $s) => getAuthController()->confirmLogin($_POST, $s)));
$ar->map("POST", "/register", AppAction::noAuth(fn(SessionHandle $s) => getAuthController()->confirmRegister($_POST, $s))); $ar->map("POST", "/register", Action::noAuth(fn(SessionHandle $s) => getAuthController()->confirmRegister($_POST, $s)));
//user-related //user-related
$ar->map("GET", "/home", AppAction::auth(fn(SessionHandle $s) => getUserController()->home($s))); $ar->map("GET", "/home", Action::auth(fn(SessionHandle $s) => getUserController()->home($s)));
$ar->map("GET", "/settings", AppAction::auth(fn(SessionHandle $s) => getUserController()->settings($s))); $ar->map("GET", "/", Action::auth(fn(SessionHandle $s) => getUserController()->home($s)));
$ar->map("GET", "/settings", Action::auth(fn(SessionHandle $s) => getUserController()->settings($s)));
//tactic-related //tactic-related
$ar->map("GET", "/tactic/[i:id]/view", AppAction::auth(fn(int $id, SessionHandle $s) => getVisualizerController()->visualize($id, $s))); $ar->map("GET", "/tactic/[i:id]/view", Action::auth(fn(int $id, SessionHandle $s) => getVisualizerController()->visualize($id, $s)));
$ar->map("GET", "/tactic/[i:id]/edit", AppAction::auth(fn(int $id, SessionHandle $s) => getEditorController()->edit($id, $s))); $ar->map("GET", "/tactic/[i:id]/edit", Action::auth(fn(int $id, SessionHandle $s) => getEditorController()->edit($id, $s)));
$ar->map("GET", "/tactic/new", AppAction::auth(fn(SessionHandle $s) => getEditorController()->createNew($s))); $ar->map("GET", "/tactic/new", Action::auth(fn(SessionHandle $s) => getEditorController()->createNew($s)));
//team-related //team-related
$ar->map("GET", "/team/new", AppAction::auth(fn(SessionHandle $s) => getTeamController()->displayCreateTeam($s))); $ar->map("GET", "/team/new", Action::auth(fn(SessionHandle $s) => getTeamController()->displayCreateTeam($s)));
$ar->map("POST", "/team/new", AppAction::auth(fn(SessionHandle $s) => getTeamController()->submitTeam($_POST, $s))); $ar->map("POST", "/team/new", Action::auth(fn(SessionHandle $s) => getTeamController()->submitTeam($_POST, $s)));
$ar->map("GET", "/team/search", AppAction::auth(fn(SessionHandle $s) => getTeamController()->displayListTeamByName($s))); $ar->map("GET", "/team/search", Action::auth(fn(SessionHandle $s) => getTeamController()->displayListTeamByName($s)));
$ar->map("POST", "/team/search", AppAction::auth(fn(SessionHandle $s) => getTeamController()->listTeamByName($_POST, $s))); $ar->map("POST", "/team/search", Action::auth(fn(SessionHandle $s) => getTeamController()->listTeamByName($_POST, $s)));
$ar->map("GET", "/team/[i:id]", AppAction::auth(fn(int $id, SessionHandle $s) => getTeamController()->displayTeam($id, $s))); $ar->map("GET", "/team/[i:id]", Action::auth(fn(int $id, SessionHandle $s) => getTeamController()->displayTeam($id, $s)));
$ar->map("GET", "/team/members/add", AppAction::auth(fn(SessionHandle $s) => getTeamController()->displayAddMember($s))); $ar->map("GET", "/team/members/add", Action::auth(fn(SessionHandle $s) => getTeamController()->displayAddMember($s)));
$ar->map("POST", "/team/members/add", AppAction::auth(fn(SessionHandle $s) => getTeamController()->addMember($_POST, $s))); $ar->map("POST", "/team/members/add", Action::auth(fn(SessionHandle $s) => getTeamController()->addMember($_POST, $s)));
$ar->map("GET", "/team/members/remove", AppAction::auth(fn(SessionHandle $s) => getTeamController()->displayDeleteMember($s))); $ar->map("GET", "/team/members/remove", Action::auth(fn(SessionHandle $s) => getTeamController()->displayDeleteMember($s)));
$ar->map("POST", "/team/members/remove", AppAction::auth(fn(SessionHandle $s) => getTeamController()->deleteMember($_POST, $s))); $ar->map("POST", "/team/members/remove", Action::auth(fn(SessionHandle $s) => getTeamController()->deleteMember($_POST, $s)));
return $ar; return $ar;
} }
function render(HttpResponse $response): void {
http_response_code($response->getCode());
foreach ($response->getHeaders() as $header => $value) {
header("$header: $value");
}
if ($response instanceof ViewHttpResponse) {
renderView($response);
} elseif ($response instanceof JsonHttpResponse) {
header('Content-type: application/json');
echo $response->getJson();
}
}
function renderView(ViewHttpResponse $response): void {
$file = $response->getFile();
$args = $response->getArguments();
switch ($response->getViewKind()) {
case ViewHttpResponse::REACT_VIEW:
send_react_front($file, $args);
break;
case ViewHttpResponse::TWIG_VIEW:
try {
$loader = new FilesystemLoader('../src/Views/');
$twig = new Environment($loader);
$twig->display($file, $args);
} catch (RuntimeError | SyntaxError | LoaderError $e) {
http_response_code(500);
echo "There was an error rendering your view, please refer to an administrator.\nlogs date: " . date("YYYD, d M Y H:i:s");
throw $e;
}
break;
}
}
function runAction(AppAction $action, array $params, MutableSessionHandle $session): HttpResponse {
global $basePath;
if ($action->isAuthRequired()) {
$account = $session->getAccount();
if ($account == null) {
// put in the session the initial url the user wanted to get
$session->setInitialTarget($_SERVER['REQUEST_URI']);
return HttpResponse::redirect($basePath . "/login");
}
}
return $action->run($params, $session);
}
function runMatch(array $match, MutableSessionHandle $session): HttpResponse {
if (!$match) {
return ViewHttpResponse::twig("error.html.twig", [
'failures' => [ValidationFail::notFound("Could not find page ${_SERVER['REQUEST_URI']}.")],
], HttpCodes::NOT_FOUND);
}
return runAction($match['target'], $match['params'], $session);
}
//this is a global variable //this is a global variable
$basePath = get_public_path(); $basePath = get_public_path();
render(runMatch(getRoutes()->match(), PhpSessionHandle::init())); App::render(App::runMatch(getRoutes()->match(), PhpSessionHandle::init()));

@ -0,0 +1,71 @@
<?php
namespace IQBall\Api;
use Exception;
use IQBall\Core\Action;
use IQBall\Core\Connection;
use IQBall\Core\Data\Account;
use IQBall\Core\Gateway\AccountGateway;
use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Http\JsonHttpResponse;
use IQBall\Core\Session\PhpSessionHandle;
use IQBall\Core\Validation\ValidationFail;
class API {
public static function render(HttpResponse $response): void {
http_response_code($response->getCode());
foreach ($response->getHeaders() as $header => $value) {
header("$header: $value");
}
if ($response instanceof JsonHttpResponse) {
header('Content-type: application/json');
echo $response->getJson();
} else {
throw new Exception("API returned a non-json response.");
}
}
/**
* @param mixed[] $match
* @return HttpResponse
* @throws Exception
*/
public static function handleMatch(array $match): HttpResponse {
if (!$match) {
return new JsonHttpResponse([ValidationFail::notFound("not found")]);
}
$action = $match['target'];
if (!$action instanceof Action) {
throw new Exception("routed action is not an AppAction object.");
}
$auth = null;
if ($action->isAuthRequired()) {
$auth = self::tryGetAuthorization();
if ($auth == null) {
return new JsonHttpResponse([ValidationFail::unauthorized("Missing or invalid 'Authorization' header.")]);
}
}
return $action->run($match['params'], $auth);
}
private static function tryGetAuthorization(): ?Account {
$headers = getallheaders();
// If no authorization header is set, try fallback to php session.
if (!isset($headers['Authorization'])) {
$session = PhpSessionHandle::init();
return $session->getAccount();
}
$token = $headers['Authorization'];
$gateway = new AccountGateway(new Connection(get_database()));
return $gateway->getAccountFromToken($token);
}
}

@ -1,46 +0,0 @@
<?php
namespace IQBall\Api;
use IQBall\Core\Data\Account;
use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Route\AbstractAction;
/**
* @extends AbstractAction<?Account>
*/
class ApiAction extends AbstractAction {
/**
* @param mixed[] $params
* @param ?Account $session
* @return HttpResponse
*/
public function run(array $params, $session): HttpResponse {
$params = array_values($params);
if ($this->isAuthRequired()) {
if ($session == null) {
throw new \Exception("action requires authorization.");
}
$params[] = $session;
}
return call_user_func_array($this->action, $params);
}
/**
* @param callable(mixed[]): HttpResponse $action
* @return ApiAction an action that does not require to have an authorization.
*/
public static function noAuth(callable $action): ApiAction {
return new ApiAction($action, false);
}
/**
* @param callable(mixed[]): HttpResponse $action
* @return ApiAction an action that does require to have an authorization.
*/
public static function auth(callable $action): ApiAction {
return new ApiAction($action, true);
}
}

@ -1,6 +1,6 @@
<?php <?php
namespace IQBall\Api; namespace IQBall\Api\Controller;
use IQBall\Core\Route\Control; use IQBall\Core\Route\Control;
use IQBall\Core\Http\HttpRequest; use IQBall\Core\Http\HttpRequest;

@ -1,6 +1,6 @@
<?php <?php
namespace IQBall\Api; namespace IQBall\Api\Controller;
use IQBall\Core\Route\Control; use IQBall\Core\Route\Control;
use IQBall\Core\Data\Account; use IQBall\Core\Data\Account;
@ -39,25 +39,4 @@ class APITacticController {
return HttpResponse::fromCode(HttpCodes::OK); return HttpResponse::fromCode(HttpCodes::OK);
}, true); }, true);
} }
public function newTactic(Account $account): HttpResponse {
return Control::runChecked([
"name" => [Validators::lenBetween(1, 50), Validators::nameWithSpaces()],
], function (HttpRequest $request) use ($account) {
$tactic = $this->model->makeNew($request["name"], $account->getId());
$id = $tactic->getId();
return new JsonHttpResponse(["id" => $id]);
}, true);
}
public function getTacticInfo(int $id, Account $account): HttpResponse {
$tactic_info = $this->model->get($id);
if ($tactic_info == null) {
return new JsonHttpResponse("could not find tactic #$id", HttpCodes::NOT_FOUND);
}
return new JsonHttpResponse($tactic_info);
}
} }

@ -0,0 +1,90 @@
<?php
namespace IQBall\App;
use IQBall\Core\Action;
use IQBall\Core\Http\HttpCodes;
use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Http\JsonHttpResponse;
use IQBall\Core\Session\MutableSessionHandle;
use IQBall\Core\Validation\ValidationFail;
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
use Twig\Loader\FilesystemLoader;
class App {
public static function render(HttpResponse $response): void {
http_response_code($response->getCode());
foreach ($response->getHeaders() as $header => $value) {
header("$header: $value");
}
if ($response instanceof ViewHttpResponse) {
self::renderView($response);
} elseif ($response instanceof JsonHttpResponse) {
header('Content-type: application/json');
echo $response->getJson();
}
}
private static function renderView(ViewHttpResponse $response): void {
$file = $response->getFile();
$args = $response->getArguments();
switch ($response->getViewKind()) {
case ViewHttpResponse::REACT_VIEW:
send_react_front($file, $args);
break;
case ViewHttpResponse::TWIG_VIEW:
try {
$loader = new FilesystemLoader('../src/App/Views/');
$twig = new Environment($loader);
$twig->display($file, $args);
} catch (RuntimeError | SyntaxError | LoaderError $e) {
http_response_code(500);
echo "There was an error rendering your view, please refer to an administrator.\nlogs date: " . date("YYYD, d M Y H:i:s");
throw $e;
}
break;
}
}
/**
* @param Action<MutableSessionHandle> $action
* @param mixed[] $params
* @param MutableSessionHandle $session
* @return HttpResponse
*/
private static function runAction(Action $action, array $params, MutableSessionHandle $session): HttpResponse {
global $basePath;
if ($action->isAuthRequired()) {
$account = $session->getAccount();
if ($account == null) {
// put in the session the initial url the user wanted to get
$session->setInitialTarget($_SERVER['REQUEST_URI']);
return HttpResponse::redirect($basePath . "/login");
}
}
return $action->run($params, $session);
}
/**
* @param array<string, mixed>|false $match
* @param MutableSessionHandle $session
* @return HttpResponse
*/
public static function runMatch($match, MutableSessionHandle $session): HttpResponse {
if (!$match) {
return ViewHttpResponse::twig("error.html.twig", [
'failures' => [ValidationFail::notFound("Could not find page ${_SERVER['REQUEST_URI']}.")],
], HttpCodes::NOT_FOUND);
}
return self::runAction($match['target'], $match['params'], $session);
}
}

@ -1,55 +0,0 @@
<?php
namespace IQBall\App;
use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Session\MutableSessionHandle;
use Exception;
use IQBall\Core\Route\AbstractAction;
/**
* A Front controller action
* @extends AbstractAction<MutableSessionHandle>
*/
class AppAction extends AbstractAction {
/**
* @param mixed[] $params
* @param MutableSessionHandle $session
* @return HttpResponse
* @throws Exception <p>
* thrown if this action is required to be authenticated, but the given session does not contain a logged-in account.
* </p>
* <p>
* Caller is supposed to ensure that the user is logged-in before, if `$this->isAuthRequired()` is true before
* running this action.
* </p>
*/
public function run(array $params, $session): HttpResponse {
$params = array_values($params);
if ($this->isAuthRequired()) {
if ($session->getAccount() == null) {
throw new Exception("action requires authorization.");
}
}
$params[] = $session;
return call_user_func_array($this->action, $params);
}
/**
* @param callable(mixed[]): HttpResponse $action
* @return AppAction an action that does not require to have an authorization.
*/
public static function noAuth(callable $action): AppAction {
return new AppAction($action, false);
}
/**
* @param callable(mixed[]): HttpResponse $action
* @return AppAction an action that does require to have an authorization.
*/
public static function auth(callable $action): AppAction {
return new AppAction($action, true);
}
}

@ -2,11 +2,11 @@
namespace IQBall\Core\Route; namespace IQBall\Core\Route;
use IQBall\App\ViewHttpResponse;
use IQBall\Core\Http\HttpCodes; use IQBall\Core\Http\HttpCodes;
use IQBall\Core\Http\HttpRequest; use IQBall\Core\Http\HttpRequest;
use IQBall\Core\Http\HttpResponse; use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Http\JsonHttpResponse; use IQBall\Core\Http\JsonHttpResponse;
use IQBall\Core\Http\ViewHttpResponse;
use IQBall\Core\Validation\ValidationFail; use IQBall\Core\Validation\ValidationFail;
use IQBall\Core\Validation\Validator; use IQBall\Core\Validation\Validator;

@ -4,7 +4,7 @@ namespace IQBall\App\Controller;
use IQBall\Core\Http\HttpRequest; use IQBall\Core\Http\HttpRequest;
use IQBall\Core\Http\HttpResponse; use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Http\ViewHttpResponse; use IQBall\App\ViewHttpResponse;
use IQBall\Core\Model\AuthModel; use IQBall\Core\Model\AuthModel;
use IQBall\Core\Session\MutableSessionHandle; use IQBall\Core\Session\MutableSessionHandle;
use IQBall\Core\Validation\ValidationFail; use IQBall\Core\Validation\ValidationFail;

@ -5,7 +5,7 @@ namespace IQBall\App\Controller;
use IQBall\Core\Data\TacticInfo; use IQBall\Core\Data\TacticInfo;
use IQBall\Core\Http\HttpCodes; use IQBall\Core\Http\HttpCodes;
use IQBall\Core\Http\HttpResponse; use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Http\ViewHttpResponse; use IQBall\App\ViewHttpResponse;
use IQBall\Core\Model\TacticModel; use IQBall\Core\Model\TacticModel;
use IQBall\Core\Session\SessionHandle; use IQBall\Core\Session\SessionHandle;
use IQBall\Core\Validator\TacticValidator; use IQBall\Core\Validator\TacticValidator;

@ -4,7 +4,7 @@ namespace IQBall\App\Controller;
use IQBall\Core\Http\HttpRequest; use IQBall\Core\Http\HttpRequest;
use IQBall\Core\Http\HttpResponse; use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Http\ViewHttpResponse; use IQBall\App\ViewHttpResponse;
use IQBall\Core\Model\TeamModel; use IQBall\Core\Model\TeamModel;
use IQBall\Core\Session\SessionHandle; use IQBall\Core\Session\SessionHandle;
use IQBall\Core\Validation\FieldValidationFail; use IQBall\Core\Validation\FieldValidationFail;

@ -3,7 +3,7 @@
namespace IQBall\App\Controller; namespace IQBall\App\Controller;
use IQBall\Core\Http\HttpResponse; use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Http\ViewHttpResponse; use IQBall\App\ViewHttpResponse;
use IQBall\Core\Model\TacticModel; use IQBall\Core\Model\TacticModel;
use IQBall\Core\Session\SessionHandle; use IQBall\Core\Session\SessionHandle;

@ -4,7 +4,7 @@ namespace IQBall\App\Controller;
use IQBall\Core\Http\HttpCodes; use IQBall\Core\Http\HttpCodes;
use IQBall\Core\Http\HttpResponse; use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Http\ViewHttpResponse; use IQBall\App\ViewHttpResponse;
use IQBall\Core\Model\TacticModel; use IQBall\Core\Model\TacticModel;
use IQBall\Core\Session\SessionHandle; use IQBall\Core\Session\SessionHandle;
use IQBall\Core\Validator\TacticValidator; use IQBall\Core\Validator\TacticValidator;

@ -1,6 +1,9 @@
<?php <?php
namespace IQBall\Core\Http; namespace IQBall\App;
use IQBall\Core\Http\HttpCodes;
use IQBall\Core\Http\HttpResponse;
class ViewHttpResponse extends HttpResponse { class ViewHttpResponse extends HttpResponse {
public const TWIG_VIEW = 0; public const TWIG_VIEW = 0;

@ -0,0 +1,56 @@
<?php
namespace IQBall\Core;
use IQBall\Core\Http\HttpResponse;
/**
* @template S session
*/
class Action {
/**
* @var callable(mixed[], S): HttpResponse $action action to call
*/
protected $action;
private bool $isAuthRequired;
/**
* @param callable(mixed[], S): HttpResponse $action
*/
protected function __construct(callable $action, bool $isAuthRequired) {
$this->action = $action;
$this->isAuthRequired = $isAuthRequired;
}
public function isAuthRequired(): bool {
return $this->isAuthRequired;
}
/**
* @param mixed[] $params
* @param S $session
* @return HttpResponse
*/
public function run(array $params, $session): HttpResponse {
$params = array_values($params);
$params[] = $session;
return call_user_func_array($this->action, $params);
}
/**
* @param callable(mixed[], S): HttpResponse $action
* @return Action<S> an action that does not require to have an authorization.
*/
public static function noAuth(callable $action): Action {
return new Action($action, false);
}
/**
* @param callable(mixed[], S): HttpResponse $action
* @return Action<S> an action that does require to have an authorization.
*/
public static function auth(callable $action): Action {
return new Action($action, true);
}
}

@ -1,36 +0,0 @@
<?php
namespace IQBall\Core\Route;
use IQBall\Core\Http\HttpResponse;
/**
* @template S session
*/
abstract class AbstractAction {
/**
* @var callable(mixed[]): HttpResponse $action action to call
*/
protected $action;
private bool $isAuthRequired;
/**
* @param callable(mixed[]): HttpResponse $action
*/
protected function __construct(callable $action, bool $isAuthRequired) {
$this->action = $action;
$this->isAuthRequired = $isAuthRequired;
}
public function isAuthRequired(): bool {
return $this->isAuthRequired;
}
/**
* @param mixed[] $params
* @param S $session
* @return HttpResponse
*/
public abstract function run(array $params, $session): HttpResponse;
}
Loading…
Cancel
Save