39514-vm/db/scmanutention.php
Flatlogic Bot 99a83d106c V1.4.9
2026-05-07 01:31:16 +00:00

802 lines
29 KiB
PHP

<?php
require_once __DIR__ . '/config.php';
function scmanutention_column_exists(PDO $db, string $table, string $column): bool
{
$stmt = $db->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 = 25, int $offset = 0): array
{
$query = trim($query);
if ($query === '') {
return [];
}
$escaped = scmanutention_escape_like($query);
$exact = $escaped;
$prefix = $escaped . '%';
$contains = '%' . $escaped . '%';
$limit_clause = '';
$offset = max(0, $offset);
if ($limit !== null && $limit > 0) {
$limit = max(1, min(100, $limit));
$limit_clause = ' LIMIT ' . (int) $limit . ' OFFSET ' . (int) $offset;
}
$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_clause}";
$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;
}
function scmanutention_fetch_custom_stats_preview_map(PDO $db, array $custom_ids): array
{
$custom_ids = array_values(array_unique(array_map('intval', 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;
}