Skip to content

Commit

Permalink
revamped router: typed path params, groups
Browse files Browse the repository at this point in the history
  • Loading branch information
donwilson committed Sep 20, 2023
1 parent 4dcd712 commit 5ed0565
Show file tree
Hide file tree
Showing 21 changed files with 606 additions and 269 deletions.
2 changes: 0 additions & 2 deletions src/Magnetar/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
use Magnetar\Log\LogServiceProvider;
use Magnetar\Router\RouterServiceProvider;

// @TODO use Magnetar\Helpers\DeferrableServiceInterface;

/**
* The core application class
*
Expand Down
2 changes: 1 addition & 1 deletion src/Magnetar/Container/BoundMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ protected static function getMethodDependencies(
): array {
$dependencies = [];

foreach (static::getCallReflector($callback)->getParameters() as $parameter) {
foreach(static::getCallReflector($callback)->getParameters() as $parameter) {
static::addDependencyForCallParameter(
$container,
$parameter,
Expand Down
8 changes: 0 additions & 8 deletions src/Magnetar/Database/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -407,12 +407,4 @@ public function fetchOne(): array {
// get a single row
return $this->adapter->get_row($query, $params);
}

/**
* @TMP Debug function
* @return string
*/
public function debugQueryParams(): string {
return print_r($this->buildQueryAndParams(), true);
}
}
6 changes: 3 additions & 3 deletions src/Magnetar/Helpers/Facades/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
* @method header(string $name): ?string;
* @method hasHeader(string $name): bool;
* @method path(): string;
* @method getMethod(): ?string;
* @method method(): ?Magnetar\Router\Enums\HTTPMethodEnum;
* @method assignOverrideParameters(array $parameters): void;
* @method getParameter(string $name, mixed $default=null): mixed;
* @method getParameters(): array;
* @method parameter(string $name, mixed $default=null): mixed;
* @method parameters(): array;
* @method body(): string;
*
* @see Magnetar\Http\Request
Expand Down
20 changes: 11 additions & 9 deletions src/Magnetar/Helpers/Facades/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@
use Magnetar\Helpers\Facades\Facade;

/**
* @method group(string $prefixPath, callable $callback): void;
* @method processRequest(Magnetar\Http\Request $request): Magnetar\Http\Response;
* @method any(string $pattern, callable|array|null $callback=null): void;
* @method get(string $pattern, callable|array|null $callback=null): void;
* @method post(string $pattern, callable|array|null $callback=null): void;
* @method put(string $pattern, callable|array|null $callback=null): void;
* @method patch(string $pattern, callable|array|null $callback=null): void;
* @method delete(string $pattern, callable|array|null $callback=null): void;
* @method head(string $pattern, callable|array|null $callback=null): void;
* @method option(string $pattern, callable|array|null $callback=null): void;
* @method attachContext(Magnetar\Router\RouteCollection $collection): void;
* @method detachContext(): void;
* @method isTrailingSlashOptional(): bool;
* @method any(string $pattern, callable|array|null $callback=null): Magnetar\Router\Route;
* @method get(string $pattern, callable|array|null $callback=null): Magnetar\Router\Route;
* @method post(string $pattern, callable|array|null $callback=null): Magnetar\Router\Route;
* @method put(string $pattern, callable|array|null $callback=null): Magnetar\Router\Route;
* @method patch(string $pattern, callable|array|null $callback=null): Magnetar\Router\Route;
* @method delete(string $pattern, callable|array|null $callback=null): Magnetar\Router\Route;
* @method options(string $pattern, callable|array|null $callback=null): Magnetar\Router\Route;
* @method group(string $pathPrefix, callable $callback): void;
*
* @see Magnetar\Router\Router
*/
Expand Down
47 changes: 45 additions & 2 deletions src/Magnetar/Helpers/TypedEnumHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ public static function getType(mixed $value, TypedEnum|null $default=null): Type
* Get a type by it's name. This accepts loosely typed names, such as 'int' or 'integer' for Int, or 'bool' or 'boolean' for Boolean
* @param string $named_type The name of the type to get
* @param mixed $default The default value to return if the type is unknown. If null, an exception will be thrown
* @return Typed The type
* @return TypedEnum The type
*
* @throws Exception If the type is unknown and no default value is provided
*
* @see Magnetar\Helpers\Enums\Typed
* @see Magnetar\Helpers\Enums\TypedEnum
*/
public static function typeByName(string $named_type, mixed $default=null): TypedEnum {
return match($named_type) {
Expand Down Expand Up @@ -135,4 +135,47 @@ public static function allNames(): array {
'void',
];
}

/**
* Cast a variable based on the specified TypedEnum
* @param TypedEnum $type The type to cast the variable to
* @param mixed $value The value to cast
* @return mixed
*/
public static function castTypedVariable(
TypedEnum $type,
mixed $value
): mixed {
// return the type
return match($type) {
// booleans
TypedEnum::Boolean => (bool)$value,

// integers
TypedEnum::Int => (int)$value,

// floats
TypedEnum::Float => (float)$value,

// strings
TypedEnum::String => (string)$value,

// arrays
TypedEnum::Array => $value,

// objects
TypedEnum::Object => $value,

// resources
TypedEnum::Resource => $value,

// null
TypedEnum::Null => null,

//'callable' => TypedEnum::Callable,
//'mixed' => TypedEnum::Mixed,
//'void' => TypedEnum::Void,
default => $value
};
}
}
1 change: 0 additions & 1 deletion src/Magnetar/Http/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ public function process(Request $request): Response {
->then($this->sendRequestToRouter());

// send to client
// @TODO currently doesnt work because of the way the router is set up
$response->send();
} catch(Throwable $e) {
$this->recordException($e);
Expand Down
113 changes: 39 additions & 74 deletions src/Magnetar/Http/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@

namespace Magnetar\Http;

//use Magnetar\Router\Route;
use Magnetar\Router\Enums\HTTPMethodEnum;
use Magnetar\Router\Helpers\HTTPMethodEnumResolver;

class Request {
//protected ?Route $route = null;

/**
* The requested path (without query string)
* @var string
Expand All @@ -30,7 +29,7 @@ class Request {
* The request method
* @var string|null
*/
protected ?string $method = null;
protected ?HTTPMethodEnum $method = null;

/**
* Request headers
Expand All @@ -43,28 +42,41 @@ class Request {
* @param string $path The requested path (without query string)
*/
public function __construct() {
// set request method
$this->processRequestMethod();

// parse the request path and query string
$this->processRequestPath();



// @TODO massive cleanup






// record request headers
$this->recordHeaders();
}

/**
* Process the request method
* @return void
*/
protected function processRequestMethod(): void {
// set request method
$this->method = HTTPMethodEnumResolver::resolve(
$_SERVER['REQUEST_METHOD'] ?? null,
HTTPMethodEnum::GET
);
}

/**
* Process the request path
* @return void
*/
protected function processRequestPath(): void {
$path = $_SERVER['REQUEST_URI'];

// sanitize request path
$path = ltrim($path, "/");
$path = '/'. ltrim($path, "/");
$path = rtrim($path, '?&');

$this->path = $path;

// set request method
$this->method = $_SERVER['REQUEST_METHOD'] ?? null;

if(false !== ($q_pos = strpos($this->path, '?'))) {
// request has ?, save to request and parse parameters
parse_str(
Expand All @@ -75,29 +87,6 @@ public function __construct() {
// chop off query string from request path
$this->path = substr($this->path, 0, $q_pos);
}


// record request headers
$this->recordHeaders();

//// set base parameters (any created with URI arguments)
//$this->parameters = $_REQUEST;

//// override any existing parameters set by URI arguments
//if(!empty($override_parameters)) {
// if(!is_array($override_parameters)) {
// //parse_str($override_parameters, $override_parameters);
// throw new \Exception("Request was provided invalid routed parameters");
// }
//
// foreach($override_parameters as $name => $value) {
// if("" === ($name = strtolower(trim($name)))) {
// continue;
// }
//
// $this->parameters[ $name ] = $value;
// }
//}
}

/**
Expand Down Expand Up @@ -171,14 +160,15 @@ public function path(): string {

/**
* Get the request method
* @return string|null
* @return ?HTTPMethodEnum
*/
public function getMethod(): ?string {
public function method(): ?HTTPMethodEnum {
return $this->method;
}

/**
* Pass in parameters from the route that override parameters found in URI query params (eg those found in ?...)
* Pass in parameters from the route that override parameters found in URI query params (eg those found in ?...).
* Called by Router::processRequest()
* @param array $parameters Assoc array of arameters to override
* @return void
*/
Expand All @@ -198,23 +188,19 @@ public function assignOverrideParameters(array $parameters): void {
* @param mixed $default Optional. Return this if requested parameter isn't set
* @return mixed
*/
public function getParameter(string $name, mixed $default=null): mixed {
if("" === ($name = strtolower(trim($name)))) {
return $default;
}

if(!isset($this->parameters[ $name ])) {
return $default;
}
public function parameter(string $name, mixed $default=null): mixed {
//if("" === ($name = strtolower(trim($name)))) {
// return $default;
//}

return $this->parameters[ $name ];
return $this->parameters[ $name ] ?? $default;
}

/**
* Get all parameters from the request
* @return array
*/
public function getParameters(): array {
public function parameters(): array {
return $this->parameters;
}

Expand All @@ -225,25 +211,4 @@ public function getParameters(): array {
public function body(): string {
return file_get_contents('php://input') ?: '';
}

/**
* Get the route that was matched
* @return Route|null
*/
/* public function getRoute(): ?Route {
return $this->route;
} */

/**
* Set the route that was matched
* @param Route $route The route that was matched
* @return void
*/
/* public function setRoute(Route $route): void {
if(!is_null($this->route)) {
return;
}
$this->route = $route;
} */
}
3 changes: 2 additions & 1 deletion src/Magnetar/Http/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ public function setBody(string $body=''): self {
* @return void
*/
public function json(array $body): self {
// @TODO turn into a factory method
// @TODO turn into a factory method that clones itself and returns
// a JsonResponse object instead

$this->header('Content-Type', 'application/json');

Expand Down
4 changes: 2 additions & 2 deletions src/Magnetar/Pipeline/Pipeline.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public function then(Closure $destination): mixed {
// eg: from the core of the onion outwards
array_reverse($this->pipes),

// create a closure that will call the next pipe in the chain
// create a closure that will call the next pipe in the pipeline
$this->carry(),

// create a closure that will call the destination callback
Expand Down Expand Up @@ -118,7 +118,7 @@ protected function prepDestination(Closure $destination): Closure {
}

/**
* Create a closure for the next pipe in the chain
* Create a closure for the next pipe in the pipeline
* @return Closure
*
* @throws Exception
Expand Down
1 change: 0 additions & 1 deletion src/Magnetar/Router/Enums/HTTPMethodEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,5 @@ enum HTTPMethodEnum {
case DELETE;
case OPTIONS;
case HEAD;
//case TRACE;
case CONNECT;
}
10 changes: 10 additions & 0 deletions src/Magnetar/Router/Exceptions/InvalidMethodException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace Magnetar\Router\Exceptions;

use Exception;

class InvalidMethodException extends Exception {

}
13 changes: 13 additions & 0 deletions src/Magnetar/Router/Exceptions/RouteNotFoundException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php
declare(strict_types=1);

namespace Magnetar\Router\Exceptions;

use Exception;

/**
* Exception thrown when the router cannot find a route matching the request
*/
class RouteNotFoundException extends Exception {

}
1 change: 0 additions & 1 deletion src/Magnetar/Router/Helpers/HTTPMethodEnumResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ public static function resolve(string $method, mixed $default=null): HTTPMethodE
'DELETE' => HTTPMethodEnum::DELETE,
'OPTIONS' => HTTPMethodEnum::OPTIONS,
'HEAD' => HTTPMethodEnum::HEAD,
'TRACE' => HTTPMethodEnum::TRACE,
'CONNECT' => HTTPMethodEnum::CONNECT,
default => $default ?? throw new Exception('Unknown HTTP method: '. $method)
};
Expand Down
Loading

0 comments on commit 5ed0565

Please sign in to comment.