unwrapList($rows); } public function nextBookmarkSortOrder(int $userId, ?int $groupId): int { if ($userId <= 0) { return 1; } if ($groupId !== null && $groupId > 0) { $max = DB::selectValue( 'select COALESCE(max(sort_order), 0) from user_bookmarks where user_id = ? and group_id = ?', (string) $userId, (string) $groupId ); return max(1, ((int) $max) + 1); } $max = DB::selectValue( 'select COALESCE(max(sort_order), 0) from user_bookmarks where user_id = ? and group_id is NULL', (string) $userId ); return max(1, ((int) $max) + 1); } public function countByUser(int $userId): int { if ($userId <= 0) { return 0; } $count = DB::selectValue( 'select count(*) from user_bookmarks where user_id = ?', (string) $userId ); return $count ? (int) $count : 0; } public function findById(int $id, int $userId): array|false { if ($id <= 0 || $userId <= 0) { return false; } $rows = DB::select( 'select id, user_id, group_id, name, url, sort_order, created, modified from user_bookmarks where id = ? and user_id = ?', (string) $id, (string) $userId ); $list = $this->unwrapList($rows); return $list[0] ?? false; } public function findByUserAndUrl(int $userId, string $url): array|false { $url = trim($url); if ($userId <= 0 || $url === '') { return false; } $rows = DB::select( 'select id, user_id, group_id, name, url, sort_order, created, modified from user_bookmarks where user_id = ? and url = ? order by id desc limit 1', (string) $userId, $url ); $list = $this->unwrapList($rows); return $list[0] ?? false; } public function create(array $data): int|false { $userId = (int) ($data['user_id'] ?? 0); $name = trim((string) ($data['name'] ?? '')); $url = trim((string) ($data['url'] ?? '')); $groupId = isset($data['group_id']) ? (int) $data['group_id'] : null; $sortOrder = (int) ($data['sort_order'] ?? 0); if ($userId <= 0 || $name === '' || $url === '') { return false; } $groupIdParam = ($groupId !== null && $groupId > 0) ? (string) $groupId : null; return DB::insert( 'insert into user_bookmarks (user_id, group_id, name, url, sort_order, created) values (?,?,?,?,?,NOW())', (string) $userId, $groupIdParam, $name, $url, (string) $sortOrder ); } public function update(int $id, int $userId, array $data): bool { if ($id <= 0 || $userId <= 0) { return false; } $sets = []; $params = []; if (array_key_exists('name', $data)) { $name = trim((string) $data['name']); if ($name === '') { return false; } $sets[] = 'name = ?'; $params[] = $name; } if (array_key_exists('group_id', $data)) { $sets[] = 'group_id = ?'; $groupId = $data['group_id']; $params[] = ($groupId !== null && (int) $groupId > 0) ? (string) (int) $groupId : null; } if (array_key_exists('url', $data)) { $url = trim((string) $data['url']); if ($url === '') { return false; } $sets[] = 'url = ?'; $params[] = $url; } if (array_key_exists('sort_order', $data)) { $sortOrder = (int) $data['sort_order']; if ($sortOrder <= 0) { return false; } $sets[] = 'sort_order = ?'; $params[] = (string) $sortOrder; } if ($sets === []) { return false; } $params[] = (string) $id; $params[] = (string) $userId; $affected = DB::update( 'update user_bookmarks set ' . implode(', ', $sets) . ' where id = ? and user_id = ?', ...$params ); return $affected !== false; } public function delete(int $id, int $userId): bool { if ($id <= 0 || $userId <= 0) { return false; } $deleted = DB::delete( 'delete from user_bookmarks where id = ? and user_id = ?', (string) $id, (string) $userId ); return $deleted !== false && (int) $deleted > 0; } /** @return list> */ public function listByGroup(int $userId, int $groupId): array { if ($userId <= 0 || $groupId <= 0) { return []; } $rows = DB::select( 'select id, user_id, group_id, name, url, sort_order from user_bookmarks where user_id = ? and group_id = ? order by sort_order, id', (string) $userId, (string) $groupId ); return $this->unwrapList($rows); } public function unsetGroupId(int $bookmarkId, int $userId, int $sortOrder): bool { if ($bookmarkId <= 0 || $userId <= 0 || $sortOrder <= 0) { return false; } $updated = DB::update( 'update user_bookmarks set group_id = NULL, sort_order = ? where id = ? and user_id = ?', (string) $sortOrder, (string) $bookmarkId, (string) $userId ); return $updated !== false; } }