From d7e2a86f095c2d7ab8b4cfc156c0f86e9a3f260f Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Wed, 6 May 2026 22:51:03 +0000 Subject: [PATCH] V1.4.6 --- database/full.sql | 50 ++ database/schema.sql | 50 ++ db/auth.php | 1 + db/scmanutention.php | 762 ++++++++++++++++++ scmanutention.php | 1678 +++++++++++++++++++++++++++++++++++++++ scmanutentionpublic.php | 322 ++++++++ 6 files changed, 2863 insertions(+) create mode 100644 db/scmanutention.php create mode 100644 scmanutention.php create mode 100644 scmanutentionpublic.php diff --git a/database/full.sql b/database/full.sql index 652e82f..d6d5046 100644 --- a/database/full.sql +++ b/database/full.sql @@ -18787,3 +18787,53 @@ CREATE TABLE IF NOT EXISTS tbl_sccharacteritems ( ON DELETE SET NULL ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + + +CREATE TABLE IF NOT EXISTS tbl_scmanutentions ( + cl_scmanutention_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + cl_scmanutention_owner_auth_id INT UNSIGNED NOT NULL, + cl_scmanutention_title VARCHAR(190) NOT NULL, + cl_scmanutention_type VARCHAR(120) NOT NULL DEFAULT '', + cl_scmanutention_subtype VARCHAR(120) NOT NULL DEFAULT '', + cl_scmanutention_description TEXT DEFAULT NULL, + cl_scmanutention_share_token VARCHAR(64) NOT NULL, + cl_scmanutention_share_enabled TINYINT(1) NOT NULL DEFAULT 0, + cl_scmanutention_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + cl_scmanutention_updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + UNIQUE KEY uq_scmanutention_share_token (cl_scmanutention_share_token), + KEY idx_scmanutention_owner (cl_scmanutention_owner_auth_id), + KEY idx_scmanutention_title (cl_scmanutention_title), + CONSTRAINT fk_scmanutention_owner_auth FOREIGN KEY (cl_scmanutention_owner_auth_id) + REFERENCES tbl_auth (cl_auth_id) + ON DELETE CASCADE + ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS tbl_scmanutentionitems ( + cl_scmanutentionitem_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + cl_scmanutentionitem_manutention_id INT UNSIGNED NOT NULL, + cl_scmanutentionitem_source ENUM('base', 'custom') NOT NULL DEFAULT 'base', + cl_scmanutentionitem_scobjs_id INT UNSIGNED DEFAULT NULL, + cl_scmanutentionitem_scitemcustom_id INT(11) DEFAULT NULL, + cl_scmanutentionitem_quantity INT UNSIGNED NOT NULL DEFAULT 1, + cl_scmanutentionitem_extra_info TEXT DEFAULT NULL, + cl_scmanutentionitem_sort_order INT UNSIGNED NOT NULL DEFAULT 0, + cl_scmanutentionitem_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + cl_scmanutentionitem_updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + KEY idx_scmanutentionitem_sheet (cl_scmanutentionitem_manutention_id), + KEY idx_scmanutentionitem_scobjs (cl_scmanutentionitem_scobjs_id), + KEY idx_scmanutentionitem_scitemcustom (cl_scmanutentionitem_scitemcustom_id), + KEY idx_scmanutentionitem_sheet_sort (cl_scmanutentionitem_manutention_id, cl_scmanutentionitem_sort_order, cl_scmanutentionitem_id), + CONSTRAINT fk_scmanutentionitem_sheet FOREIGN KEY (cl_scmanutentionitem_manutention_id) + REFERENCES tbl_scmanutentions (cl_scmanutention_id) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT fk_scmanutentionitem_scobjs FOREIGN KEY (cl_scmanutentionitem_scobjs_id) + REFERENCES tbl_scobjs (cl_scobjs_id) + ON DELETE SET NULL + ON UPDATE CASCADE, + CONSTRAINT fk_scmanutentionitem_scitemcustom FOREIGN KEY (cl_scmanutentionitem_scitemcustom_id) + REFERENCES tbl_scitemcustom (cl_scitemcustom_id) + ON DELETE SET NULL + ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/database/schema.sql b/database/schema.sql index f50adea..9a6a064 100644 --- a/database/schema.sql +++ b/database/schema.sql @@ -260,3 +260,53 @@ CREATE TABLE IF NOT EXISTS tbl_sccharacteritems ( ON DELETE SET NULL ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + + +CREATE TABLE IF NOT EXISTS tbl_scmanutentions ( + cl_scmanutention_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + cl_scmanutention_owner_auth_id INT UNSIGNED NOT NULL, + cl_scmanutention_title VARCHAR(190) NOT NULL, + cl_scmanutention_type VARCHAR(120) NOT NULL DEFAULT '', + cl_scmanutention_subtype VARCHAR(120) NOT NULL DEFAULT '', + cl_scmanutention_description TEXT DEFAULT NULL, + cl_scmanutention_share_token VARCHAR(64) NOT NULL, + cl_scmanutention_share_enabled TINYINT(1) NOT NULL DEFAULT 0, + cl_scmanutention_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + cl_scmanutention_updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + UNIQUE KEY uq_scmanutention_share_token (cl_scmanutention_share_token), + KEY idx_scmanutention_owner (cl_scmanutention_owner_auth_id), + KEY idx_scmanutention_title (cl_scmanutention_title), + CONSTRAINT fk_scmanutention_owner_auth FOREIGN KEY (cl_scmanutention_owner_auth_id) + REFERENCES tbl_auth (cl_auth_id) + ON DELETE CASCADE + ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS tbl_scmanutentionitems ( + cl_scmanutentionitem_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + cl_scmanutentionitem_manutention_id INT UNSIGNED NOT NULL, + cl_scmanutentionitem_source ENUM('base', 'custom') NOT NULL DEFAULT 'base', + cl_scmanutentionitem_scobjs_id INT UNSIGNED DEFAULT NULL, + cl_scmanutentionitem_scitemcustom_id INT(11) DEFAULT NULL, + cl_scmanutentionitem_quantity INT UNSIGNED NOT NULL DEFAULT 1, + cl_scmanutentionitem_extra_info TEXT DEFAULT NULL, + cl_scmanutentionitem_sort_order INT UNSIGNED NOT NULL DEFAULT 0, + cl_scmanutentionitem_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + cl_scmanutentionitem_updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + KEY idx_scmanutentionitem_sheet (cl_scmanutentionitem_manutention_id), + KEY idx_scmanutentionitem_scobjs (cl_scmanutentionitem_scobjs_id), + KEY idx_scmanutentionitem_scitemcustom (cl_scmanutentionitem_scitemcustom_id), + KEY idx_scmanutentionitem_sheet_sort (cl_scmanutentionitem_manutention_id, cl_scmanutentionitem_sort_order, cl_scmanutentionitem_id), + CONSTRAINT fk_scmanutentionitem_sheet FOREIGN KEY (cl_scmanutentionitem_manutention_id) + REFERENCES tbl_scmanutentions (cl_scmanutention_id) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT fk_scmanutentionitem_scobjs FOREIGN KEY (cl_scmanutentionitem_scobjs_id) + REFERENCES tbl_scobjs (cl_scobjs_id) + ON DELETE SET NULL + ON UPDATE CASCADE, + CONSTRAINT fk_scmanutentionitem_scitemcustom FOREIGN KEY (cl_scmanutentionitem_scitemcustom_id) + REFERENCES tbl_scitemcustom (cl_scitemcustom_id) + ON DELETE SET NULL + ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/db/auth.php b/db/auth.php index 3ea1f13..046bd48 100644 --- a/db/auth.php +++ b/db/auth.php @@ -470,6 +470,7 @@ function auth_navigation_items(): array ['file' => 'scstatsitem.php', 'label' => 'Stats Item'], ['file' => 'scitemcustom.php', 'label' => 'Objets perso.'], ['file' => 'sccharacters.php', 'label' => 'Personnages'], + ['file' => 'scmanutention.php', 'label' => 'Manutention'], ['file' => 'scmining.php', 'label' => 'Scanner Minage'], ['file' => 'scmanufactures.php', 'label' => 'Manufactures'], ['file' => 'scvaisseaux.php', 'label' => 'Vaisseaux'], diff --git a/db/scmanutention.php b/db/scmanutention.php new file mode 100644 index 0000000..3b33803 --- /dev/null +++ b/db/scmanutention.php @@ -0,0 +1,762 @@ +query("SHOW COLUMNS FROM `{$table}` LIKE " . $db->quote($column)); + + return (bool) $stmt->fetch(); +} + +function scmanutention_index_exists(PDO $db, string $table, string $index): bool +{ + $stmt = $db->query("SHOW INDEX FROM `{$table}` WHERE Key_name = " . $db->quote($index)); + + return (bool) $stmt->fetch(); +} + +function scmanutention_foreign_key_exists(PDO $db, string $table, string $constraint): bool +{ + $stmt = $db->prepare( + "SELECT COUNT(*) + FROM information_schema.TABLE_CONSTRAINTS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = :table_name + AND CONSTRAINT_NAME = :constraint_name + AND CONSTRAINT_TYPE = 'FOREIGN KEY'" + ); + $stmt->execute([ + 'table_name' => $table, + 'constraint_name' => $constraint, + ]); + + return (int) $stmt->fetchColumn() > 0; +} + +function scmanutention_bootstrap(): void +{ + static $bootstrapped = false; + + if ($bootstrapped) { + return; + } + + $db = db(); + + $db->exec( + "CREATE TABLE IF NOT EXISTS tbl_scmanutentions ( + cl_scmanutention_id INT UNSIGNED NOT NULL AUTO_INCREMENT, + cl_scmanutention_owner_auth_id INT UNSIGNED NOT NULL, + cl_scmanutention_title VARCHAR(190) NOT NULL, + cl_scmanutention_type VARCHAR(120) NOT NULL DEFAULT '', + cl_scmanutention_subtype VARCHAR(120) NOT NULL DEFAULT '', + cl_scmanutention_description TEXT DEFAULT NULL, + cl_scmanutention_share_token VARCHAR(64) NOT NULL, + cl_scmanutention_share_enabled TINYINT(1) NOT NULL DEFAULT 0, + cl_scmanutention_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + cl_scmanutention_updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (cl_scmanutention_id), + UNIQUE KEY uq_scmanutention_share_token (cl_scmanutention_share_token), + KEY idx_scmanutention_owner (cl_scmanutention_owner_auth_id), + KEY idx_scmanutention_title (cl_scmanutention_title), + CONSTRAINT fk_scmanutention_owner_auth FOREIGN KEY (cl_scmanutention_owner_auth_id) + REFERENCES tbl_auth (cl_auth_id) + ON DELETE CASCADE + ON UPDATE CASCADE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci" + ); + + if (!scmanutention_column_exists($db, 'tbl_scmanutentions', 'cl_scmanutention_owner_auth_id')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentions + ADD COLUMN cl_scmanutention_owner_auth_id INT UNSIGNED NULL AFTER cl_scmanutention_id' + ); + } + + if (!scmanutention_column_exists($db, 'tbl_scmanutentions', 'cl_scmanutention_type')) { + $db->exec( + "ALTER TABLE tbl_scmanutentions + ADD COLUMN cl_scmanutention_type VARCHAR(120) NOT NULL DEFAULT '' AFTER cl_scmanutention_title" + ); + } + + if (!scmanutention_column_exists($db, 'tbl_scmanutentions', 'cl_scmanutention_subtype')) { + $db->exec( + "ALTER TABLE tbl_scmanutentions + ADD COLUMN cl_scmanutention_subtype VARCHAR(120) NOT NULL DEFAULT '' AFTER cl_scmanutention_type" + ); + } + + if (!scmanutention_column_exists($db, 'tbl_scmanutentions', 'cl_scmanutention_description')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentions + ADD COLUMN cl_scmanutention_description TEXT NULL AFTER cl_scmanutention_subtype' + ); + } + + if (!scmanutention_column_exists($db, 'tbl_scmanutentions', 'cl_scmanutention_share_token')) { + $db->exec( + "ALTER TABLE tbl_scmanutentions + ADD COLUMN cl_scmanutention_share_token VARCHAR(64) NOT NULL DEFAULT '' AFTER cl_scmanutention_description" + ); + } + + if (!scmanutention_column_exists($db, 'tbl_scmanutentions', 'cl_scmanutention_share_enabled')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentions + ADD COLUMN cl_scmanutention_share_enabled TINYINT(1) NOT NULL DEFAULT 0 AFTER cl_scmanutention_share_token' + ); + } + + if (!scmanutention_index_exists($db, 'tbl_scmanutentions', 'idx_scmanutention_owner')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentions + ADD INDEX idx_scmanutention_owner (cl_scmanutention_owner_auth_id)' + ); + } + + if (!scmanutention_index_exists($db, 'tbl_scmanutentions', 'idx_scmanutention_title')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentions + ADD INDEX idx_scmanutention_title (cl_scmanutention_title)' + ); + } + + if (!scmanutention_index_exists($db, 'tbl_scmanutentions', 'uq_scmanutention_share_token')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentions + ADD UNIQUE KEY uq_scmanutention_share_token (cl_scmanutention_share_token)' + ); + } + + if (!scmanutention_foreign_key_exists($db, 'tbl_scmanutentions', 'fk_scmanutention_owner_auth')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentions + ADD CONSTRAINT fk_scmanutention_owner_auth FOREIGN KEY (cl_scmanutention_owner_auth_id) + REFERENCES tbl_auth (cl_auth_id) + ON DELETE CASCADE + ON UPDATE CASCADE' + ); + } + + $db->exec( + "CREATE TABLE IF NOT EXISTS tbl_scmanutentionitems ( + cl_scmanutentionitem_id INT UNSIGNED NOT NULL AUTO_INCREMENT, + cl_scmanutentionitem_manutention_id INT UNSIGNED NOT NULL, + cl_scmanutentionitem_source ENUM('base', 'custom') NOT NULL DEFAULT 'base', + cl_scmanutentionitem_scobjs_id INT UNSIGNED DEFAULT NULL, + cl_scmanutentionitem_scitemcustom_id INT(11) DEFAULT NULL, + cl_scmanutentionitem_quantity INT UNSIGNED NOT NULL DEFAULT 1, + cl_scmanutentionitem_extra_info TEXT DEFAULT NULL, + cl_scmanutentionitem_sort_order INT UNSIGNED NOT NULL DEFAULT 0, + cl_scmanutentionitem_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + cl_scmanutentionitem_updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (cl_scmanutentionitem_id), + KEY idx_scmanutentionitem_sheet (cl_scmanutentionitem_manutention_id), + KEY idx_scmanutentionitem_scobjs (cl_scmanutentionitem_scobjs_id), + KEY idx_scmanutentionitem_scitemcustom (cl_scmanutentionitem_scitemcustom_id), + KEY idx_scmanutentionitem_sheet_sort (cl_scmanutentionitem_manutention_id, cl_scmanutentionitem_sort_order, cl_scmanutentionitem_id), + CONSTRAINT fk_scmanutentionitem_sheet FOREIGN KEY (cl_scmanutentionitem_manutention_id) + REFERENCES tbl_scmanutentions (cl_scmanutention_id) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT fk_scmanutentionitem_scobjs FOREIGN KEY (cl_scmanutentionitem_scobjs_id) + REFERENCES tbl_scobjs (cl_scobjs_id) + ON DELETE SET NULL + ON UPDATE CASCADE, + CONSTRAINT fk_scmanutentionitem_scitemcustom FOREIGN KEY (cl_scmanutentionitem_scitemcustom_id) + REFERENCES tbl_scitemcustom (cl_scitemcustom_id) + ON DELETE SET NULL + ON UPDATE CASCADE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci" + ); + + if (!scmanutention_column_exists($db, 'tbl_scmanutentionitems', 'cl_scmanutentionitem_source')) { + $db->exec( + "ALTER TABLE tbl_scmanutentionitems + ADD COLUMN cl_scmanutentionitem_source ENUM('base', 'custom') NOT NULL DEFAULT 'base' AFTER cl_scmanutentionitem_manutention_id" + ); + } + + if (!scmanutention_column_exists($db, 'tbl_scmanutentionitems', 'cl_scmanutentionitem_scobjs_id')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentionitems + ADD COLUMN cl_scmanutentionitem_scobjs_id INT UNSIGNED NULL AFTER cl_scmanutentionitem_source' + ); + } + + if (!scmanutention_column_exists($db, 'tbl_scmanutentionitems', 'cl_scmanutentionitem_scitemcustom_id')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentionitems + ADD COLUMN cl_scmanutentionitem_scitemcustom_id INT(11) NULL AFTER cl_scmanutentionitem_scobjs_id' + ); + } + + if (!scmanutention_column_exists($db, 'tbl_scmanutentionitems', 'cl_scmanutentionitem_quantity')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentionitems + ADD COLUMN cl_scmanutentionitem_quantity INT UNSIGNED NOT NULL DEFAULT 1 AFTER cl_scmanutentionitem_scitemcustom_id' + ); + } + + if (!scmanutention_column_exists($db, 'tbl_scmanutentionitems', 'cl_scmanutentionitem_extra_info')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentionitems + ADD COLUMN cl_scmanutentionitem_extra_info TEXT NULL AFTER cl_scmanutentionitem_quantity' + ); + } + + if (!scmanutention_column_exists($db, 'tbl_scmanutentionitems', 'cl_scmanutentionitem_sort_order')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentionitems + ADD COLUMN cl_scmanutentionitem_sort_order INT UNSIGNED NOT NULL DEFAULT 0 AFTER cl_scmanutentionitem_extra_info' + ); + } + + if (!scmanutention_index_exists($db, 'tbl_scmanutentionitems', 'idx_scmanutentionitem_sheet')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentionitems + ADD INDEX idx_scmanutentionitem_sheet (cl_scmanutentionitem_manutention_id)' + ); + } + + if (!scmanutention_index_exists($db, 'tbl_scmanutentionitems', 'idx_scmanutentionitem_scobjs')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentionitems + ADD INDEX idx_scmanutentionitem_scobjs (cl_scmanutentionitem_scobjs_id)' + ); + } + + if (!scmanutention_index_exists($db, 'tbl_scmanutentionitems', 'idx_scmanutentionitem_scitemcustom')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentionitems + ADD INDEX idx_scmanutentionitem_scitemcustom (cl_scmanutentionitem_scitemcustom_id)' + ); + } + + if (!scmanutention_index_exists($db, 'tbl_scmanutentionitems', 'idx_scmanutentionitem_sheet_sort')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentionitems + ADD INDEX idx_scmanutentionitem_sheet_sort (cl_scmanutentionitem_manutention_id, cl_scmanutentionitem_sort_order, cl_scmanutentionitem_id)' + ); + } + + if (!scmanutention_foreign_key_exists($db, 'tbl_scmanutentionitems', 'fk_scmanutentionitem_sheet')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentionitems + ADD CONSTRAINT fk_scmanutentionitem_sheet FOREIGN KEY (cl_scmanutentionitem_manutention_id) + REFERENCES tbl_scmanutentions (cl_scmanutention_id) + ON DELETE CASCADE + ON UPDATE CASCADE' + ); + } + + if (!scmanutention_foreign_key_exists($db, 'tbl_scmanutentionitems', 'fk_scmanutentionitem_scobjs')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentionitems + ADD CONSTRAINT fk_scmanutentionitem_scobjs FOREIGN KEY (cl_scmanutentionitem_scobjs_id) + REFERENCES tbl_scobjs (cl_scobjs_id) + ON DELETE SET NULL + ON UPDATE CASCADE' + ); + } + + if (!scmanutention_foreign_key_exists($db, 'tbl_scmanutentionitems', 'fk_scmanutentionitem_scitemcustom')) { + $db->exec( + 'ALTER TABLE tbl_scmanutentionitems + ADD CONSTRAINT fk_scmanutentionitem_scitemcustom FOREIGN KEY (cl_scmanutentionitem_scitemcustom_id) + REFERENCES tbl_scitemcustom (cl_scitemcustom_id) + ON DELETE SET NULL + ON UPDATE CASCADE' + ); + } + + $stmt_missing_tokens = $db->query( + "SELECT cl_scmanutention_id + FROM tbl_scmanutentions + WHERE cl_scmanutention_share_token = '' + OR cl_scmanutention_share_token IS NULL" + ); + + foreach ($stmt_missing_tokens->fetchAll(PDO::FETCH_COLUMN) as $sheet_id) { + $stmt_update = $db->prepare( + 'UPDATE tbl_scmanutentions + SET cl_scmanutention_share_token = :token + WHERE cl_scmanutention_id = :id' + ); + $stmt_update->execute([ + 'token' => scmanutention_generate_share_token(), + 'id' => (int) $sheet_id, + ]); + } + + $bootstrapped = true; +} + +function scmanutention_generate_share_token(int $length = 32): string +{ + $length = max(16, min(64, $length)); + + return bin2hex(random_bytes((int) ceil($length / 2))); +} + +function scmanutention_clean_text(?string $value): string +{ + return trim((string) $value); +} + +function scmanutention_normalize_quantity($value): int +{ + $quantity = (int) $value; + + if ($quantity <= 0) { + return 1; + } + + return min($quantity, 999999); +} + +function scmanutention_is_valid_source(string $value): bool +{ + return in_array($value, ['base', 'custom'], true); +} + +function scmanutention_escape_like(string $value): string +{ + return strtr($value, [ + '\\' => '\\\\', + '%' => '\\%', + '_' => '\\_', + ]); +} + +function scmanutention_sheet_share_url(string $token): string +{ + $is_https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') + || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') + || ((string) ($_SERVER['SERVER_PORT'] ?? '') === '443'); + + $scheme = $is_https ? 'https' : 'http'; + $host = trim((string) ($_SERVER['HTTP_HOST'] ?? '')); + + if ($host === '') { + $host = '127.0.0.1'; + } + + return $scheme . '://' . $host . '/scmanutentionpublic.php?share=' . rawurlencode($token); +} + +function scmanutention_find_owned_sheet(PDO $db, int $sheet_id, int $owner_auth_id): ?array +{ + if ($sheet_id <= 0 || $owner_auth_id <= 0) { + return null; + } + + $stmt = $db->prepare( + 'SELECT * + FROM tbl_scmanutentions + WHERE cl_scmanutention_id = :id + AND cl_scmanutention_owner_auth_id = :owner_auth_id + LIMIT 1' + ); + $stmt->execute([ + 'id' => $sheet_id, + 'owner_auth_id' => $owner_auth_id, + ]); + + $row = $stmt->fetch(); + + return $row ?: null; +} + +function scmanutention_find_public_sheet_by_token(PDO $db, string $share_token): ?array +{ + $share_token = trim($share_token); + if ($share_token === '') { + return null; + } + + $stmt = $db->prepare( + 'SELECT m.*, COALESCE(NULLIF(TRIM(a.cl_auth_user), \'\'), \'Inconnu\') AS cl_scmanutention_owner_name + FROM tbl_scmanutentions m + LEFT JOIN tbl_auth a ON a.cl_auth_id = m.cl_scmanutention_owner_auth_id + WHERE m.cl_scmanutention_share_token = :share_token + AND m.cl_scmanutention_share_enabled = 1 + LIMIT 1' + ); + $stmt->execute(['share_token' => $share_token]); + + $row = $stmt->fetch(); + + return $row ?: null; +} + +function scmanutention_next_item_sort_order(PDO $db, int $sheet_id): int +{ + $stmt = $db->prepare( + 'SELECT COALESCE(MAX(cl_scmanutentionitem_sort_order), 0) + FROM tbl_scmanutentionitems + WHERE cl_scmanutentionitem_manutention_id = :sheet_id' + ); + $stmt->execute(['sheet_id' => $sheet_id]); + + return ((int) $stmt->fetchColumn()) + 1; +} + +function scmanutention_reindex_items(PDO $db, int $sheet_id): void +{ + if ($sheet_id <= 0) { + return; + } + + $stmt = $db->prepare( + 'SELECT cl_scmanutentionitem_id + FROM tbl_scmanutentionitems + WHERE cl_scmanutentionitem_manutention_id = :sheet_id + ORDER BY cl_scmanutentionitem_sort_order ASC, cl_scmanutentionitem_id ASC' + ); + $stmt->execute(['sheet_id' => $sheet_id]); + $ids = $stmt->fetchAll(PDO::FETCH_COLUMN); + + $position = 1; + $stmt_update = $db->prepare( + 'UPDATE tbl_scmanutentionitems + SET cl_scmanutentionitem_sort_order = :sort_order + WHERE cl_scmanutentionitem_id = :id' + ); + + foreach ($ids as $id) { + $stmt_update->execute([ + 'sort_order' => $position++, + 'id' => (int) $id, + ]); + } +} + +function scmanutention_find_owned_item(PDO $db, int $item_id, int $owner_auth_id): ?array +{ + if ($item_id <= 0 || $owner_auth_id <= 0) { + return null; + } + + $stmt = $db->prepare( + "SELECT + mi.*, + m.cl_scmanutention_owner_auth_id + FROM tbl_scmanutentionitems mi + INNER JOIN tbl_scmanutentions m ON m.cl_scmanutention_id = mi.cl_scmanutentionitem_manutention_id + WHERE mi.cl_scmanutentionitem_id = :item_id + AND m.cl_scmanutention_owner_auth_id = :owner_auth_id + LIMIT 1" + ); + $stmt->execute([ + 'item_id' => $item_id, + 'owner_auth_id' => $owner_auth_id, + ]); + + $row = $stmt->fetch(); + + return $row ?: null; +} + +function scmanutention_validate_item_reference(PDO $db, int $owner_auth_id, string $source, int $scobjs_id, int $scitemcustom_id): ?array +{ + if (!scmanutention_is_valid_source($source)) { + return null; + } + + if ($source === 'base') { + if ($scobjs_id <= 0) { + return null; + } + + $stmt = $db->prepare( + 'SELECT cl_scobjs_id, cl_scobjs_name, cl_scobjs_type, cl_scobjs_subtype, cl_scobjs_uuid, cl_scobjs_rarity + FROM tbl_scobjs + WHERE cl_scobjs_id = :id + LIMIT 1' + ); + $stmt->execute(['id' => $scobjs_id]); + $row = $stmt->fetch(); + + if (!$row) { + return null; + } + + return [ + 'source' => 'base', + 'scobjs_id' => (int) $row['cl_scobjs_id'], + 'scitemcustom_id' => 0, + 'name' => (string) $row['cl_scobjs_name'], + 'type' => (string) ($row['cl_scobjs_type'] ?? ''), + 'subtype' => (string) ($row['cl_scobjs_subtype'] ?? ''), + 'uuid' => (string) ($row['cl_scobjs_uuid'] ?? ''), + 'rarity' => (string) ($row['cl_scobjs_rarity'] ?? ''), + ]; + } + + if ($scitemcustom_id <= 0 || $owner_auth_id <= 0) { + return null; + } + + $stmt = $db->prepare( + "SELECT + c.cl_scitemcustom_id, + o.cl_scobjs_id, + o.cl_scobjs_name, + o.cl_scobjs_type, + o.cl_scobjs_subtype, + o.cl_scobjs_uuid, + o.cl_scobjs_rarity + FROM tbl_scitemcustom c + INNER JOIN tbl_scobjs o ON o.cl_scobjs_id = c.cl_scitemcustom_obj_id + WHERE c.cl_scitemcustom_id = :itemcustom_id + AND c.cl_scitemcustom_owner_auth_id = :owner_auth_id + LIMIT 1" + ); + $stmt->execute([ + 'itemcustom_id' => $scitemcustom_id, + 'owner_auth_id' => $owner_auth_id, + ]); + $row = $stmt->fetch(); + + if (!$row) { + return null; + } + + return [ + 'source' => 'custom', + 'scobjs_id' => (int) $row['cl_scobjs_id'], + 'scitemcustom_id' => (int) $row['cl_scitemcustom_id'], + 'name' => (string) $row['cl_scobjs_name'], + 'type' => (string) ($row['cl_scobjs_type'] ?? ''), + 'subtype' => (string) ($row['cl_scobjs_subtype'] ?? ''), + 'uuid' => (string) ($row['cl_scobjs_uuid'] ?? ''), + 'rarity' => (string) ($row['cl_scobjs_rarity'] ?? ''), + ]; +} + +function scmanutention_search_available_items(PDO $db, int $owner_auth_id, string $query, int $limit = 12): array +{ + $query = trim($query); + if ($query === '') { + return []; + } + + $escaped = scmanutention_escape_like($query); + $exact = $escaped; + $prefix = $escaped . '%'; + $contains = '%' . $escaped . '%'; + $limit = max(1, min(30, $limit)); + + $sql = " + SELECT * + FROM ( + SELECT + CONCAT('base:', o.cl_scobjs_id) AS result_key, + 'base' AS result_source, + o.cl_scobjs_id AS result_scobjs_id, + NULL AS result_scitemcustom_id, + o.cl_scobjs_name AS result_name, + COALESCE(o.cl_scobjs_type, '') AS result_type, + COALESCE(o.cl_scobjs_subtype, '') AS result_subtype, + COALESCE(o.cl_scobjs_uuid, '') AS result_uuid, + COALESCE(o.cl_scobjs_rarity, '') AS result_rarity + FROM tbl_scobjs o + WHERE ( + o.cl_scobjs_name LIKE :contains_name_base + OR o.cl_scobjs_type LIKE :contains_type_base + OR o.cl_scobjs_subtype LIKE :contains_subtype_base + OR o.cl_scobjs_uuid LIKE :contains_uuid_base + ) + + UNION ALL + + SELECT + CONCAT('custom:', c.cl_scitemcustom_id) AS result_key, + 'custom' AS result_source, + o.cl_scobjs_id AS result_scobjs_id, + c.cl_scitemcustom_id AS result_scitemcustom_id, + o.cl_scobjs_name AS result_name, + COALESCE(o.cl_scobjs_type, '') AS result_type, + COALESCE(o.cl_scobjs_subtype, '') AS result_subtype, + COALESCE(o.cl_scobjs_uuid, '') AS result_uuid, + COALESCE(o.cl_scobjs_rarity, '') AS result_rarity + FROM tbl_scitemcustom c + INNER JOIN tbl_scobjs o ON o.cl_scobjs_id = c.cl_scitemcustom_obj_id + WHERE c.cl_scitemcustom_owner_auth_id = :owner_auth_id + AND ( + o.cl_scobjs_name LIKE :contains_name_custom + OR o.cl_scobjs_type LIKE :contains_type_custom + OR o.cl_scobjs_subtype LIKE :contains_subtype_custom + OR o.cl_scobjs_uuid LIKE :contains_uuid_custom + ) + ) search_results + ORDER BY + CASE + WHEN result_name = :exact_name THEN 0 + WHEN result_name LIKE :prefix_name THEN 1 + WHEN result_source = 'custom' THEN 2 + WHEN result_uuid = :exact_uuid THEN 3 + WHEN result_uuid LIKE :prefix_uuid THEN 4 + WHEN result_type LIKE :prefix_type THEN 5 + WHEN result_subtype LIKE :prefix_subtype THEN 6 + ELSE 7 + END ASC, + CHAR_LENGTH(result_name) ASC, + result_name ASC, + result_key ASC + LIMIT {$limit}"; + + $stmt = $db->prepare($sql); + $stmt->execute([ + 'owner_auth_id' => $owner_auth_id, + 'contains_name_base' => $contains, + 'contains_type_base' => $contains, + 'contains_subtype_base' => $contains, + 'contains_uuid_base' => $contains, + 'contains_name_custom' => $contains, + 'contains_type_custom' => $contains, + 'contains_subtype_custom' => $contains, + 'contains_uuid_custom' => $contains, + 'exact_name' => $exact, + 'prefix_name' => $prefix, + 'exact_uuid' => $exact, + 'prefix_uuid' => $prefix, + 'prefix_type' => $prefix, + 'prefix_subtype' => $prefix, + ]); + + return $stmt->fetchAll() ?: []; +} + + +function scmanutention_sortable_item_name(array $item_row): string +{ + $name = (string) ((($item_row['cl_scmanutentionitem_source'] ?? '') === 'custom') + ? ($item_row['cl_scmanutentionitem_custom_name'] ?? '') + : ($item_row['cl_scmanutentionitem_base_name'] ?? '')); + $name = trim($name); + + if ($name === '') { + return ''; + } + + if (function_exists('iconv')) { + $ascii_name = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $name); + if ($ascii_name !== false) { + $name = $ascii_name; + } + } + + return function_exists('mb_strtolower') + ? mb_strtolower($name, 'UTF-8') + : strtolower($name); +} + +function scmanutention_fetch_items(PDO $db, int $sheet_id): array +{ + if ($sheet_id <= 0) { + return []; + } + + scmanutention_reindex_items($db, $sheet_id); + + $stmt = $db->prepare( + "SELECT + mi.*, + bo.cl_scobjs_name AS cl_scmanutentionitem_base_name, + bo.cl_scobjs_type AS cl_scmanutentionitem_base_type, + bo.cl_scobjs_subtype AS cl_scmanutentionitem_base_subtype, + bo.cl_scobjs_uuid AS cl_scmanutentionitem_base_uuid, + bo.cl_scobjs_rarity AS cl_scmanutentionitem_base_rarity, + co.cl_scitemcustom_id AS cl_scmanutentionitem_custom_ref_id, + oo.cl_scobjs_name AS cl_scmanutentionitem_custom_name, + oo.cl_scobjs_type AS cl_scmanutentionitem_custom_type, + oo.cl_scobjs_subtype AS cl_scmanutentionitem_custom_subtype, + oo.cl_scobjs_uuid AS cl_scmanutentionitem_custom_uuid, + oo.cl_scobjs_rarity AS cl_scmanutentionitem_custom_rarity + FROM tbl_scmanutentionitems mi + LEFT JOIN tbl_scobjs bo ON bo.cl_scobjs_id = mi.cl_scmanutentionitem_scobjs_id + LEFT JOIN tbl_scitemcustom co ON co.cl_scitemcustom_id = mi.cl_scmanutentionitem_scitemcustom_id + LEFT JOIN tbl_scobjs oo ON oo.cl_scobjs_id = co.cl_scitemcustom_obj_id + WHERE mi.cl_scmanutentionitem_manutention_id = :sheet_id + ORDER BY mi.cl_scmanutentionitem_sort_order ASC, mi.cl_scmanutentionitem_id ASC" + ); + $stmt->execute(['sheet_id' => $sheet_id]); + + $items = $stmt->fetchAll() ?: []; + foreach ($items as $index => &$item_row) { + $item_row['__alpha_sort_name'] = scmanutention_sortable_item_name($item_row); + $item_row['__alpha_sort_index'] = $index; + } + unset($item_row); + + usort($items, static function (array $left, array $right): int { + $name_compare = strnatcasecmp((string) ($left['__alpha_sort_name'] ?? ''), (string) ($right['__alpha_sort_name'] ?? '')); + if ($name_compare !== 0) { + return $name_compare; + } + + $sort_order_compare = ((int) ($left['cl_scmanutentionitem_sort_order'] ?? 0)) <=> ((int) ($right['cl_scmanutentionitem_sort_order'] ?? 0)); + if ($sort_order_compare !== 0) { + return $sort_order_compare; + } + + $id_compare = ((int) ($left['cl_scmanutentionitem_id'] ?? 0)) <=> ((int) ($right['cl_scmanutentionitem_id'] ?? 0)); + if ($id_compare !== 0) { + return $id_compare; + } + + return ((int) ($left['__alpha_sort_index'] ?? 0)) <=> ((int) ($right['__alpha_sort_index'] ?? 0)); + }); + + foreach ($items as &$item_row) { + unset($item_row['__alpha_sort_name'], $item_row['__alpha_sort_index']); + } + unset($item_row); + + return $items; +} + +function scmanutention_fetch_custom_stats_map(PDO $db, array $item_rows): array +{ + $custom_ids = []; + foreach ($item_rows as $row) { + if (($row['cl_scmanutentionitem_source'] ?? '') === 'custom' && !empty($row['cl_scmanutentionitem_scitemcustom_id'])) { + $custom_ids[] = (int) $row['cl_scmanutentionitem_scitemcustom_id']; + } + } + + $custom_ids = array_values(array_unique(array_filter($custom_ids))); + if ($custom_ids === []) { + return []; + } + + $placeholders = implode(',', array_fill(0, count($custom_ids), '?')); + $stmt = $db->prepare( + "SELECT + cs.cl_scitemcustomstat_itemcustom_id, + st.cl_scstatsitem_name, + st.cl_scstatsitem_unit, + cs.cl_scitemcustomstat_sign, + cs.cl_scitemcustomstat_value + FROM tbl_scitemcustomstat cs + INNER JOIN tbl_scstatsitem st ON st.cl_scstatsitem_id = cs.cl_scitemcustomstat_stat_id + WHERE cs.cl_scitemcustomstat_itemcustom_id IN ({$placeholders}) + ORDER BY st.cl_scstatsitem_name ASC, cs.cl_scitemcustomstat_id ASC" + ); + $stmt->execute($custom_ids); + + $stats_map = []; + foreach ($stmt->fetchAll() as $row) { + $itemcustom_id = (int) $row['cl_scitemcustomstat_itemcustom_id']; + if (!isset($stats_map[$itemcustom_id])) { + $stats_map[$itemcustom_id] = []; + } + $stats_map[$itemcustom_id][] = $row; + } + + return $stats_map; +} diff --git a/scmanutention.php b/scmanutention.php new file mode 100644 index 0000000..2216a13 --- /dev/null +++ b/scmanutention.php @@ -0,0 +1,1678 @@ +prepare( + 'SELECT cl_auth_id + FROM tbl_auth + WHERE cl_auth_user = :user + LIMIT 1' + ); + $stmt->execute(['user' => $session_user]); + + return (int) $stmt->fetchColumn(); +} + +function scmanutention_redirect(int $sheet_id = 0, string $anchor = ''): void +{ + $location = 'scmanutention.php'; + if ($sheet_id > 0) { + $location .= '?sheet=' . $sheet_id; + } + if ($anchor !== '') { + $location .= '#' . rawurlencode(ltrim($anchor, '#')); + } + + header('Location: ' . $location); + exit; +} + +function scmanutention_rarity_class(string $rarity): string +{ + $rarity = strtoupper(trim($rarity)); + + return in_array($rarity, ['L', 'E', 'R', 'U', 'C'], true) ? 'rarity-' . $rarity : ''; +} + +function scmanutention_item_name(array $item_row): string +{ + $is_custom = ($item_row['cl_scmanutentionitem_source'] ?? '') === 'custom'; + + return (string) ($is_custom + ? ($item_row['cl_scmanutentionitem_custom_name'] ?? '') + : ($item_row['cl_scmanutentionitem_base_name'] ?? '')); +} + +function scmanutention_item_type(array $item_row): string +{ + $is_custom = ($item_row['cl_scmanutentionitem_source'] ?? '') === 'custom'; + + return (string) ($is_custom + ? ($item_row['cl_scmanutentionitem_custom_type'] ?? '') + : ($item_row['cl_scmanutentionitem_base_type'] ?? '')); +} + +function scmanutention_item_subtype(array $item_row): string +{ + $is_custom = ($item_row['cl_scmanutentionitem_source'] ?? '') === 'custom'; + + return (string) ($is_custom + ? ($item_row['cl_scmanutentionitem_custom_subtype'] ?? '') + : ($item_row['cl_scmanutentionitem_base_subtype'] ?? '')); +} + +function scmanutention_item_uuid(array $item_row): string +{ + $is_custom = ($item_row['cl_scmanutentionitem_source'] ?? '') === 'custom'; + + return (string) ($is_custom + ? ($item_row['cl_scmanutentionitem_custom_uuid'] ?? '') + : ($item_row['cl_scmanutentionitem_base_uuid'] ?? '')); +} + +function scmanutention_item_rarity(array $item_row): string +{ + $is_custom = ($item_row['cl_scmanutentionitem_source'] ?? '') === 'custom'; + + return (string) ($is_custom + ? ($item_row['cl_scmanutentionitem_custom_rarity'] ?? '') + : ($item_row['cl_scmanutentionitem_base_rarity'] ?? '')); +} + +function scmanutention_format_stat_preview(array $stat_row): string +{ + $sign = (string) ($stat_row['cl_scitemcustomstat_sign'] ?? ''); + $prefix = $sign === '-' ? '-' : ($sign === '+' ? '+' : ''); + $value = (float) ($stat_row['cl_scitemcustomstat_value'] ?? 0); + $formatted = number_format($value, 2, '.', ''); + $formatted = rtrim(rtrim($formatted, '0'), '.'); + if ($formatted === '') { + $formatted = '0'; + } + + $unit = trim((string) ($stat_row['cl_scstatsitem_unit'] ?? '')); + + return trim((string) ($stat_row['cl_scstatsitem_name'] ?? '') . ' : ' . $prefix . $formatted . ($unit !== '' ? ' ' . $unit : '')); +} + +$flash = auth_flash_get(); +$flash_type = $flash['type'] ?? ''; +$flash_message = $flash['message'] ?? ''; + +$db = db(); +$csrf_token = auth_csrf_token(); +$current_owner_auth_id = scmanutention_current_owner_auth_id($db); +$current_role_label = auth_role_label(auth_current_role()); +$current_session_user = auth_current_user(); + +if ($current_owner_auth_id <= 0) { + auth_flash_set('error', 'Utilisateur introuvable. Merci de vous reconnecter.'); + header('Location: logout.php'); + exit; +} + +if ($_SERVER['REQUEST_METHOD'] === 'GET' && (string) ($_GET['ajax'] ?? '') === 'item_suggestions') { + header('Content-Type: application/json; charset=utf-8'); + + $query = trim((string) ($_GET['q'] ?? '')); + $items = array_map(static function (array $row): array { + return [ + 'key' => (string) $row['result_key'], + 'source' => (string) $row['result_source'], + 'sourceLabel' => ((string) $row['result_source']) === 'custom' ? 'Objet perso' : 'Base d\'objets', + 'scobjs_id' => (int) ($row['result_scobjs_id'] ?? 0), + 'scitemcustom_id' => (int) ($row['result_scitemcustom_id'] ?? 0), + 'name' => (string) ($row['result_name'] ?? ''), + 'type' => (string) ($row['result_type'] ?? ''), + 'subtype' => (string) ($row['result_subtype'] ?? ''), + 'uuid' => (string) ($row['result_uuid'] ?? ''), + 'rarity' => (string) ($row['result_rarity'] ?? ''), + ]; + }, scmanutention_search_available_items($db, $current_owner_auth_id, $query, 14)); + + echo json_encode(['items' => $items], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + exit; +} + +$selected_sheet_id = isset($_GET['sheet']) ? (int) $_GET['sheet'] : 0; + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $csrf = isset($_POST['csrf_token']) ? (string) $_POST['csrf_token'] : null; + if (!auth_validate_csrf($csrf)) { + auth_flash_set('error', 'Jeton CSRF invalide.'); + scmanutention_redirect($selected_sheet_id); + } + + $action = trim((string) ($_POST['action'] ?? '')); + + if ($action === 'create_sheet') { + $title = scmanutention_clean_text($_POST['title'] ?? ''); + $type = scmanutention_clean_text($_POST['type'] ?? ''); + $subtype = scmanutention_clean_text($_POST['subtype'] ?? ''); + $description = scmanutention_clean_text($_POST['description'] ?? ''); + $share_enabled = isset($_POST['share_enabled']) ? 1 : 0; + + if ($title === '') { + auth_flash_set('error', 'Le nom de la fiche est obligatoire.'); + scmanutention_redirect(); + } + + $stmt = $db->prepare( + 'INSERT INTO tbl_scmanutentions ( + cl_scmanutention_owner_auth_id, + cl_scmanutention_title, + cl_scmanutention_type, + cl_scmanutention_subtype, + cl_scmanutention_description, + cl_scmanutention_share_token, + cl_scmanutention_share_enabled + ) VALUES ( + :owner_auth_id, + :title, + :type, + :subtype, + :description, + :share_token, + :share_enabled + )' + ); + $stmt->execute([ + 'owner_auth_id' => $current_owner_auth_id, + 'title' => $title, + 'type' => $type, + 'subtype' => $subtype, + 'description' => $description !== '' ? $description : null, + 'share_token' => scmanutention_generate_share_token(), + 'share_enabled' => $share_enabled, + ]); + + $new_sheet_id = (int) $db->lastInsertId(); + auth_flash_set('success', 'Fiche créée avec succès.'); + scmanutention_redirect($new_sheet_id, 'sheet-settings'); + } + + if ($action === 'update_sheet') { + $sheet_id = (int) ($_POST['sheet_id'] ?? 0); + $sheet = scmanutention_find_owned_sheet($db, $sheet_id, $current_owner_auth_id); + if (!$sheet) { + auth_flash_set('error', 'Fiche introuvable.'); + scmanutention_redirect(); + } + + $title = scmanutention_clean_text($_POST['title'] ?? ''); + $type = scmanutention_clean_text($_POST['type'] ?? ''); + $subtype = scmanutention_clean_text($_POST['subtype'] ?? ''); + $description = scmanutention_clean_text($_POST['description'] ?? ''); + $share_enabled = isset($_POST['share_enabled']) ? 1 : 0; + + if ($title === '') { + auth_flash_set('error', 'Le nom de la fiche est obligatoire.'); + scmanutention_redirect($sheet_id, 'sheet-settings'); + } + + $stmt = $db->prepare( + 'UPDATE tbl_scmanutentions + SET cl_scmanutention_title = :title, + cl_scmanutention_type = :type, + cl_scmanutention_subtype = :subtype, + cl_scmanutention_description = :description, + cl_scmanutention_share_enabled = :share_enabled + WHERE cl_scmanutention_id = :sheet_id' + ); + $stmt->execute([ + 'title' => $title, + 'type' => $type, + 'subtype' => $subtype, + 'description' => $description !== '' ? $description : null, + 'share_enabled' => $share_enabled, + 'sheet_id' => $sheet_id, + ]); + + auth_flash_set('success', 'Fiche mise à jour.'); + scmanutention_redirect($sheet_id, 'sheet-settings'); + } + + if ($action === 'regenerate_share') { + $sheet_id = (int) ($_POST['sheet_id'] ?? 0); + $sheet = scmanutention_find_owned_sheet($db, $sheet_id, $current_owner_auth_id); + if (!$sheet) { + auth_flash_set('error', 'Fiche introuvable.'); + scmanutention_redirect(); + } + + $stmt = $db->prepare( + 'UPDATE tbl_scmanutentions + SET cl_scmanutention_share_token = :share_token + WHERE cl_scmanutention_id = :sheet_id' + ); + $stmt->execute([ + 'share_token' => scmanutention_generate_share_token(), + 'sheet_id' => $sheet_id, + ]); + + auth_flash_set('success', 'Lien public régénéré.'); + scmanutention_redirect($sheet_id, 'sheet-settings'); + } + + if ($action === 'delete_sheet') { + $sheet_id = (int) ($_POST['sheet_id'] ?? 0); + $sheet = scmanutention_find_owned_sheet($db, $sheet_id, $current_owner_auth_id); + if (!$sheet) { + auth_flash_set('error', 'Fiche introuvable.'); + scmanutention_redirect(); + } + + $stmt = $db->prepare('DELETE FROM tbl_scmanutentions WHERE cl_scmanutention_id = :sheet_id'); + $stmt->execute(['sheet_id' => $sheet_id]); + + auth_flash_set('success', 'Fiche supprimée.'); + scmanutention_redirect(); + } + + if ($action === 'add_item') { + $sheet_id = (int) ($_POST['sheet_id'] ?? 0); + $sheet = scmanutention_find_owned_sheet($db, $sheet_id, $current_owner_auth_id); + if (!$sheet) { + auth_flash_set('error', 'Fiche introuvable.'); + scmanutention_redirect(); + } + + $source = trim((string) ($_POST['item_source'] ?? '')); + $scobjs_id = (int) ($_POST['item_scobjs_id'] ?? 0); + $scitemcustom_id = (int) ($_POST['item_scitemcustom_id'] ?? 0); + $quantity = scmanutention_normalize_quantity($_POST['quantity'] ?? 1); + $extra_info = scmanutention_clean_text($_POST['extra_info'] ?? ''); + + $item_reference = scmanutention_validate_item_reference($db, $current_owner_auth_id, $source, $scobjs_id, $scitemcustom_id); + if (!$item_reference) { + auth_flash_set('error', 'Objet invalide ou inaccessible.'); + scmanutention_redirect($sheet_id, 'item-add-card'); + } + + $stmt = $db->prepare( + 'INSERT INTO tbl_scmanutentionitems ( + cl_scmanutentionitem_manutention_id, + cl_scmanutentionitem_source, + cl_scmanutentionitem_scobjs_id, + cl_scmanutentionitem_scitemcustom_id, + cl_scmanutentionitem_quantity, + cl_scmanutentionitem_extra_info, + cl_scmanutentionitem_sort_order + ) VALUES ( + :sheet_id, + :source, + :scobjs_id, + :scitemcustom_id, + :quantity, + :extra_info, + :sort_order + )' + ); + $stmt->execute([ + 'sheet_id' => $sheet_id, + 'source' => $item_reference['source'], + 'scobjs_id' => $item_reference['scobjs_id'] > 0 ? $item_reference['scobjs_id'] : null, + 'scitemcustom_id' => $item_reference['scitemcustom_id'] > 0 ? $item_reference['scitemcustom_id'] : null, + 'quantity' => $quantity, + 'extra_info' => $extra_info !== '' ? $extra_info : null, + 'sort_order' => scmanutention_next_item_sort_order($db, $sheet_id), + ]); + + auth_flash_set('success', 'Objet ajouté à la fiche.'); + scmanutention_redirect($sheet_id, 'sheet-items'); + } + + if ($action === 'update_item') { + $item_id = (int) ($_POST['item_id'] ?? 0); + $item_row = scmanutention_find_owned_item($db, $item_id, $current_owner_auth_id); + if (!$item_row) { + auth_flash_set('error', 'Ligne introuvable.'); + scmanutention_redirect($selected_sheet_id); + } + + $sheet_id = (int) $item_row['cl_scmanutentionitem_manutention_id']; + $source = trim((string) ($_POST['item_source'] ?? '')); + $scobjs_id = (int) ($_POST['item_scobjs_id'] ?? 0); + $scitemcustom_id = (int) ($_POST['item_scitemcustom_id'] ?? 0); + $quantity = scmanutention_normalize_quantity($_POST['quantity'] ?? 1); + $extra_info = scmanutention_clean_text($_POST['extra_info'] ?? ''); + + $item_reference = scmanutention_validate_item_reference($db, $current_owner_auth_id, $source, $scobjs_id, $scitemcustom_id); + if (!$item_reference) { + auth_flash_set('error', 'Objet invalide ou inaccessible.'); + scmanutention_redirect($sheet_id, 'manutention-item-' . $item_id); + } + + $stmt = $db->prepare( + 'UPDATE tbl_scmanutentionitems + SET cl_scmanutentionitem_source = :source, + cl_scmanutentionitem_scobjs_id = :scobjs_id, + cl_scmanutentionitem_scitemcustom_id = :scitemcustom_id, + cl_scmanutentionitem_quantity = :quantity, + cl_scmanutentionitem_extra_info = :extra_info + WHERE cl_scmanutentionitem_id = :item_id' + ); + $stmt->execute([ + 'source' => $item_reference['source'], + 'scobjs_id' => $item_reference['scobjs_id'] > 0 ? $item_reference['scobjs_id'] : null, + 'scitemcustom_id' => $item_reference['scitemcustom_id'] > 0 ? $item_reference['scitemcustom_id'] : null, + 'quantity' => $quantity, + 'extra_info' => $extra_info !== '' ? $extra_info : null, + 'item_id' => $item_id, + ]); + + auth_flash_set('success', 'Ligne mise à jour.'); + scmanutention_redirect($sheet_id, 'manutention-item-' . $item_id); + } + + if ($action === 'delete_item') { + $item_id = (int) ($_POST['item_id'] ?? 0); + $item_row = scmanutention_find_owned_item($db, $item_id, $current_owner_auth_id); + if (!$item_row) { + auth_flash_set('error', 'Ligne introuvable.'); + scmanutention_redirect($selected_sheet_id); + } + + $sheet_id = (int) $item_row['cl_scmanutentionitem_manutention_id']; + $stmt = $db->prepare('DELETE FROM tbl_scmanutentionitems WHERE cl_scmanutentionitem_id = :item_id'); + $stmt->execute(['item_id' => $item_id]); + scmanutention_reindex_items($db, $sheet_id); + + auth_flash_set('success', 'Ligne supprimée.'); + scmanutention_redirect($sheet_id, 'sheet-items'); + } + + auth_flash_set('error', 'Action inconnue.'); + scmanutention_redirect($selected_sheet_id); +} + +$stmt_sheets = $db->prepare( + 'SELECT + m.*, + COUNT(mi.cl_scmanutentionitem_id) AS cl_item_total + FROM tbl_scmanutentions m + LEFT JOIN tbl_scmanutentionitems mi ON mi.cl_scmanutentionitem_manutention_id = m.cl_scmanutention_id + WHERE m.cl_scmanutention_owner_auth_id = :owner_auth_id + GROUP BY m.cl_scmanutention_id + ORDER BY m.cl_scmanutention_updated_at DESC, m.cl_scmanutention_id DESC' +); +$stmt_sheets->execute(['owner_auth_id' => $current_owner_auth_id]); +$sheets = $stmt_sheets->fetchAll() ?: []; + +if ($selected_sheet_id <= 0 && !empty($sheets)) { + $selected_sheet_id = (int) $sheets[0]['cl_scmanutention_id']; +} + +$selected_sheet = $selected_sheet_id > 0 + ? scmanutention_find_owned_sheet($db, $selected_sheet_id, $current_owner_auth_id) + : null; + +$selected_items = $selected_sheet + ? scmanutention_fetch_items($db, (int) $selected_sheet['cl_scmanutention_id']) + : []; +$custom_stats_map = scmanutention_fetch_custom_stats_map($db, $selected_items); +$page_access_widget = auth_render_page_access_widget('scmanutention.php', 'Manutention'); +?> + + + + + + Manutention + + + + + + +
+
+
+

MANUTENTION

+

Gestion de fiches privées/publiques avec ajout interactif d’objets, quantités et informations complémentaires.

+

Niveau d'accès :

+
+
+ Connecté : + Retour au site + Déconnexion +
+
+ + + + +
+ +
+ + +
+ + +
+ +
+

Aucune fiche sélectionnée

+
Crée une fiche ou sélectionne-en une dans la colonne de gauche pour commencer à ajouter des objets.
+
+ +
+
+
+

+
+ + + + + + + + objet(s) +
+
+
+ +

+ + +
+ +
+

Ajouter un objet

+

Recherche interactive inspirée de la page objets perso : base d’objets + objets personnalisés, avec quantité et info libre.

+
+ + + + +
+ + + + +
+ + +
+ +
La recherche démarre à partir de 2 caractères et distingue les objets de base des objets persos.
+ + +
+ +
+
+ + +
+
+ + +
+
+ +
+ +
+
+
+ +
+

Objets de la fiche

+ +
Cette fiche ne contient encore aucun objet. Utilise la recherche ci-dessus pour commencer.
+ +
+ + +
+
+
+ + + +
+
+ x + +
+
+ + + + + + + + + + +
+
+
+
+
+ + + + +
+
+
+ + +
+ + +
+ Modifier la ligne +
+ + + + +
+ + + + +
+ + +
+ +
+
+ +
+ +
+ +
+
+
+ +
+
+ +
+
+ + +
+
+ + +
+
+
+ +
+
+
+
+ +
+ +
+ +
+
+
+ + + diff --git a/scmanutentionpublic.php b/scmanutentionpublic.php new file mode 100644 index 0000000..718e2ec --- /dev/null +++ b/scmanutentionpublic.php @@ -0,0 +1,322 @@ + + + + + + + <?php echo htmlspecialchars($sheet ? ((string) $sheet['cl_scmanutention_title'] . ' | Fiche manutention') : 'Fiche introuvable', ENT_QUOTES, 'UTF-8'); ?> + + + +
+ +
+

Fiche introuvable

+

Cette fiche n’existe pas, n’est plus publique, ou le lien partagé n’est plus valide.

+
+ +
+

+
+ + + + + + + objet(s) + Publié par +
+ +

+ +

Cette fiche publique ne contient pas encore de description.

+ +
+ +
+

Contenu de la fiche

+ +

Aucun objet n’est actuellement listé sur cette fiche.

+ +
+ + +
+
+ + + +
+
+ x +
+
+
+ + + + + + + + + + +
+
+
+ + +
+ + +
+ +
+ +
+ +
+ +