From a472ed9a8fdaea192568f50d454f5fc477289956 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Thu, 16 Apr 2026 09:44:15 +0000 Subject: [PATCH] V1.2.7 --- database/full.sql | 3 ++ database/schema.sql | 3 ++ db/sccharacters.php | 62 ++++++++++++++++++++++ sccharacter.php | 60 ++++++++++++++++++--- sccharacters.php | 124 ++++++++++++++++++++++++++++++++++++++------ 5 files changed, 231 insertions(+), 21 deletions(-) diff --git a/database/full.sql b/database/full.sql index 43f0078..1ccdc5f 100644 --- a/database/full.sql +++ b/database/full.sql @@ -18734,6 +18734,9 @@ CREATE TABLE IF NOT EXISTS tbl_sccharacters ( cl_sccharacter_name VARCHAR(190) NOT NULL, cl_sccharacter_role VARCHAR(190) NOT NULL DEFAULT '', cl_sccharacter_faction VARCHAR(190) NOT NULL DEFAULT '', + cl_sccharacter_org_rsi_url VARCHAR(255) NOT NULL DEFAULT '', + cl_sccharacter_is_player TINYINT(1) NOT NULL DEFAULT 0, + cl_sccharacter_player_handle VARCHAR(190) NOT NULL DEFAULT '', cl_sccharacter_avatar_url VARCHAR(255) NOT NULL DEFAULT '', cl_sccharacter_description TEXT DEFAULT NULL, cl_sccharacter_notes TEXT DEFAULT NULL, diff --git a/database/schema.sql b/database/schema.sql index ae6fe80..5d4b61e 100644 --- a/database/schema.sql +++ b/database/schema.sql @@ -213,6 +213,9 @@ CREATE TABLE IF NOT EXISTS tbl_sccharacters ( cl_sccharacter_name VARCHAR(190) NOT NULL, cl_sccharacter_role VARCHAR(190) NOT NULL DEFAULT '', cl_sccharacter_faction VARCHAR(190) NOT NULL DEFAULT '', + cl_sccharacter_org_rsi_url VARCHAR(255) NOT NULL DEFAULT '', + cl_sccharacter_is_player TINYINT(1) NOT NULL DEFAULT 0, + cl_sccharacter_player_handle VARCHAR(190) NOT NULL DEFAULT '', cl_sccharacter_avatar_url VARCHAR(255) NOT NULL DEFAULT '', cl_sccharacter_description TEXT DEFAULT NULL, cl_sccharacter_notes TEXT DEFAULT NULL, diff --git a/db/sccharacters.php b/db/sccharacters.php index 54c1b55..695ca88 100644 --- a/db/sccharacters.php +++ b/db/sccharacters.php @@ -51,6 +51,9 @@ function sccharacters_bootstrap(): void cl_sccharacter_name VARCHAR(190) NOT NULL, cl_sccharacter_role VARCHAR(190) NOT NULL DEFAULT '', cl_sccharacter_faction VARCHAR(190) NOT NULL DEFAULT '', + cl_sccharacter_org_rsi_url VARCHAR(255) NOT NULL DEFAULT '', + cl_sccharacter_is_player TINYINT(1) NOT NULL DEFAULT 0, + cl_sccharacter_player_handle VARCHAR(190) NOT NULL DEFAULT '', cl_sccharacter_avatar_url VARCHAR(255) NOT NULL DEFAULT '', cl_sccharacter_description TEXT DEFAULT NULL, cl_sccharacter_notes TEXT DEFAULT NULL, @@ -99,6 +102,27 @@ function sccharacters_bootstrap(): void ); } + if (!sccharacters_column_exists($db, 'tbl_sccharacters', 'cl_sccharacter_org_rsi_url')) { + $db->exec( + "ALTER TABLE tbl_sccharacters + ADD COLUMN cl_sccharacter_org_rsi_url VARCHAR(255) NOT NULL DEFAULT '' AFTER cl_sccharacter_faction" + ); + } + + if (!sccharacters_column_exists($db, 'tbl_sccharacters', 'cl_sccharacter_is_player')) { + $db->exec( + 'ALTER TABLE tbl_sccharacters + ADD COLUMN cl_sccharacter_is_player TINYINT(1) NOT NULL DEFAULT 0 AFTER cl_sccharacter_org_rsi_url' + ); + } + + if (!sccharacters_column_exists($db, 'tbl_sccharacters', 'cl_sccharacter_player_handle')) { + $db->exec( + "ALTER TABLE tbl_sccharacters + ADD COLUMN cl_sccharacter_player_handle VARCHAR(190) NOT NULL DEFAULT '' AFTER cl_sccharacter_is_player" + ); + } + if (!sccharacters_column_exists($db, 'tbl_sccharacters', 'cl_sccharacter_category_order')) { $db->exec( 'ALTER TABLE tbl_sccharacters @@ -287,6 +311,44 @@ function sccharacters_generate_share_token(PDO $db): string return $token; } + +function sccharacters_extract_org_tag(?string $url): string +{ + $url = trim((string) $url); + if ($url === '') { + return ''; + } + + $path = trim((string) parse_url($url, PHP_URL_PATH)); + if ($path === '') { + return ''; + } + + if (preg_match('~/(?:[a-z]{2}/)?orgs/([^/?#]+)~i', $path, $matches)) { + $tag = rawurldecode((string) ($matches[1] ?? '')); + } else { + $segments = array_values(array_filter(explode('/', trim($path, '/')), static fn (string $segment): bool => $segment !== '')); + $tag = $segments !== [] ? rawurldecode((string) end($segments)) : ''; + } + + $tag = preg_replace('/[^A-Za-z0-9._-]+/', '', (string) $tag); + if (!is_string($tag)) { + return ''; + } + + return strtoupper(trim($tag)); +} + +function sccharacters_resolve_org_tag(array $character): string +{ + return sccharacters_extract_org_tag((string) ($character['cl_sccharacter_org_rsi_url'] ?? '')); +} + +function sccharacters_has_player_handle(array $character): bool +{ + return trim((string) ($character['cl_sccharacter_player_handle'] ?? '')) !== ''; +} + function sccharacters_reindex_character_items(PDO $db, int $character_id): void { if ($character_id <= 0) { diff --git a/sccharacter.php b/sccharacter.php index 68f8e49..021a241 100644 --- a/sccharacter.php +++ b/sccharacter.php @@ -16,6 +16,8 @@ $share_token = trim((string) ($_GET['share'] ?? '')); $character = null; $character_items = []; $custom_stats_by_itemcustom = []; +$character_org_tag = ''; +$character_has_player_handle = false; if ($share_token !== '') { $stmt_character = $db->prepare( @@ -31,6 +33,8 @@ if ($share_token !== '') { } if ($character) { + $character_org_tag = sccharacters_resolve_org_tag($character); + $character_has_player_handle = sccharacters_has_player_handle($character); sccharacters_reindex_character_items($db, (int) $character['cl_sccharacter_id']); $stmt_items = $db->prepare( @@ -227,6 +231,42 @@ $character_items_by_category = sccharacters_sort_items_by_category_order( align-items: center; } + .identity-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 0.7rem; + margin-bottom: 0.8rem; + } + + .identity-item { + display: flex; + flex-direction: column; + gap: 0.24rem; + padding: 0.76rem 0.84rem; + border-radius: 14px; + background: rgba(255,255,255,0.05); + border: 1px solid rgba(255,255,255,0.1); + } + + .identity-label { + font-size: 0.7rem; + letter-spacing: 0.09em; + text-transform: uppercase; + color: var(--text-soft); + } + + .identity-value { + font-size: 0.96rem; + font-weight: 600; + color: #f6f7fb; + line-height: 1.35; + word-break: break-word; + } + + .meta { + margin-top: 0.2rem; + } + .tag { display: inline-flex; align-items: center; @@ -389,13 +429,21 @@ $character_items_by_category = sccharacters_sort_items_by_category_order(

+
+
+ Rôle / Classe + +
+
+ Tag + +
+
+ Handle + +
+
- - - - - - Créé par équipement(s)
diff --git a/sccharacters.php b/sccharacters.php index 53ec7ce..ed51597 100644 --- a/sccharacters.php +++ b/sccharacters.php @@ -886,7 +886,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($action === 'create_character') { $name = sccharacters_clean_text($_POST['character_name'] ?? ''); $role = sccharacters_clean_text($_POST['character_role'] ?? ''); - $faction = sccharacters_clean_text($_POST['character_faction'] ?? ''); + $faction = ''; + $org_rsi_url = sccharacters_clean_text($_POST['character_org_rsi_url'] ?? ''); + $player_handle = sccharacters_clean_text($_POST['character_player_handle'] ?? ''); + $is_player = $player_handle !== '' ? 1 : 0; $avatar_url = sccharacters_clean_text($_POST['character_avatar_url'] ?? ''); $description = sccharacters_clean_text($_POST['character_description'] ?? ''); $notes = sccharacters_clean_text($_POST['character_notes'] ?? ''); @@ -907,12 +910,21 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { exit; } + if (!sccharacters_is_valid_url($org_rsi_url)) { + auth_flash_set('error', 'L’URL RSI de l’organisation n’est pas valide.'); + header('Location: sccharacters.php?mode=create'); + exit; + } + $stmt = $db->prepare( 'INSERT INTO tbl_sccharacters ( cl_sccharacter_owner_auth_id, cl_sccharacter_name, cl_sccharacter_role, cl_sccharacter_faction, + cl_sccharacter_org_rsi_url, + cl_sccharacter_is_player, + cl_sccharacter_player_handle, cl_sccharacter_avatar_url, cl_sccharacter_description, cl_sccharacter_notes, @@ -924,6 +936,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { :name, :role, :faction, + :org_rsi_url, + :is_player, + :player_handle, :avatar_url, :description, :notes, @@ -937,6 +952,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { 'name' => $name, 'role' => $role, 'faction' => $faction, + 'org_rsi_url' => $org_rsi_url, + 'is_player' => $is_player, + 'player_handle' => $player_handle, 'avatar_url' => $avatar_url, 'description' => $description !== '' ? $description : null, 'notes' => $notes !== '' ? $notes : null, @@ -963,7 +981,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $name = sccharacters_clean_text($_POST['character_name'] ?? ''); $role = sccharacters_clean_text($_POST['character_role'] ?? ''); - $faction = sccharacters_clean_text($_POST['character_faction'] ?? ''); + $faction = ''; + $org_rsi_url = sccharacters_clean_text($_POST['character_org_rsi_url'] ?? ''); + $player_handle = sccharacters_clean_text($_POST['character_player_handle'] ?? ''); + $is_player = $player_handle !== '' ? 1 : 0; $avatar_url = sccharacters_clean_text($_POST['character_avatar_url'] ?? ''); $description = sccharacters_clean_text($_POST['character_description'] ?? ''); $notes = sccharacters_clean_text($_POST['character_notes'] ?? ''); @@ -984,11 +1005,20 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { exit; } + if (!sccharacters_is_valid_url($org_rsi_url)) { + auth_flash_set('error', 'L’URL RSI de l’organisation n’est pas valide.'); + header('Location: sccharacters.php?character=' . $character_id); + exit; + } + $stmt = $db->prepare( 'UPDATE tbl_sccharacters SET cl_sccharacter_name = :name, cl_sccharacter_role = :role, cl_sccharacter_faction = :faction, + cl_sccharacter_org_rsi_url = :org_rsi_url, + cl_sccharacter_is_player = :is_player, + cl_sccharacter_player_handle = :player_handle, cl_sccharacter_avatar_url = :avatar_url, cl_sccharacter_description = :description, cl_sccharacter_notes = :notes, @@ -1001,6 +1031,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { 'name' => $name, 'role' => $role, 'faction' => $faction, + 'org_rsi_url' => $org_rsi_url, + 'is_player' => $is_player, + 'player_handle' => $player_handle, 'avatar_url' => $avatar_url, 'description' => $description !== '' ? $description : null, 'notes' => $notes !== '' ? $notes : null, @@ -1581,12 +1614,17 @@ $create_character = [ 'cl_sccharacter_name' => '', 'cl_sccharacter_role' => '', 'cl_sccharacter_faction' => '', + 'cl_sccharacter_org_rsi_url' => '', + 'cl_sccharacter_is_player' => 0, + 'cl_sccharacter_player_handle' => '', 'cl_sccharacter_avatar_url' => '', 'cl_sccharacter_description' => '', 'cl_sccharacter_notes' => '', 'cl_sccharacter_share_enabled' => 0, 'cl_sccharacter_is_pinned' => 0, ]; +$selected_character_org_tag = $selected_character ? sccharacters_resolve_org_tag($selected_character) : ''; +$selected_character_has_player_handle = $selected_character ? sccharacters_has_player_handle($selected_character) : false; $item_has_previous_page = $item_page > 1; $item_has_next_page = $item_page < $item_total_pages; $item_query_base_params = []; @@ -2066,6 +2104,41 @@ if ($selected_character) { flex-wrap: wrap; } + .hero-meta-secondary { + margin-top: 0.7rem; + } + + .identity-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 0.7rem; + } + + .identity-item { + display: flex; + flex-direction: column; + gap: 0.22rem; + padding: 0.72rem 0.82rem; + border-radius: 14px; + background: rgba(255,255,255,0.05); + border: 1px solid rgba(255,255,255,0.1); + } + + .identity-label { + font-size: 0.7rem; + letter-spacing: 0.09em; + text-transform: uppercase; + color: var(--text-soft); + } + + .identity-value { + font-size: 0.95rem; + font-weight: 600; + color: #f6f7fb; + line-height: 1.35; + word-break: break-word; + } + .badge { display: inline-flex; align-items: center; @@ -2797,8 +2870,12 @@ if ($selected_character) {
- - + + +
+
+ +
@@ -2857,6 +2934,8 @@ if ($selected_character) { $initial = function_exists('mb_substr') ? mb_strtoupper(mb_substr((string) $character_row['cl_sccharacter_name'], 0, 1, 'UTF-8'), 'UTF-8') : strtoupper(substr((string) $character_row['cl_sccharacter_name'], 0, 1)); + $character_row_org_tag = sccharacters_resolve_org_tag($character_row); + $character_row_has_player_handle = sccharacters_has_player_handle($character_row); $character_link = 'sccharacters.php?character=' . $character_id . '&item_source=' . rawurlencode($item_source); if ($item_search !== '') { $character_link .= '&item_search=' . rawurlencode($item_search); @@ -2879,8 +2958,11 @@ if ($selected_character) { - - + + Org: + + + Handle: objet(s) @@ -2922,13 +3004,21 @@ if ($selected_character) { 📌
-
- - - - - - +
+
+ Rôle / Classe + +
+
+ Tag organisation + +
+
+ Handle + +
+
+
équipement(s)
@@ -2987,8 +3077,12 @@ if ($selected_character) {
- - + + +
+
+ +