PHP Classes

File: src/database.php

Recommend this page to a friend!
  Packages of Uku-Kaarel Jo~esaar   too-vark   src/database.php   Download  
File: src/database.php
Role: Auxiliary script
Content type: text/plain
Description: Auxiliary script
Class: too-vark
Manage people work schedule times and tasks
Author: By
Last change:
Date: 9 days ago
Size: 2,980 bytes
 

Contents

Class file image Download
<?php
/**
 * DATABASE INIT KEY DESIGN DECISIONS:
 * ? UNIQUE(user_id, task_date, title) allows `INSERT OR IGNORE` so the rule
 * engine never overwrites tasks that a worker has already started or edited.
 * ? ON DELETE CASCADE on user_id means deleting a user automatically removes
 * all their tasks and rules ? no orphan cleanup needed.
 * ? An index on task_date speeds up the most common query (today's tasks).
 * ? PRAGMA user_version bypasses schema checks on subsequent loads to drop init overhead.
 */
if (defined('APP_DEBUG') && APP_DEBUG) $time_dbinit = hrtime(true);

$pdo = new PDO('sqlite:' . DB_FILE, null, null, [
   
PDO::ATTR_ERRMODE =>PDO::ERRMODE_EXCEPTION,
   
PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC,
]);

// Group per-connection PRAGMAs to minimize SQLite parser roundtrips.
// foreign_keys is REQUIRED every connection.
$pdo->exec("
    PRAGMA foreign_keys = ON;
    PRAGMA synchronous = NORMAL;
    PRAGMA temp_store = MEMORY;
    PRAGMA cache_size = -20000;
"
);

// WAL mode is persistent ? only set once
if ($pdo->query("PRAGMA journal_mode")->fetchColumn() !== 'wal') {
   
$pdo->exec("PRAGMA journal_mode=WAL;");
}

function
ensure_tasks_table(PDO $pdo): void {
   
$pdo->exec("CREATE TABLE IF NOT EXISTS tasks (
        id INTEGER PRIMARY KEY, user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
        task_date TEXT, title TEXT, start_time TEXT, end_time TEXT, status INTEGER DEFAULT 0, source TEXT NOT NULL DEFAULT 'manual', notes TEXT DEFAULT '',
        UNIQUE(user_id, task_date, title)
    )"
);
   
$pdo->exec("CREATE INDEX IF NOT EXISTS idx_tasks_date ON tasks(task_date)");
   
$pdo->exec("CREATE INDEX IF NOT EXISTS idx_tasks_date_title ON tasks(task_date, title, user_id)");
}


// Skip parsing/evaluating CREATE TABLE statements if schema is already up to date
if ((int)$pdo->query("PRAGMA user_version")->fetchColumn() < 1) {
   
$pdo->exec("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, username TEXT UNIQUE, password TEXT, real_name TEXT, contact TEXT, force_password_change INTEGER DEFAULT 0)");
   
$pdo->exec("CREATE TABLE IF NOT EXISTS user_rules (user_id INTEGER PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE, rules_text TEXT)");

   
ensure_tasks_table($pdo);

   
$pdo->exec("CREATE TABLE IF NOT EXISTS rl (ip TEXT PRIMARY KEY, fails INTEGER, expire INTEGER)");
   
$pdo->exec("CREATE TABLE IF NOT EXISTS task_details (title TEXT PRIMARY KEY NOT NULL, address TEXT, description TEXT, related_person TEXT, checklist TEXT)");


   
$pdo->exec("CREATE TABLE IF NOT EXISTS config (key TEXT PRIMARY KEY, val TEXT)");

    if (
$pdo->query("SELECT COUNT(*) FROM users")->fetchColumn() == 0) {
       
insert_user($pdo, USER1, USER1, USER1, USER1, 1);
    }

   
// Lock schema version to skip these checks on next connection
   
$pdo->exec("PRAGMA user_version = 1");
}

$cfg = array_column($pdo->query("SELECT key,val FROM config ORDER BY key")->fetchAll(), 'val', 'key');

if (
defined('APP_DEBUG') && APP_DEBUG) $time_db_ms = round((hrtime(true) - $time_dbinit) / 1e6, 2);