diff --git a/src/controllers/Cart.php b/src/controllers/Cart.php index cf5c2d8..a65ce86 100644 --- a/src/controllers/Cart.php +++ b/src/controllers/Cart.php @@ -57,7 +57,7 @@ private function validateURL(): bool private function handleInvalidURL(): void { if (!$this->validateURL()) { - (new _404())->index(); + (new Error())->handlePageNotFoundError(); die(); } } diff --git a/src/controllers/Error.php b/src/controllers/Error.php new file mode 100644 index 0000000..e85b024 --- /dev/null +++ b/src/controllers/Error.php @@ -0,0 +1,63 @@ +view_data['error_message'] = '500 - Internal server error'; + $this->view_data['extended_error_message'] = 'Something bad happened'; + } + + public function handleDatabaseError(): void + { + $this->view_data['extended_error_message'] = 'Unable to connect to database.'; + + $this->view( + 'Error', + $this->view_data, + template_title: "Error", + enableIndexing: false + ); + } + + public function handlePageNotFoundError($extended_error_message = 'Ensure that you have properly typed the URL.' + ): void { + $this->view_data['error_message'] = '404 - Page not found'; + $this->view_data['extended_error_message'] = $extended_error_message; + + $this->view( + 'Error', + $this->view_data, + template_title: "Page not found", + enableIndexing: false + ); + } + + public function handleUnknownError(): void + { + $this->view_data['extended_error_message'] = 'The server has encountered a situation + it does not know how to handle.'; + + $this->view( + 'Error', + $this->view_data, + template_title: "Unknown error", + enableIndexing: false + ); + } + + public function index(): void + { + $this->handlePageNotFoundError(); + } +} diff --git a/src/controllers/Home.php b/src/controllers/Home.php index 11d45c8..c9b230e 100644 --- a/src/controllers/Home.php +++ b/src/controllers/Home.php @@ -19,7 +19,7 @@ private function validateURL(): bool private function handleInvalidURL(): void { if (!$this->validateURL()) { - (new _404())->index(); + (new Error())->handlePageNotFoundError(); die(); } } diff --git a/src/controllers/Login.php b/src/controllers/Login.php index 6855eb6..633cc0c 100644 --- a/src/controllers/Login.php +++ b/src/controllers/Login.php @@ -81,7 +81,7 @@ private function validateURL(): bool private function handleInvalidURL(): void { if (!$this->validateURL()) { - (new _404())->index(); + (new Error())->handlePageNotFoundError(); die(); } } diff --git a/src/controllers/Password.php b/src/controllers/Password.php index d83a9c2..4f2298f 100644 --- a/src/controllers/Password.php +++ b/src/controllers/Password.php @@ -189,7 +189,7 @@ public function index(): void } // if url follows some other format display error page - (new _404())->index(); + (new Error())->handlePageNotFoundError(); } } diff --git a/src/controllers/Product.php b/src/controllers/Product.php index f6674cd..d1bcb20 100644 --- a/src/controllers/Product.php +++ b/src/controllers/Product.php @@ -243,7 +243,7 @@ private function validateURL(): bool private function handleInvalidURL(): void { if (!$this->validateURL()) { - (new _404())->index(); + (new Error())->handlePageNotFoundError('Product does not exist'); die(); } } @@ -254,7 +254,7 @@ public function index(): void // if product was not found, display error page if (empty($this->product)) { - (new _404())->index(); + (new Error())->handlePageNotFoundError('Product does not exist.'); return; } diff --git a/src/controllers/Profile.php b/src/controllers/Profile.php index 562ef1a..f707854 100644 --- a/src/controllers/Profile.php +++ b/src/controllers/Profile.php @@ -150,7 +150,7 @@ private function validateURL(): bool private function handleInvalidURL(): void { if (!$this->validateURL()) { - (new _404())->index(); + (new Error())->handlePageNotFoundError(); die(); } } diff --git a/src/controllers/Register.php b/src/controllers/Register.php index 9360133..56562c9 100644 --- a/src/controllers/Register.php +++ b/src/controllers/Register.php @@ -115,8 +115,8 @@ private function handleFormSubmission(): void Utility::redirect('login'); } - // TODO: redirect to some error page - Utility::redirect('home'); + (new Error())->index("An error occurred while processing your registration. Please try again later."); + die(); } else { $this->loadDataToForm($form_data); } @@ -148,7 +148,7 @@ private function validateURL(): bool private function handleInvalidURL(): void { if (!$this->validateURL()) { - (new _404())->index(); + (new Error())->index("Page not found"); die(); } } diff --git a/src/controllers/Shop.php b/src/controllers/Shop.php index 2146b87..caccf5c 100644 --- a/src/controllers/Shop.php +++ b/src/controllers/Shop.php @@ -111,7 +111,7 @@ public function index(): void // check if URL is not /shop if (Utility::getURL() !== "shop") { // let 404 controller handle this - (new _404())->index(); + (new Error())->handlePageNotFoundError(); return; } diff --git a/src/controllers/_404.php b/src/controllers/_404.php deleted file mode 100644 index e3b4a48..0000000 --- a/src/controllers/_404.php +++ /dev/null @@ -1,24 +0,0 @@ -view( - '404', - template_title: "Page not found", - template_meta_description: "Oops! It seems you've wandered off the beaten path. - Let us guide you back to the aromatic world of Steamy Sips. - Return to our delightful offerings or explore anew. Flavorful surprises await your next click.", - enableIndexing: false - ); - } -} diff --git a/src/core/App.php b/src/core/App.php index 9b11190..1f50d01 100644 --- a/src/core/App.php +++ b/src/core/App.php @@ -4,17 +4,33 @@ namespace Steamy\Core; -use Steamy\Controller\_404; +use Steamy\Controller\Error; use Steamy\Controller\API; +use Throwable; class App { + + /** + * Global exception handler + * @param Throwable $exception + * @return void + */ + public function exception_handler(Throwable $exception): void + { +// echo "Uncaught exception: ", $exception->getMessage(), "\n"; + (new Error())->handleUnknownError(); + } + + /** * Calls appropriate controller class to deal with URL. * @return void */ public function loadController(): void { + set_exception_handler(array($this, "exception_handler")); + $URL = Utility::splitURL(); switch ($URL[0]) { @@ -28,8 +44,8 @@ public function loadController(): void // call appropriate controller (new $controllerClassName())->index(); } else { - // Fallback to 404 controller - (new _404())->index(); + // Display error page + (new Error())->handlePageNotFoundError(); } } } diff --git a/src/core/Controller.php b/src/core/Controller.php index e4532f6..911642a 100644 --- a/src/core/Controller.php +++ b/src/core/Controller.php @@ -86,7 +86,7 @@ public function view( if (file_exists($view_file_path)) { include $view_file_path; } else { - include __DIR__ . '/../views/404.php'; + include __DIR__ . '/../views/Error.php'; } $template_content = ob_get_contents(); ob_end_clean(); diff --git a/src/core/Database.php b/src/core/Database.php index a516ed1..0e32b12 100644 --- a/src/core/Database.php +++ b/src/core/Database.php @@ -7,6 +7,7 @@ use PDO; use PDOException; use stdClass; +use Steamy\Controller\Error; trait Database { @@ -25,8 +26,7 @@ protected static function connect(): PDO } catch (PDOException $e) { // if PHPUnit is not running, handle the exception if (!defined('PHPUNIT_STEAMY_TESTSUITE')) { - // TODO: Display a user-friendly error message - Utility::show("Sorry, we're unable to process your request at the moment. Please try again later."); + (new Error())->handleDatabaseError(); die(); } else { // if PHPUnit is running, re-throw the exception to allow it to propagate diff --git a/src/models/Client.php b/src/models/Client.php index 7266e52..1603709 100644 --- a/src/models/Client.php +++ b/src/models/Client.php @@ -120,7 +120,7 @@ public function deleteUser(): void public function save(): bool { // if attributes are invalid, exit - if (count($this->validate()) > 0) { + if (!empty($this->validate())) { return false; } @@ -129,31 +129,54 @@ public function save(): bool return false; } - // get data to be inserted to user table - $user_data = parent::toArray(); - unset($user_data['user_id']); + // start transaction + $conn = self::connect(); + $conn->beginTransaction(); // perform insertion to user table - $inserted_id = $this->insert($user_data, 'user'); + $query = <<< EOL + INSERT INTO user(email, first_name, password, phone_no, last_name) + VALUES(:email, :first_name, :password, :phone_no, :last_name); + EOL; + $stm = $conn->prepare($query); + $success = $stm->execute([ + 'email' => $this->email, + 'first_name' => $this->first_name, + 'password' => $this->password, + 'phone_no' => $this->phone_no, + 'last_name' => $this->last_name + ]); - if ($inserted_id === null) { + if (!$success) { + $conn->rollBack(); + $conn = null; return false; } - $this->user_id = $inserted_id; + $this->user_id = (int)$conn->lastInsertId(); - // get data to be inserted to client table - $client_data = [ + // perform insertion to client table + $query = <<< EOL + INSERT INTO client(user_id, street, city, district_id) + VALUES(:user_id, :street, :city, :district_id); + EOL; + $stm = $conn->prepare($query); + $success = $stm->execute([ 'user_id' => $this->user_id, 'street' => $this->address->getStreet(), 'city' => $this->address->getCity(), 'district_id' => $this->address->getDistrictID() - ]; + ]); - // perform insertion to client table - $this->insert($client_data, $this->table); + if (!$success) { + $conn->rollBack(); + $conn = null; + return false; + } - return true; // insertion was successful + $conn->commit(); + $conn = null; + return true; } public function updateUser(bool $updatePassword = false): bool diff --git a/src/views/404.php b/src/views/404.php deleted file mode 100644 index 8e96205..0000000 --- a/src/views/404.php +++ /dev/null @@ -1,4 +0,0 @@ -
-

Whoops 😢

-

404 Page Not Found

-
\ No newline at end of file diff --git a/src/views/Error.php b/src/views/Error.php new file mode 100644 index 0000000..cc8278d --- /dev/null +++ b/src/views/Error.php @@ -0,0 +1,71 @@ + + +
+
+
+
+

Oops! 😢

+

+
+

+ + + Go home + +
+ +
+ + +
+
+
\ No newline at end of file