Database transactions implemented

This commit is contained in:
Mal 2020-08-18 11:46:03 +02:00
parent adc1c38d54
commit 0f026de5da
3 changed files with 57 additions and 4 deletions

View File

@ -21,26 +21,35 @@ final class FingerprintPostController extends AbstractController
{ {
parent::handle(); parent::handle();
$db = new MySqlDatabase();
$json = json_decode($this->requestBody); $json = json_decode($this->requestBody);
$fingerprint = new Fingerprint(); $fingerprint = new Fingerprint(null, $db);
try { try {
$fingerprint->setFingerprint($json->fingerprint); $fingerprint->setFingerprint($json->fingerprint);
$fingerprint->setUserId($json->userId); $fingerprint->setUserId($json->userId);
if (!$db->hasTransaction()) {
$db->startTransaction();
}
$fingerprint->Save(); $fingerprint->Save();
$qrCode = new QrCode($fingerprint->getFingerprintId(), $fingerprint->getFingerprint()); $qrCode = new QrCode($fingerprint->getFingerprintId(), $fingerprint->getFingerprint());
$qrCode->generate(); $qrCode->generate();
$qrCode->save(); $qrCode->save();
$db->commit();
$this->response->setParameter('fingerprintId', $fingerprint->getFingerprintId()); $this->response->setParameter('fingerprintId', $fingerprint->getFingerprintId());
} catch (QrCodeException $e) { } catch (QrCodeException $e) {
$fingerprint->Delete(); $db->rollback();
$this->response->setParameter('success', false); $this->response->setParameter('success', false);
$this->response->setStatus(ServerStatus::INTERNAL_ERROR); $this->response->setStatus(ServerStatus::INTERNAL_ERROR);
$this->response->setMessage('An error occured during qr code creation!'); $this->response->setMessage('An error occured during qr code creation!');
} catch (Throwable $e) { } catch (Throwable $e) {
$db->rollback();
$this->catchDatabaseException($e->getMessage(), $json); $this->catchDatabaseException($e->getMessage(), $json);
} }
} }

View File

@ -53,6 +53,26 @@ interface DatabaseInterface
*/ */
public function Count(string $table, array $conditions = []): int; 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. * Returns the primary key from the last inserted row.
*/ */

View File

@ -2,12 +2,13 @@
declare(strict_types=1); declare(strict_types=1);
class MySqlDatabase implements DatabaseInterface final class MySqlDatabase implements DatabaseInterface
{ {
private const CHARS_ALLOWED_IN_TABLE_NAMES = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_-'; private const CHARS_ALLOWED_IN_TABLE_NAMES = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_-';
private ?PDO $connection; private ?PDO $connection;
private ?PDOStatement $cursor; private ?PDOStatement $cursor;
private bool $isTransactionOpen = false;
public function __construct( public function __construct(
string $hostname = Setting::MYSQL_HOST, string $hostname = Setting::MYSQL_HOST,
@ -236,6 +237,29 @@ class MySqlDatabase implements DatabaseInterface
return (int)$result[0]['count(*)']; 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} * {@inheritDoc}
*/ */