diff options
| author | Kevin J Hoerr <kjhoerr@protonmail.com> | 2017-07-08 13:58:36 -0400 |
|---|---|---|
| committer | Kevin J Hoerr <kjhoerr@protonmail.com> | 2017-07-08 13:58:36 -0400 |
| commit | 692a4a48d5f8f74a06d0b5890e31887a76a903f3 (patch) | |
| tree | 9fc39dc20be3b8a442031b85beffc7baa583143b | |
| parent | 0364d790e9764d91489db21805064ceeb23e3e22 (diff) | |
| download | august-offensive-692a4a48d5f8f74a06d0b5890e31887a76a903f3.tar.gz august-offensive-692a4a48d5f8f74a06d0b5890e31887a76a903f3.tar.bz2 august-offensive-692a4a48d5f8f74a06d0b5890e31887a76a903f3.zip | |
Improve exception handling, introduce autoloading
| -rw-r--r-- | index.php | 43 | ||||
| -rw-r--r-- | private/Controller/Controller.php | 44 | ||||
| -rw-r--r-- | private/Model/Connection.php | 3 | ||||
| -rw-r--r-- | private/View/Main.php | 26 | ||||
| -rw-r--r-- | private/View/Output.php | 34 |
5 files changed, 124 insertions, 26 deletions
@@ -4,21 +4,38 @@ declare(strict_types=1); namespace AugustOffensive; -// y u no autoload -include 'private/Model/Connection.php'; -include 'private/Model/Query.php'; -include 'private/Model/Result.php'; -include 'private/View/Main.php'; -include 'private/Controller/Controller.php'; +// Borrowed and modified from PSR-4 Closure Example +spl_autoload_register( + function ($class) { + $prefix = 'AugustOffensive\\'; + $relative_class = substr($class, strlen($prefix)); + + // find file in /private/ in respective namespace path + $file = __DIR__ . '/private/' . str_replace('\\', '/', $relative_class) . '.php'; + + // if the file exists, require it + if (file_exists($file)) { + require $file; + } + } +); use AugustOffensive\View; -use AugustOffensive\Model; +use AugustOffensive\Controller; + +try { + // initiate connection and build front-end + $connection = Controller\Controller::initiateConnection(); + $view = new View\Main($connection); -// initiate connection and build front-end -$connection = new Model\Connection(); -$view = new View\Main($connection); + // get results of query from front-end + $result = $view->generateResult(); -// get results of query from front-end -$result = $view->generateResult(); + echo $result; +} catch (\Exception $err) { + // catch all exceptions and let the controller generate the error + $error = Controller\Controller::errorResult($err); -echo $result; + // pass generated error result to output + echo View\Main::generateOutput($error); +} diff --git a/private/Controller/Controller.php b/private/Controller/Controller.php index 188345a..586be15 100644 --- a/private/Controller/Controller.php +++ b/private/Controller/Controller.php @@ -12,6 +12,20 @@ use AugustOffensive\Model; class Controller { /** + * Initiates connection with the database. + * + * While errors are ideally handled by the controller, this instantiation + * will likely throw a \PDOException which should be handled by the front- + * end due to this being a fatal error and generally unrecoverable. + * + * @return Model\Connection + */ + public static function initiateConnection (): Model\Connection + { + return new Model\Connection(); + } + + /** * Creates and returns a Query object. * * If the creation results in an error, a different query object is @@ -29,9 +43,9 @@ class Controller array $content ): Model\Query { try { - return new Model\Query ($path, $request, $content); + return new Model\Query($path, $request, $content); } catch (\Exception $err) { - return new Model\Query (array(), "", array("ERROR" => $err->getMessage())); + return new Model\Query(array(), "", array("ERROR" => $err->getMessage())); } } @@ -48,9 +62,31 @@ class Controller array $result ): Model\Result { try { - return new Model\Result ($resultType, $result); + return new Model\Result($resultType, $result); } catch (\Exception $err) { - return new Model\Result ("ERROR", array($err->getMessage())); + return new Model\Result("ERROR", array($err->getMessage())); + } + } + + /** + * Obtain the error result based on the exception that was thrown. + * + * @param \Exception $err the error that was thrown. + * + * @return Model\Result + */ + public static function errorResult (\Exception $err): Model\Result + { + $errorType = ""; + // Juggle error: objective is to sort error type + try { + throw $err; + } catch (\PDOException $e) { + $errorType = "DATABASE_ERROR"; + } catch (\Exception $e) { + $errorType = "ERROR"; } + + return new Model\Result($errorType, array("error" => $err->getMessage())); } } diff --git a/private/Model/Connection.php b/private/Model/Connection.php index 48cf4fb..4afa330 100644 --- a/private/Model/Connection.php +++ b/private/Model/Connection.php @@ -19,6 +19,7 @@ class Connection public function __construct () { // Establish connection to db + // breaks side-effect rule include 'creds.php'; try { @@ -34,7 +35,7 @@ class Connection } catch (\PDOException $err) { // we destroy $cred as quickly as possible $cred = null; - die(json_encode(array("Result-Type" => "ERROR", "Content" => array($err->getMessage())))); + throw $err; // throw for Controller to catch } return $this; } diff --git a/private/View/Main.php b/private/View/Main.php index 1dcd760..746c2bb 100644 --- a/private/View/Main.php +++ b/private/View/Main.php @@ -18,6 +18,9 @@ class Main /** @var Model\Result $result the Result object to be sent to the client. */ private $result; + /** @var string TYPE The type of output the client should receive. */ + private const TYPE = "json"; + /** * Prepares the output and environment for the front end of the service. * @@ -27,8 +30,6 @@ class Main */ public function __construct (Model\Connection $connection) { - header("Content-Type: application/json"); - $this->query = Controller\Controller::createQuery( explode('/', trim($_SERVER['PATH_INFO'] ?? '/api', '/')), $_SERVER['REQUEST_METHOD'], @@ -58,7 +59,7 @@ class Main } /** - * Communicates with the controller to generate the JSON result. + * Communicates with the controller to generate the output. * * @return string */ @@ -69,10 +70,19 @@ class Main array() ); - // generate result - return json_encode(array( - "Result-Type" => $this->result->getResultType(), - "Content" => $this->result->getResult() - )); + return self::generateOutput($this->result); + } + + /** + * Creates output of the result based on the defined constant TYPE. + * + * @param Model\Result $result The result to be sent to the client. + * + * @return string + */ + public static function generateOutput (Model\Result $result): string + { + $type = self::TYPE; + return Output::$type($result); } } diff --git a/private/View/Output.php b/private/View/Output.php new file mode 100644 index 0000000..fe42c15 --- /dev/null +++ b/private/View/Output.php @@ -0,0 +1,34 @@ +<?php + +declare(strict_types=1); + +namespace AugustOffensive\View; + +use AugustOffensive\Model; + +/** + * Output formats for Results that are returned to the client. + */ +class Output +{ + /** + * Formats the result into JSON. + * + * @param Model\Result $result The result to return to the client. + * @param bool $prepare Whether to set the content type of the response (default true). + * + * @return string + */ + public static function json (Model\Result $result, bool $prepare = true): string + { + // breaks side effect rule? + if ($prepare) { + header("Content-Type: application/json"); + } + + return json_encode(array( + "Result-Type" => $result->getResultType(), + "Content" => $result->getResult() + )); + } +} |
