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

Commit

Permalink
Added custom exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
o-alquimista committed Mar 20, 2020
1 parent 025c1ff commit db84d0a
Show file tree
Hide file tree
Showing 13 changed files with 238 additions and 39 deletions.
30 changes: 30 additions & 0 deletions src/Fragments/Bundle/Exception/AccessDeniedHttpException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

/**
* Copyright 2019-2020 Douglas Silva (0x9fd287d56ec107ac)
*
* This file is part of Fragments.
*
* Fragments is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fragments. If not, see <https://www.gnu.org/licenses/>.
*/

namespace Fragments\Bundle\Exception;

class AccessDeniedHttpException extends HttpException
{
public function __construct(string $message = null, \Throwable $previous = null, int $code = 0)
{
parent::__construct(403, $message, $previous, $code);
}
}
39 changes: 39 additions & 0 deletions src/Fragments/Bundle/Exception/HttpException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

/**
* Copyright 2019-2020 Douglas Silva (0x9fd287d56ec107ac)
*
* This file is part of Fragments.
*
* Fragments is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fragments. If not, see <https://www.gnu.org/licenses/>.
*/

namespace Fragments\Bundle\Exception;

class HttpException extends \RuntimeException
{
private $statusCode;

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

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

public function getStatusCode(): int
{
return $this->statusCode;
}
}
32 changes: 32 additions & 0 deletions src/Fragments/Bundle/Exception/MethodNotAllowedHttpException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/**
* Copyright 2019-2020 Douglas Silva (0x9fd287d56ec107ac)
*
* This file is part of Fragments.
*
* Fragments is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fragments. If not, see <https://www.gnu.org/licenses/>.
*/

namespace Fragments\Bundle\Exception;

class MethodNotAllowedHttpException extends HttpException
{
public function __construct(\Throwable $previous = null, int $code = 0)
{
$message = 'Method not allowed.';

parent::__construct(405, $message, $previous, $code);
}
}
30 changes: 30 additions & 0 deletions src/Fragments/Bundle/Exception/NotFoundHttpException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

/**
* Copyright 2019-2020 Douglas Silva (0x9fd287d56ec107ac)
*
* This file is part of Fragments.
*
* Fragments is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fragments. If not, see <https://www.gnu.org/licenses/>.
*/

namespace Fragments\Bundle\Exception;

class NotFoundHttpException extends HttpException
{
public function __construct(string $message = null, \Throwable $previous = null, int $code = 0)
{
parent::__construct(404, $message, $previous, $code);
}
}
30 changes: 30 additions & 0 deletions src/Fragments/Bundle/Exception/ServerErrorHttpException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

/**
* Copyright 2019-2020 Douglas Silva (0x9fd287d56ec107ac)
*
* This file is part of Fragments.
*
* Fragments is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fragments. If not, see <https://www.gnu.org/licenses/>.
*/

namespace Fragments\Bundle\Exception;

class ServerErrorHttpException extends HttpException
{
public function __construct(string $message = null, \Throwable $previous = null, int $code = 0)
{
parent::__construct(500, $message, $previous, $code);
}
}
4 changes: 2 additions & 2 deletions src/Fragments/Component/CsrfTokenManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
namespace Fragments\Component;

use Fragments\Component\SessionManagement\Session;
use Fragments\Bundle\Exception\AccessDeniedHttpException;

/**
* Manage tokens used to prevent CSRF attacks.
Expand Down Expand Up @@ -64,8 +65,7 @@ public function isTokenValid(string $tokenReceived, string $targetId): bool
$targetId = self::PREFIX . $targetId;

if (false === $this->session->exists($targetId)) {
// FIXME: throw access denied exception
return false;
throw new AccessDeniedHttpException('The CSRF token identifier could not be found.');
}

$tokenStored = $this->session->get($targetId);
Expand Down
45 changes: 45 additions & 0 deletions src/Fragments/Component/ExceptionHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

/**
* Copyright 2019-2020 Douglas Silva (0x9fd287d56ec107ac)
*
* This file is part of Fragments.
*
* Fragments is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fragments. If not, see <https://www.gnu.org/licenses/>.
*/

namespace Fragments\Component;

/**
* Converts all PHP errors to exceptions.
*/
class ExceptionHandler
{
public function handler($severity, $message, $file, $line)
{
if (!(error_reporting() & $severity)) {
// This error code is not included in error_reporting
return;
}

// FIXME: handle different severities differently

throw new \ErrorException($message, 0, $severity, $file, $line);
}

public function setHandler()
{
set_error_handler([$this, 'handler']);
}
}
10 changes: 3 additions & 7 deletions src/Fragments/Component/PDOBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

namespace Fragments\Component;

use Fragments\Bundle\Exception\ServerErrorHttpException;

class PDOBuilder
{
public function getConnection(): \PDO
Expand All @@ -38,8 +40,7 @@ public function getConnection(): \PDO
$config['username'], $config['password'], $options
);
} catch(\PDOException $error) {
// FIXME: throw server error exception
exit;
throw new ServerErrorHttpException('Failed to connect to the database.');
}

return $pdo;
Expand All @@ -49,11 +50,6 @@ private function getConfig(): array
{
$config = parse_ini_file('../config/database.ini');

if (false === $config) {
// FIXME: throw server error exception
exit;
}

// FIXME: test for missing configuration keys
return $config;
}
Expand Down
36 changes: 14 additions & 22 deletions src/Fragments/Component/Routing/RequestMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

namespace Fragments\Component\Routing;

use Fragments\Bundle\Exception\MethodNotAllowedHttpException;

/**
* Request matcher
*
Expand All @@ -44,12 +46,12 @@ class RequestMatcher
/**
* When a matching route is found, its name is stored here.
*/
public $matchedRouteName = null;
public $matchedRouteName;

/**
* The parameter to be passed to the controller.
*/
public $parameter = null;
public $parameter;

public function __construct($routeCollection, RequestContext $context)
{
Expand All @@ -66,34 +68,20 @@ public function match()
}
}

private function testWildcard(Route $route)
private function testWildcard(Route $route): bool
{
if ($this->containsWildcard($route) === true) {
if ($this->matchPathWithWildcard($route) === true) {
return true;
}

return false;
} else {
if ($this->matchPathWithoutWildcard($route) == true) {
return true;
}

return false;
return $this->matchPathWithWildcard($route);
}

return $this->matchPathWithoutWildcard($route);
}

/**
* Test the URI and its wildcard against the registered route
* and retrieve the parameter.
*/
private function matchPathWithWildcard(Route $route): bool {
if (!in_array($this->context->requestMethod, $route->methods)) {
// FIXME: throw access denied exception

return false;
}

$path = $route->path;
$pattern = '/\/{alpha}/';
$replacement = '';
Expand All @@ -103,7 +91,11 @@ private function matchPathWithWildcard(Route $route): bool {
// Using ~ as the regex delimiter to prevent conflict
$prefix = '~^' . $prefix . '\/' . '(?<alpha>[a-zA-Z0-9_]+)$~';

if (preg_match($prefix, $this->context->uri, $match) == true) {
if (true == preg_match($prefix, $this->context->uri, $match)) {
if (!in_array($this->context->requestMethod, $route->methods)) {
throw new MethodNotAllowedHttpException;
}

$this->parameter = $match['alpha'];

return true;
Expand All @@ -122,7 +114,7 @@ private function matchPathWithoutWildcard(Route $route): bool
}

if (!in_array($this->context->requestMethod, $route->methods)) {
return false;
throw new MethodNotAllowedHttpException;
}

return true;
Expand Down
10 changes: 5 additions & 5 deletions src/Fragments/Component/Routing/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

namespace Fragments\Component\Routing;

use Fragments\Bundle\Exception\NotFoundHttpException;

/**
* The router controller.
*
Expand All @@ -41,13 +43,11 @@ public function start()
$matcher = new RequestMatcher($routeCollection, $context);
$matcher->match();

if (is_null($matcher->matchedRouteName)) {
// FIXME: throw not found exception

return;
if (!$matcher->matchedRouteName) {
throw new NotFoundHttpException('The page you were looking for could not be found.');
}

if (!is_null($matcher->parameter)) {
if ($matcher->parameter) {
$this->parameter = $matcher->parameter;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@

namespace Fragments\Component\SessionManagement\Init;

use Fragments\Bundle\Exception\ServerErrorHttpException;

class SessionStrict extends AbstractSessionInit
{
public function init()
{
$this->options['use_strict_mode'] = 1;
if (!session_start($this->options)) {
// FIXME: throw server error exception
throw new ServerErrorHttpException('Failed to start the session.');
}
}
}
Loading

0 comments on commit db84d0a

Please sign in to comment.