From d628f9b3ca0b3794f6ac26384715f5b7825abd47 Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Fri, 21 Apr 2017 11:52:24 +0200 Subject: [PATCH] Make DB migrations fully automatic --- Grocy.php | 41 ++++++++++++++--- GrocyDbMigrator.php | 11 ++--- GrocyDemoDataGenerator.php | 93 ++++++++++++++++++++------------------ GrocyLogicStock.php | 3 +- index.php | 4 +- 5 files changed, 91 insertions(+), 61 deletions(-) diff --git a/Grocy.php b/Grocy.php index ea363ee7..06c0adfa 100644 --- a/Grocy.php +++ b/Grocy.php @@ -6,17 +6,21 @@ class Grocy /** * @return PDO */ - public static function GetDbConnectionRaw() + public static function GetDbConnectionRaw($doMigrations = false) { + if ($doMigrations === true) + { + self::$DbConnectionRaw = null; + } + if (self::$DbConnectionRaw == null) { - $newDb = !file_exists(__DIR__ . '/data/grocy.db'); $pdo = new PDO('sqlite:' . __DIR__ . '/data/grocy.db'); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - if ($newDb) + if ($doMigrations === true) { - $pdo->exec("CREATE TABLE migrations (migration INTEGER NOT NULL UNIQUE, execution_time_timestamp DATETIME DEFAULT (datetime('now', 'localtime')), PRIMARY KEY(migration)) WITHOUT ROWID"); + Grocy::ExecuteDbStatement($pdo, "CREATE TABLE IF NOT EXISTS migrations (migration INTEGER NOT NULL UNIQUE, execution_time_timestamp DATETIME DEFAULT (datetime('now', 'localtime')), PRIMARY KEY(migration)) WITHOUT ROWID"); GrocyDbMigrator::MigrateDb($pdo); if (self::IsDemoInstallation()) @@ -35,16 +39,41 @@ class Grocy /** * @return LessQL\Database */ - public static function GetDbConnection() + public static function GetDbConnection($doMigrations = false) { + if ($doMigrations === true) + { + self::$DbConnection = null; + } + if (self::$DbConnection == null) { - self::$DbConnection = new LessQL\Database(self::GetDbConnectionRaw()); + self::$DbConnection = new LessQL\Database(self::GetDbConnectionRaw($doMigrations)); } return self::$DbConnection; } + public static function ExecuteDbStatement(PDO $pdo, string $sql) + { + if ($pdo->exec(utf8_encode($sql)) === false) + { + throw new Exception($pdo->errorInfo()); + } + + return true; + } + + public static function ExecuteDbQuery(PDO $pdo, string $sql) + { + if (self::ExecuteDbStatement($pdo, $sql) === true) + { + return $pdo->query(utf8_encode($sql)); + } + + return false; + } + public static function IsDemoInstallation() { return file_exists(__DIR__ . '/data/demo.txt'); diff --git a/GrocyDbMigrator.php b/GrocyDbMigrator.php index d8e67f65..a9105a5a 100644 --- a/GrocyDbMigrator.php +++ b/GrocyDbMigrator.php @@ -75,14 +75,11 @@ class GrocyDbMigrator private static function ExecuteMigrationWhenNeeded(PDO $pdo, int $migrationId, string $sql) { - if ($pdo->query("SELECT COUNT(*) FROM migrations WHERE migration = $migrationId")->fetchColumn() == 0) + $rowCount = Grocy::ExecuteDbQuery($pdo, 'SELECT COUNT(*) FROM migrations WHERE migration = ' . $migrationId)->fetchColumn(); + if (intval($rowCount) === 0) { - if ($pdo->exec(utf8_encode($sql)) === false) - { - throw new Exception($pdo->errorInfo()); - } - - $pdo->exec('INSERT INTO migrations (migration) VALUES (' . $migrationId . ')'); + Grocy::ExecuteDbStatement($pdo, $sql); + Grocy::ExecuteDbStatement($pdo, 'INSERT INTO migrations (migration) VALUES (' . $migrationId . ')'); } } } diff --git a/GrocyDemoDataGenerator.php b/GrocyDemoDataGenerator.php index 246e19d6..26bd1f3c 100644 --- a/GrocyDemoDataGenerator.php +++ b/GrocyDemoDataGenerator.php @@ -4,52 +4,55 @@ class GrocyDemoDataGenerator { public static function PopulateDemoData(PDO $pdo) { - $sql = " - UPDATE locations SET name = 'Vorratskammer', description = '' WHERE id = 1; - INSERT INTO locations (name) VALUES ('Süßigkeitenschrank'); --2 - INSERT INTO locations (name) VALUES ('Konservenschrank'); --3 - INSERT INTO locations (name) VALUES ('Kühlschrank'); --4 - - UPDATE quantity_units SET name = 'Stück' WHERE id = 1; - INSERT INTO quantity_units (name) VALUES ('Packung'); --2 - INSERT INTO quantity_units (name) VALUES ('Glas'); --3 - INSERT INTO quantity_units (name) VALUES ('Dose'); --4 - INSERT INTO quantity_units (name) VALUES ('Becher'); --5 - INSERT INTO quantity_units (name) VALUES ('Bund'); --6 - - DELETE FROM products WHERE id IN (1, 2); - INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Gummibärchen', 2, 2, 2, 1); --3 - INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Chips', 2, 2, 2, 1); --4 - INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Eier', 1, 2, 1, 10); --5 - INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Nudeln', 1, 2, 2, 1); --6 - INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Essiggurken', 3, 3, 3, 1); --7 - INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Gulaschsuppe', 3, 4, 4, 1); --8 - INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Joghurt', 4, 5, 5, 1); --9 - INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Käse', 4, 2, 2, 1); --10 - INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Aufschnitt', 4, 2, 2, 1); --11 - INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Paprika', 4, 1, 1, 1); --12 - INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Gurke', 4, 1, 1, 1); --13 - INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Radieschen', 4, 6, 6, 1); --14 - INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Tomate', 4, 1, 1, 1); --15 - "; - - if ($pdo->exec(utf8_encode($sql)) === false) + $rowCount = Grocy::ExecuteDbQuery($pdo, 'SELECT COUNT(*) FROM migrations WHERE migration = -1')->fetchColumn(); + if (intval($rowCount) === 0) { - throw new Exception($pdo->errorInfo()); - } + $sql = " + UPDATE locations SET name = 'Vorratskammer', description = '' WHERE id = 1; + INSERT INTO locations (name) VALUES ('Süßigkeitenschrank'); --2 + INSERT INTO locations (name) VALUES ('Konservenschrank'); --3 + INSERT INTO locations (name) VALUES ('Kühlschrank'); --4 - GrocyLogicStock::AddProduct(3, 5, date('Y-m-d', strtotime('+180 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); - GrocyLogicStock::AddProduct(4, 5, date('Y-m-d', strtotime('+180 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); - GrocyLogicStock::AddProduct(5, 5, date('Y-m-d', strtotime('+20 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); - GrocyLogicStock::AddProduct(6, 5, date('Y-m-d', strtotime('+600 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); - GrocyLogicStock::AddProduct(7, 5, date('Y-m-d', strtotime('+800 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); - GrocyLogicStock::AddProduct(8, 5, date('Y-m-d', strtotime('+900 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); - GrocyLogicStock::AddProduct(9, 5, date('Y-m-d', strtotime('+14 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); - GrocyLogicStock::AddProduct(10, 5, date('Y-m-d', strtotime('+21 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); - GrocyLogicStock::AddProduct(11, 5, date('Y-m-d', strtotime('+10 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); - GrocyLogicStock::AddProduct(12, 5, date('Y-m-d', strtotime('+2 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); - GrocyLogicStock::AddProduct(13, 5, date('Y-m-d', strtotime('-2 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); - GrocyLogicStock::AddProduct(14, 5, date('Y-m-d', strtotime('+2 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); - GrocyLogicStock::AddProduct(15, 5, date('Y-m-d', strtotime('-2 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + UPDATE quantity_units SET name = 'Stück' WHERE id = 1; + INSERT INTO quantity_units (name) VALUES ('Packung'); --2 + INSERT INTO quantity_units (name) VALUES ('Glas'); --3 + INSERT INTO quantity_units (name) VALUES ('Dose'); --4 + INSERT INTO quantity_units (name) VALUES ('Becher'); --5 + INSERT INTO quantity_units (name) VALUES ('Bund'); --6 + + DELETE FROM products WHERE id IN (1, 2); + INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Gummibärchen', 2, 2, 2, 1); --3 + INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Chips', 2, 2, 2, 1); --4 + INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Eier', 1, 2, 1, 10); --5 + INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Nudeln', 1, 2, 2, 1); --6 + INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Essiggurken', 3, 3, 3, 1); --7 + INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Gulaschsuppe', 3, 4, 4, 1); --8 + INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Joghurt', 4, 5, 5, 1); --9 + INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Käse', 4, 2, 2, 1); --10 + INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Aufschnitt', 4, 2, 2, 1); --11 + INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Paprika', 4, 1, 1, 1); --12 + INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Gurke', 4, 1, 1, 1); --13 + INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Radieschen', 4, 6, 6, 1); --14 + INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Tomate', 4, 1, 1, 1); --15 + + INSERT INTO migrations (migration) VALUES (-1); + "; + + Grocy::ExecuteDbStatement($pdo, $sql); + + GrocyLogicStock::AddProduct(3, 5, date('Y-m-d', strtotime('+180 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + GrocyLogicStock::AddProduct(4, 5, date('Y-m-d', strtotime('+180 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + GrocyLogicStock::AddProduct(5, 5, date('Y-m-d', strtotime('+20 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + GrocyLogicStock::AddProduct(6, 5, date('Y-m-d', strtotime('+600 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + GrocyLogicStock::AddProduct(7, 5, date('Y-m-d', strtotime('+800 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + GrocyLogicStock::AddProduct(8, 5, date('Y-m-d', strtotime('+900 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + GrocyLogicStock::AddProduct(9, 5, date('Y-m-d', strtotime('+14 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + GrocyLogicStock::AddProduct(10, 5, date('Y-m-d', strtotime('+21 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + GrocyLogicStock::AddProduct(11, 5, date('Y-m-d', strtotime('+10 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + GrocyLogicStock::AddProduct(12, 5, date('Y-m-d', strtotime('+2 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + GrocyLogicStock::AddProduct(13, 5, date('Y-m-d', strtotime('-2 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + GrocyLogicStock::AddProduct(14, 5, date('Y-m-d', strtotime('+2 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + GrocyLogicStock::AddProduct(15, 5, date('Y-m-d', strtotime('-2 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + } } } diff --git a/GrocyLogicStock.php b/GrocyLogicStock.php index c4fb8fe1..67eccd82 100644 --- a/GrocyLogicStock.php +++ b/GrocyLogicStock.php @@ -8,8 +8,7 @@ class GrocyLogicStock public static function GetCurrentStock() { - $db = Grocy::GetDbConnectionRaw(); - return $db->query('SELECT product_id, SUM(amount) AS amount, MIN(best_before_date) AS best_before_date from stock GROUP BY product_id ORDER BY MIN(best_before_date) ASC')->fetchAll(PDO::FETCH_OBJ); + return Grocy::ExecuteDbQuery(Grocy::GetDbConnectionRaw(), 'SELECT product_id, SUM(amount) AS amount, MIN(best_before_date) AS best_before_date from stock GROUP BY product_id ORDER BY MIN(best_before_date) ASC')->fetchAll(PDO::FETCH_OBJ); } public static function GetProductDetails(int $productId) diff --git a/index.php b/index.php index 0bbcebdf..4a9dcac6 100644 --- a/index.php +++ b/index.php @@ -36,6 +36,8 @@ $db = Grocy::GetDbConnection(); $app->get('/', function(Request $request, Response $response) use($db) { + $db = Grocy::GetDbConnection(true); //For database schema migration + return $this->renderer->render($response, '/layout.php', [ 'title' => 'Dashboard', 'contentPage' => 'dashboard.php', @@ -167,7 +169,7 @@ $app->get('/quantityunit/{quantityunitId}', function(Request $request, Response } }); -$app->group('/api', function() use($db, $app) +$app->group('/api', function() use($db) { $this->get('/get-objects/{entity}', function(Request $request, Response $response, $args) use($db) {