Skip to content
This repository has been archived by the owner on Aug 1, 2021. It is now read-only.

Commit

Permalink
Using PHP 8 features
Browse files Browse the repository at this point in the history
  • Loading branch information
o-alquimista committed Apr 26, 2021
1 parent 98b758a commit bf26aa4
Show file tree
Hide file tree
Showing 12 changed files with 52 additions and 131 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Fragments aims to be a small PHP framework for web applications. Keep in mind th
It has its own router component and is heavily inspired by [Symfony](https://symfony.com/).

## Requirements
- PHP 8
- [Composer](https://getcomposer.org/)
- PHP XML extension. This package is called `php-xml` on Ubuntu.

Expand Down
29 changes: 12 additions & 17 deletions src/Fragments/Component/Bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,8 @@ public function processRequest(Request $request): Response
{
try {
$route = $this->router->getRouteFromRequest($request);

$controller = $route->getController();
$action = $route->getAction();
$parameters = $route->getParameters();

$controller = new $controller;
$response = $controller->{$action}(...$parameters);
$controller = new $route->controller;
$response = $controller->{$route->action}(...$route->parameters);
} catch (HttpException $exception) {
$response = $this->createCustomErrorResponse($exception);
} catch (\Throwable $exception) {
Expand All @@ -61,23 +56,23 @@ public function processRequest(Request $request): Response

private function createCustomErrorResponse(HttpException $exception): Response
{
if ($exception->getStatusCode() === 500) {
if ($exception->statusCode === 500) {
error_log($exception);
}

if (file_exists('../templates/error')) {
if (file_exists("../templates/error/{$exception->getStatusCode()}.php")) {
$response = $this->templating->render("error/{$exception->getStatusCode()}.php");
$response->setStatusCode($exception->getStatusCode());
if (file_exists("../templates/error/{$exception->statusCode}.php")) {
$response = $this->templating->render("error/{$exception->statusCode}.php");
$response->statusCode = $exception->statusCode;
} else {
$response = $this->templating->render('error/error.php', [
'statusCode' => $exception->getStatusCode()
'statusCode' => $exception->statusCode
]);

$response->setStatusCode($exception->getStatusCode());
$response->statusCode = $exception->statusCode;
}
} else {
$response = new Response($exception->getMessage(), $exception->getStatusCode());
$response = new Response(content: $exception->getMessage(), statusCode: $exception->statusCode);
}

return $response;
Expand All @@ -92,17 +87,17 @@ private function createServerErrorResponse(\Throwable $exception): Response
if (file_exists("../templates/error/500.php")) {
// Render code-specific template
$response = $this->templating->render("error/500.php");
$response->setStatusCode(500);
$response->statusCode = 500;
} else {
// Render generic template
$response = $this->templating->render('error/error.php', [
'statusCode' => 500
]);

$response->setStatusCode(500);
$response->statusCode = 500;
}
} else {
$response = new Response('Something went wrong.', 500);
$response = new Response(content: 'Something went wrong.', statusCode: 500);
}

return $response;
Expand Down
4 changes: 2 additions & 2 deletions src/Fragments/Component/Html/Templating.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ private function buildContext(): array
return $context;
}

public function escape(string $value): string
public function escape(string $string): string
{
return htmlspecialchars($value, ENT_QUOTES);
return htmlspecialchars($string, flags: ENT_QUOTES);
}

public function getCsrfToken(string $name): string
Expand Down
7 changes: 1 addition & 6 deletions src/Fragments/Component/Http/Exception/HttpException.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,12 @@

class HttpException extends \RuntimeException
{
private $statusCode;
public int $statusCode;

public function __construct(int $statusCode, string $message = '', \Throwable $previous = null, ?int $code = 0)
{
$this->statusCode = $statusCode;

parent::__construct($message, $code, $previous);
}

public function getStatusCode(): int
{
return $this->statusCode;
}
}
2 changes: 1 addition & 1 deletion src/Fragments/Component/Http/RedirectResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
namespace Fragments\Component\Http;

/**
* An object-oriented representation of the HTTP response.
* Conveniently performs a redirection to the specified URL.
*/
class RedirectResponse extends Response
{
Expand Down
6 changes: 3 additions & 3 deletions src/Fragments/Component/Http/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
*/
class Request
{
public $post;
public array $post;

public $get;
public array $get;

public $server;
public array $server;

public function __construct()
{
Expand Down
11 changes: 3 additions & 8 deletions src/Fragments/Component/Http/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
*/
class Response
{
public $content;
public string $content;

public $statusCode;
public int $statusCode;

public $headers;
public array $headers;

public function __construct(string $content = '', int $statusCode = 200, array $headers = [])
{
Expand All @@ -44,11 +44,6 @@ public function send()
$this->sendHeaders();
$this->sendContent();
}

public function setStatusCode(int $statusCode)
{
$this->statusCode = $statusCode;
}

private function sendHeaders()
{
Expand Down
70 changes: 5 additions & 65 deletions src/Fragments/Component/Routing/Model/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,22 @@ class Route
/**
* The route identifier.
*/
private $id;
public string $id;

/**
* The associated URL.
*/
private $path;
public string $path;

/**
* The fully qualified class name of the controller.
*/
private $controller;
public string $controller;

/**
* The class method to be executed.
*/
private $action;
public string $action;

/**
* The request methods supported.
Expand All @@ -51,55 +51,7 @@ class Route
/**
* Route parameters injected by the router.
*/
private $parameters = [];

public function getId(): string
{
return $this->id;
}

public function setId(string $id): self
{
$this->id = $id;

return $this;
}

public function getPath(): string
{
return $this->path;
}

public function setPath(string $path): self
{
$this->path = $path;

return $this;
}

public function getController(): string
{
return $this->controller;
}

public function setController(string $controller): self
{
$this->controller = $controller;

return $this;
}

public function getAction(): string
{
return $this->action;
}

public function setAction(string $action): self
{
$this->action = $action;

return $this;
}
public array $parameters = [];

public function getMethods(): array
{
Expand All @@ -114,16 +66,4 @@ public function setMethods(string $methods): self

return $this;
}

public function getParameters(): array
{
return $this->parameters;
}

public function setParameters(array $parameters): self
{
$this->parameters = $parameters;

return $this;
}
}
8 changes: 4 additions & 4 deletions src/Fragments/Component/Routing/Parser/XMLParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ public function getRoutes(): array

foreach ($file as $entry) {
$route = new Route;
$route->setId($entry->id);
$route->setPath($entry->path);
$route->id = $entry->id;
$route->path = $entry->path;
$route->controller = $entry->controller;
$route->action = $entry->action;
$route->setMethods($entry->methods);
$route->setController($entry->controller);
$route->setAction($entry->action);

$routes[] = $route;
}
Expand Down
36 changes: 17 additions & 19 deletions src/Fragments/Component/Routing/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ public function getRouteFromRequest(Request $request): Route
$uri = $request->server['REQUEST_URI'];

// Ignore GET parameters in the URI, if present
if (strpos($uri, '?') !== false) {
$uri = strstr($uri, '?', true);
if (strpos(haystack: $uri, needle: '?') !== false) {
$uri = strstr(haystack: $uri, needle: '?', before_needle: true);
}

// Eliminate the trailing forward slash from the URI
Expand All @@ -51,24 +51,22 @@ public function getRouteFromRequest(Request $request): Route
}

foreach ($routes as $route) {
if ($route->getPath() != $uri) {
$routePath = $route->getPath();

if ($route->path !== $uri) {
// Are there any wildcards in the route path?
if (!preg_match('/{(\w+)}/', $routePath)) {
if (false == preg_match('/{(\w+)}/', $route->path)) {
continue;
}

// Replace all wildcards with capturing groups
$regex = preg_replace('/{(\w+)}/', '(\w+)', $routePath);
$regex = preg_replace('/{(\w+)}/', '(\w+)', $route->path);

// Escape forward slashes in the path
$regex = preg_replace('/\//', '\/', $regex);

// Add start and end regex delimiters
$regex = '/^' . $regex . '$/';

if (preg_match($regex, $uri, $matches)) {
if (preg_match(pattern: $regex, subject: $uri, matches: $matches)) {
// The first item is not a wildcard value, so remove it
array_shift($matches);

Expand All @@ -78,47 +76,47 @@ public function getRouteFromRequest(Request $request): Route
$parameters[] = $parameter;
}

$route->setParameters($parameters);
$route->parameters = $parameters;
} else {
continue;
}
}

if (!in_array($request->server['REQUEST_METHOD'], $route->getMethods())) {
throw new HttpException(405, 'Method not allowed.');
if (false === in_array(needle: $request->server['REQUEST_METHOD'], haystack: $route->getMethods())) {
throw new HttpException(statusCode: 405, message: 'Method not allowed.');
}

return $route;
}

throw new HttpException(404, 'Route not found.');
throw new HttpException(statusCode: 404, message: 'Route not found.');
}

private function getRouteById(string $routeId): Route
{
$routes = $this->parser->getRoutes();

foreach ($routes as $route) {
if ($route->getId() == $routeId) {
if ($route->id === $routeId) {
return $route;
}
}

throw new HttpException(404, 'Route not found.');
throw new HttpException(statusCode: 404, message: 'Route not found.');
}

public function generateUrl(string $routeId, array $parameters = []): string
{
$route = $this->getRouteById($routeId);
$routePath = $route->getPath();
$routePath = $route->path;

// If there are no wildcards in this route path, return it as is
if (!preg_match('/{(\w+)}/', $routePath)) {
if (false == preg_match('/{(\w+)}/', $routePath)) {
return $routePath;
}

// Break the route path in segments, without forward slashes
$routePath = explode('/', trim($routePath, '/'));
$routePath = explode(delimiter: '/', string: trim($routePath, '/'));

/*
* Iterate over the parameters, trying to find a corresponding wildcard
Expand All @@ -127,12 +125,12 @@ public function generateUrl(string $routeId, array $parameters = []): string
*/
foreach ($parameters as $parameterName => $parameterValue) {
foreach ($routePath as $pathKey => $pathSegment) {
$routePath[$pathKey] = preg_replace('/{' . $parameterName . '}/', $parameterValue, $pathSegment);
$routePath[$pathKey] = preg_replace(pattern: '/{' . $parameterName . '}/', replacement: $parameterValue, subject: $pathSegment);
}
}

// Rebuild the path as a string, restoring forward slashes
$routePath = '/' . implode('/', $routePath);
$routePath = '/' . implode(glue: '/', pieces: $routePath);

if (preg_match('/{(\w+)}/', $routePath)) {
throw new \RuntimeException('Failed to generate URL due to missing or invalid parameters: ' . $routePath);
Expand Down
Loading

0 comments on commit bf26aa4

Please sign in to comment.