From 57eefb62eeade626670cd98ca3302a6e2377003b Mon Sep 17 00:00:00 2001 From: divyesh000 Date: Tue, 7 May 2024 16:09:17 +0400 Subject: [PATCH 1/9] replace _404 to Error in controller & replace redirect to home with a user-friendly error message when registration fails & remove _404 controller and replace it with a generic error handling method --- src/controllers/Error.php | 22 ++++++++++++++++++++++ src/controllers/Register.php | 6 +++--- src/controllers/_404.php | 24 ------------------------ src/core/Database.php | 4 ++-- 4 files changed, 27 insertions(+), 29 deletions(-) create mode 100644 src/controllers/Error.php delete mode 100644 src/controllers/_404.php diff --git a/src/controllers/Error.php b/src/controllers/Error.php new file mode 100644 index 0000000..9f77d56 --- /dev/null +++ b/src/controllers/Error.php @@ -0,0 +1,22 @@ +view( + 'Error', + template_title: "Error", + template_meta_description: $error_message, + enableIndexing: false + ); + } +} 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/_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/Database.php b/src/core/Database.php index a516ed1..ce00ba0 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())->index("Sorry, we're unable to process your request at the moment. Please try again later."); die(); } else { // if PHPUnit is running, re-throw the exception to allow it to propagate From 81ff491f9dcb8010a3c78d5ed1db47598f57eae2 Mon Sep 17 00:00:00 2001 From: divyesh000 Date: Tue, 7 May 2024 16:51:17 +0400 Subject: [PATCH 2/9] refactor client model's create method to use prepared statements and begin/commit transactions for user and client table inserts --- src/models/Client.php | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/models/Client.php b/src/models/Client.php index 7266e52..da134ac 100644 --- a/src/models/Client.php +++ b/src/models/Client.php @@ -130,30 +130,53 @@ public function save(): bool } // get data to be inserted to user table - $user_data = parent::toArray(); + $user_data = $this->toArray(); unset($user_data['user_id']); + unset($user_data['street']); + unset($user_data['city']); + unset($user_data['district_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($user_data); - if ($inserted_id === null) { + + if (!$success) { + $conn->rollBack(); 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(); + return false; + } - return true; // insertion was successful + $conn->commit(); + $conn = null; + return true; } public function updateUser(bool $updatePassword = false): bool From bc61346a12e82be521c412090607c8abd161b3db Mon Sep 17 00:00:00 2001 From: creme332 <65414576+creme332@users.noreply.github.com> Date: Wed, 8 May 2024 10:34:11 +0400 Subject: [PATCH 3/9] refactor save() - set $conn to null before exiting function - no need to use toArray() --- src/models/Client.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/models/Client.php b/src/models/Client.php index da134ac..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,28 +129,27 @@ public function save(): bool return false; } - // get data to be inserted to user table - $user_data = $this->toArray(); - unset($user_data['user_id']); - unset($user_data['street']); - unset($user_data['city']); - unset($user_data['district_id']); - // start transaction $conn = self::connect(); $conn->beginTransaction(); // perform insertion to user table $query = <<< EOL - INSERT INTO user(email, first_name, password, phone_no, last_name) - VALUES(:email, :first_name, :password, :phone_no, :last_name); + 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($user_data); - + $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 (!$success) { $conn->rollBack(); + $conn = null; return false; } @@ -158,8 +157,8 @@ public function save(): bool // perform insertion to client table $query = <<< EOL - INSERT INTO client(user_id, street, city, district_id) - VALUES(:user_id, :street, :city, :district_id); + INSERT INTO client(user_id, street, city, district_id) + VALUES(:user_id, :street, :city, :district_id); EOL; $stm = $conn->prepare($query); $success = $stm->execute([ @@ -171,6 +170,7 @@ public function save(): bool if (!$success) { $conn->rollBack(); + $conn = null; return false; } From 2bb11c11d0eba9e848831b886a7d9c6b81d89f54 Mon Sep 17 00:00:00 2001 From: creme332 <65414576+creme332@users.noreply.github.com> Date: Wed, 8 May 2024 12:05:12 +0400 Subject: [PATCH 4/9] create a new dynamic error page --- src/views/404.php | 4 --- src/views/Error.php | 71 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 4 deletions(-) delete mode 100644 src/views/404.php create mode 100644 src/views/Error.php 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 From d056f0b1cfab40fe09e2d57ee2f1e6fb058c72fc Mon Sep 17 00:00:00 2001 From: creme332 <65414576+creme332@users.noreply.github.com> Date: Wed, 8 May 2024 12:06:00 +0400 Subject: [PATCH 5/9] create a new error controller with reusable error messages --- src/controllers/Error.php | 45 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/src/controllers/Error.php b/src/controllers/Error.php index 9f77d56..e85b024 100644 --- a/src/controllers/Error.php +++ b/src/controllers/Error.php @@ -10,13 +10,54 @@ class Error { use Controller; - public function index(string $error_message = ''): void + private array $view_data; + + public function __construct() + { + $this->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", - template_meta_description: $error_message, 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(); + } } From 3d5ae11b70225e7421f81fd15e2d208cc6611514 Mon Sep 17 00:00:00 2001 From: creme332 <65414576+creme332@users.noreply.github.com> Date: Wed, 8 May 2024 12:06:54 +0400 Subject: [PATCH 6/9] replace occurrences of _404 controller with Error controller --- src/controllers/Cart.php | 2 +- src/controllers/Home.php | 2 +- src/controllers/Login.php | 2 +- src/controllers/Password.php | 2 +- src/controllers/Product.php | 4 ++-- src/controllers/Profile.php | 2 +- src/controllers/Shop.php | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) 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/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/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; } From 147b3418d50382779e5d634135aad7646dd5f735 Mon Sep 17 00:00:00 2001 From: creme332 <65414576+creme332@users.noreply.github.com> Date: Wed, 8 May 2024 12:08:56 +0400 Subject: [PATCH 7/9] add global exception handler, use Error controller instead of _404 --- src/core/App.php | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) 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(); } } } From b3341ff839ed4cc6c9b342f49dc136c3407a25f0 Mon Sep 17 00:00:00 2001 From: creme332 <65414576+creme332@users.noreply.github.com> Date: Wed, 8 May 2024 12:09:48 +0400 Subject: [PATCH 8/9] use error view as default view instead of 404 --- src/core/Controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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(); From a313b70e12c7c08b1ca95a9a39c86ed820039abc Mon Sep 17 00:00:00 2001 From: creme332 <65414576+creme332@users.noreply.github.com> Date: Wed, 8 May 2024 12:10:19 +0400 Subject: [PATCH 9/9] call handleDatabaseError instead of writing custom message --- src/core/Database.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Database.php b/src/core/Database.php index ce00ba0..0e32b12 100644 --- a/src/core/Database.php +++ b/src/core/Database.php @@ -26,7 +26,7 @@ protected static function connect(): PDO } catch (PDOException $e) { // if PHPUnit is not running, handle the exception if (!defined('PHPUNIT_STEAMY_TESTSUITE')) { - (new Error())->index("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