From 0f026de5da5ff550a81cb48fb04f00b44aa16f60 Mon Sep 17 00:00:00 2001 From: Mal <=> Date: Tue, 18 Aug 2020 11:46:03 +0200 Subject: [PATCH] Database transactions implemented --- .../controller/FingerprintPostController.php | 13 +++++++-- data/classes/core/DatabaseInterface.php | 20 +++++++++++++ data/classes/core/MySqlDatabase.php | 28 +++++++++++++++++-- 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/data/classes/controller/FingerprintPostController.php b/data/classes/controller/FingerprintPostController.php index 77dbc00..076927e 100644 --- a/data/classes/controller/FingerprintPostController.php +++ b/data/classes/controller/FingerprintPostController.php @@ -21,26 +21,35 @@ final class FingerprintPostController extends AbstractController { parent::handle(); + $db = new MySqlDatabase(); $json = json_decode($this->requestBody); - $fingerprint = new Fingerprint(); + $fingerprint = new Fingerprint(null, $db); try { $fingerprint->setFingerprint($json->fingerprint); $fingerprint->setUserId($json->userId); + + if (!$db->hasTransaction()) { + $db->startTransaction(); + } + $fingerprint->Save(); $qrCode = new QrCode($fingerprint->getFingerprintId(), $fingerprint->getFingerprint()); $qrCode->generate(); $qrCode->save(); + $db->commit(); + $this->response->setParameter('fingerprintId', $fingerprint->getFingerprintId()); } catch (QrCodeException $e) { - $fingerprint->Delete(); + $db->rollback(); $this->response->setParameter('success', false); $this->response->setStatus(ServerStatus::INTERNAL_ERROR); $this->response->setMessage('An error occured during qr code creation!'); } catch (Throwable $e) { + $db->rollback(); $this->catchDatabaseException($e->getMessage(), $json); } } diff --git a/data/classes/core/DatabaseInterface.php b/data/classes/core/DatabaseInterface.php index 795ab51..68b6d7c 100644 --- a/data/classes/core/DatabaseInterface.php +++ b/data/classes/core/DatabaseInterface.php @@ -53,6 +53,26 @@ interface DatabaseInterface */ public function Count(string $table, array $conditions = []): int; + /* + * Returns if there's an open transaction. + */ + public function hasTransaction(): bool; + + /* + * Starts a transaction that can later be committed or rolled back. + */ + public function startTransaction(): void; + + /* + * Quits a current transaction without saving. + */ + public function rollback(): void; + + /* + * Saves and exits a current transaction. + */ + public function commit(): void; + /** * Returns the primary key from the last inserted row. */ diff --git a/data/classes/core/MySqlDatabase.php b/data/classes/core/MySqlDatabase.php index 5fe4533..b72e19b 100644 --- a/data/classes/core/MySqlDatabase.php +++ b/data/classes/core/MySqlDatabase.php @@ -2,14 +2,15 @@ declare(strict_types=1); -class MySqlDatabase implements DatabaseInterface +final class MySqlDatabase implements DatabaseInterface { private const CHARS_ALLOWED_IN_TABLE_NAMES = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_-'; private ?PDO $connection; private ?PDOStatement $cursor; + private bool $isTransactionOpen = false; - public function __construct( + public function __construct( string $hostname = Setting::MYSQL_HOST, string $user = Setting::MYSQL_USER, string $password = Setting::MYSQL_PASSWORD, @@ -236,6 +237,29 @@ class MySqlDatabase implements DatabaseInterface return (int)$result[0]['count(*)']; } + public function hasTransaction(): bool + { + return $this->isTransactionOpen; + } + + public function startTransaction(): void + { + $this->connection->beginTransaction(); + $this->isTransactionOpen = true; + } + + public function rollback(): void + { + $this->connection->rollBack(); + $this->isTransactionOpen = false; + } + + public function commit(): void + { + $this->connection->commit(); + $this->isTransactionOpen = false; + } + /** * {@inheritDoc} */