Skip to content

Commit

Permalink
Update Route system (add redirect command in route files); Fix BaseAc…
Browse files Browse the repository at this point in the history
…tionController (fix render if set arg 'skip_render')
  • Loading branch information
anthsnow committed May 19, 2022
1 parent 058146f commit e55c0e0
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 11 deletions.
4 changes: 3 additions & 1 deletion src/Core/Controllers/BaseActionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@ public function __construct() {
final public function render(string $action = "", array $options = [ 'layout_support' => true ]) {
// --- check skip in options ---
if (isset($options['skip_render'])
&& $options['skip_render'] === true)
&& $options['skip_render'] === true) {
$this->_isRendered = true;
return;
}
// --- check is already used ---
if ($this->_isRendered === true)
return;
Expand Down
61 changes: 59 additions & 2 deletions src/Core/Routes/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
namespace FlyCubePHP\Core\Routes;

use FlyCubePHP\HelperClasses\CoreHelper;
use GuiCore\MenuBar\ActionBase;

include_once 'RouteType.php';
include_once 'RouteRedirect.php';

/**
* Класс маршрута
Expand All @@ -24,14 +26,16 @@ class Route
private $_action; /**< название метода контроллера */
private $_as; /**< псевдоним для быстрого доступа к маршруту */
private $_constraints = []; /**< constraints для проверки параметров в динамической части маршрута (Пример маршрута: /ROUTE/:id) */
private $_redirect = null; /**< объект с сописанием перенаправления маршрута */

function __construct(int $type,
string $uri,
array $uriArgs,
string $controller,
string $action,
string $as = "",
array $constraints = []) {
string $as,
array $constraints,
/*RouteRedirect*/ $redirect = null) {
$this->_type = $type;
$this->_uri = $uri;
if (count(explode('?', $this->_uri)) > 1)
Expand All @@ -47,6 +51,10 @@ function __construct(int $type,
}
$this->_as = $as;
$this->_constraints = $constraints;

if (!is_null($redirect) && !$redirect instanceof RouteRedirect)
trigger_error("[Route] Append route redirect failed! Invalid redirect class!", E_USER_ERROR);
$this->_redirect = $redirect;
}

/**
Expand Down Expand Up @@ -184,6 +192,35 @@ public function constraints(): array {
return $this->_constraints;
}

/**
* Задано ли перенаправление маршрута?
* @return bool
*/
public function hasRedirect(): bool {
return !is_null($this->_redirect);
}

/**
* Маршрут перенаправления
* @param string $currentUri - текущий маршрут с параметрами
* @return string
*/
public function redirectUri(string $currentUri): string {
if (is_null($this->_redirect))
return "";
return $this->makeRedirectUri($currentUri);
}

/**
* HTTP статус перенаправления
* @return int
*/
public function redirectStatus(): int {
if (is_null($this->_redirect))
return -1;
return $this->_redirect->status();
}

/**
* Метод разбора аргументов
*/
Expand Down Expand Up @@ -249,4 +286,24 @@ private function prepareConstraint(string $constraint): string {
$tmpConstraint = $tmpConstraint . '$';
return $tmpConstraintStart . $tmpConstraint . $tmpConstraintEnd;
}

/**
* Создать корректный маршрут перенаправления
* @param string $currentUri
* @return string
*/
private function makeRedirectUri(string $currentUri): string {
if (is_null($this->_redirect))
return "";
$tmpUri = $this->_redirect->uri();
if ($this->_redirect->hasUriArgs()) {
$tmpArgs = $this->routeArgsFromUri($currentUri);
foreach ($tmpArgs as $key => $value) {
$argName = "%{".$key."}";
if (strpos($tmpUri, $argName) !== false)
$tmpUri = str_replace($argName, $value, $tmpUri);
}
}
return $tmpUri;
}
}
18 changes: 18 additions & 0 deletions src/Core/Routes/RouteCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use FlyCubePHP\Core\Controllers\BaseController;
use FlyCubePHP\Core\Controllers\BaseActionController;
use FlyCubePHP\Core\Logger\Logger;
use FlyCubePHP\HelperClasses\CoreHelper;

class RouteCollector
{
Expand Down Expand Up @@ -237,6 +238,23 @@ public function processingRequest() {
if (is_null($tmpCurRoute))
$tmpCurRoute = $this->processingFailed("Not found route: [$httpM] $httpUrl", 404);

// --- check redirect ---
if ($tmpCurRoute->hasRedirect()) {
// --- clear all buffers ---
while (ob_get_level() !== 0)
ob_end_clean();
// --- send redirect ---
$redirectUri = $tmpCurRoute->redirectUri(self::currentRouteUri());
if (!preg_match("/^(http:\/\/|https:\/\/).*/", $redirectUri)) {
$redirectUri = self::makeValidUrl($redirectUri);
$redirectUri = self::currentHostUri() . $redirectUri;
}
$redirectStatus = $tmpCurRoute->redirectStatus();
http_response_code($redirectStatus);
header("Location: $redirectUri", true, $redirectStatus);
die();
}

// --- processing controller ---
$tmpClassName = $tmpCurRoute->controller();
$tmpClassAct = $tmpCurRoute->action();
Expand Down
38 changes: 38 additions & 0 deletions src/Core/Routes/RouteRedirect.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace FlyCubePHP\Core\Routes;

class RouteRedirect
{
private $_uri;
private $_status;

function __construct(string $uri, int $status = 303) {
$this->_uri = $uri;
$this->_status = $status;
}

/**
* URL маршрута перенаправления
* @return string
*/
public function uri(): string {
return $this->_uri;
}

/**
* Код HTTP
* @return int
*/
public function status(): int {
return $this->_status;
}

/**
* Есть ли у маршрута входные аргументы?
* @return bool
*/
public function hasUriArgs(): bool {
return preg_match('/\%\{([a-zA-Z0-9_]*)\}/i', $this->uri());
}
}
48 changes: 41 additions & 7 deletions src/Core/Routes/RoutesHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
include_once 'RouteCollector.php';

use FlyCubePHP\Core\Routes\Route;
use FlyCubePHP\Core\Routes\RouteRedirect;
use FlyCubePHP\Core\Routes\RouteType;
use FlyCubePHP\Core\Routes\RouteCollector;

Expand All @@ -24,7 +25,7 @@ function root(string $controller, string $action) {
trigger_error("Make ROOT route failed! Empty controller name or action name!", E_USER_ERROR);

$tmpController = $controller."Controller";
$route = new Route(RouteType::GET, "/", [], $tmpController, $action, 'root');
$route = new Route(RouteType::GET, "/", [], $tmpController, $action, 'root', []);
RouteCollector::instance()->appendRoute($route);
}

Expand Down Expand Up @@ -268,6 +269,30 @@ function delete(string $uri, array $args = []) {
}
}

/**
* Создать перенаправления маршрута
* @param string $uri - новый маршрут
* @param int $status - HTTP статус код
* @return RouteRedirect
*
* ==== Examples
*
* get("/stories", [ 'to' => redirect("/articles") ] );
*
* get("/stories/:name", [ 'to' => redirect("/articles/%{name}") ] );
*
* get("/stories/:name", [ 'to' => redirect("/articles/%{name}", 302) ] );
*/
function redirect(string $uri, int $status = 303): RouteRedirect {
// --- check uri ---
if (empty($uri))
trigger_error("Make route redirect failed! Empty uri!", E_USER_ERROR);
if ($status < 300 || $status >= 400)
trigger_error("Make route redirect failed! Invalid HTTP status code ($status)!", E_USER_ERROR);

return new RouteRedirect($uri, $status);
}

/**
* Задать HTTP url
* @param string $uri
Expand Down Expand Up @@ -329,13 +354,22 @@ function make_route(string $uri, array $args = []) {
trigger_error("Make $tmpTypeStr route failed! Invalid URI!", E_USER_ERROR);

// --- check args ---
$tmpRedirect = null;
if (isset($args['to']) && !empty($args['to'])) {
$tmpTo = explode('#', $args['to']);
if (count($tmpTo) != 2)
trigger_error("Make $tmpTypeStr route failed! Invalid argument 'to'!", E_USER_ERROR);
if (is_string($args['to'])) {
$tmpTo = explode('#', $args['to']);
if (count($tmpTo) != 2)
trigger_error("Make $tmpTypeStr route failed! Invalid argument 'to'!", E_USER_ERROR);

$tmpController = $tmpTo[0];
$tmpAct = $tmpTo[1];
$tmpController = $tmpTo[0];
$tmpAct = $tmpTo[1];
} else if ($args['to'] instanceof RouteRedirect) {
$tmpController = "";
$tmpAct = "";
$tmpRedirect = $args['to'];
} else {
trigger_error("Make $tmpTypeStr route failed! Invalid argument 'to'!", E_USER_ERROR);
}
} else if (isset($args['controller']) && !empty($args['controller'])
&& isset($args['action']) && !empty($args['action'])) {
$tmpController = $args['controller'];
Expand Down Expand Up @@ -368,6 +402,6 @@ function make_route(string $uri, array $args = []) {

// --- create & add ---
$tmpController .= "Controller";
$route = new Route($tmpType, $tmpUri, $args, $tmpController, $tmpAct, $tmpAs, $tmpConstraints);
$route = new Route($tmpType, $tmpUri, $args, $tmpController, $tmpAct, $tmpAs, $tmpConstraints, $tmpRedirect);
RouteCollector::instance()->appendRoute($route);
}
18 changes: 17 additions & 1 deletion templates/routes.php.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,17 @@
* 6. Append application delete URL:
* #> delete(string $uri, array $args = [])
*
* 7. Append application URL with redirect (set redirect for get/post/put/patch/delete routes)
* #> redirect(string $uri, int $status = 303)
*
* 7.1. HTTP status codes for GET: 301, 302, 303
* 7.2. HTTP status codes for POST/PUT/PATCH/DELETE: 307, 308
*
* NOTE: the controller name is written without ending 'Controller'!
*
* Supported input arguments:
*
* - [string] to - The name of the controller and the action separated '#' (Test#show)
* - [string] to - The name of the controller and the action separated '#' (Test#show), or 'redirect' command
* - [string] controller - The name of the controller
* - [string] action - The name of the controller action
* - [string] as - Alias for quick access to the route (define is automatically generated)
Expand Down Expand Up @@ -63,6 +69,16 @@
* - show - The name of the controller action (public method)
* - test - Alias for quick access to url (use define 'test_url')
*
* Redirect examples:
*
* For GET:
* #> get('/test1/:id', [ 'to' => 'Test#test_1']);
* #> get('/test2/:id', [ 'to' => redirect('/test1/%{id}', 301) ]);
*
* For POST:
* #> post('/test1/:id', [ 'to' => 'Test#test_1']);
* #> post('/test2/:id', [ 'to' => redirect('/test1/%{id}', 308) ]);
*
*/

namespace FlyCubePHP;
Expand Down

0 comments on commit e55c0e0

Please sign in to comment.