Files
bookmarkly2/bookmarks.php
T

679 lines
35 KiB
PHP

<?php
$page_title = 'Manage Bookmarks - Bookmarkly';
require_once 'include/auth.php';
// --- Security Check: Only Admin and User roles can access this page ---
if (!isAdmin() && !isUser()) {
header('Location: index.php');
exit;
}
// Add settings-page class to body for CSS targeting
$GLOBALS['body_class'] = 'bookmarks-page';
// Flash messages for feedback
$message = '';
$message_type = '';
if (isset($_SESSION['flash_message'])) {
$message = $_SESSION['flash_message']['text'];
$message_type = $_SESSION['flash_message']['type'];
unset($_SESSION['flash_message']);
}
// --- Helper function for icon uploads ---
function handle_icon_upload($bookmark_id = null, $title = '') {
if (isset($_FILES['icon_upload']) && $_FILES['icon_upload']['error'] === UPLOAD_ERR_OK) {
$upload_dir = 'data/images/custom/';
if (!is_dir($upload_dir)) {
mkdir($upload_dir, 0755, true);
}
$file_info = pathinfo($_FILES['icon_upload']['name']);
$extension = strtolower($file_info['extension']);
$allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'ico'];
if (in_array($extension, $allowed_extensions)) {
// Sanitize title for filename
$sanitized_title = trim($title);
if (empty($sanitized_title)) {
$sanitized_title = 'bookmark';
} else {
$sanitized_title = strtolower($sanitized_title);
$sanitized_title = str_replace(' ', '_', $sanitized_title);
// Remove characters that are not letters, numbers, underscores, or hyphens
$sanitized_title = preg_replace('/[^a-z0-9_-]/', '', $sanitized_title);
// Truncate to a reasonable length
$sanitized_title = substr($sanitized_title, 0, 50);
}
$filename = 'bookmark_' . ($bookmark_id ?? 'id') . '_' . $sanitized_title . '.' . $extension;
$destination = $upload_dir . $filename;
// Before moving, if we are editing, we should delete the old file.
if ($bookmark_id) {
global $pdo;
$stmt = $pdo->prepare("SELECT icon FROM bookmarks WHERE id = ?");
$stmt->execute([$bookmark_id]);
$old_icon = $stmt->fetchColumn();
// Check if old icon exists, is custom, and is not the same path as the new one
if ($old_icon && file_exists($old_icon) && strpos($old_icon, 'data/images/custom/') === 0 && $old_icon !== $destination) {
unlink($old_icon);
}
}
if (move_uploaded_file($_FILES['icon_upload']['tmp_name'], $destination)) {
return $destination; // Return the path to be saved in DB
}
}
}
return null; // No upload or failed upload
}
// Handle POST requests for CRUD operations
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Check edit permissions for the submitted tab_id for all actions
$submitted_tab_id = $_POST['tab_id'] ?? $_GET['tab_id'] ?? null;
if (isset($_POST['action']) && !canEditTab($submitted_tab_id)) {
$_SESSION['flash_message'] = ['text' => 'You do not have permission to perform this action.', 'type' => 'danger'];
header('Location: bookmarks.php?tab_id=' . $submitted_tab_id);
exit;
}
$action = $_POST['action'] ?? '';
// --- Category Actions ---
if ($action === 'add_category') {
$category_name = trim($_POST['category_name'] ?? '');
$tab_id = filter_input(INPUT_POST, 'tab_id', FILTER_VALIDATE_INT);
if (!empty($category_name) && $tab_id) {
$sort_stmt = $pdo->prepare("SELECT MAX(sort_order) as max_sort FROM categories WHERE tab_id = ?");
$sort_stmt->execute([$tab_id]);
$max_sort = $sort_stmt->fetchColumn() ?: 0;
$stmt = $pdo->prepare("INSERT INTO categories (name, sort_order, tab_id) VALUES (?, ?, ?)");
if ($stmt->execute([$category_name, $max_sort + 1, $tab_id])) {
$_SESSION['flash_message'] = ['text' => 'Category added successfully.', 'type' => 'success'];
} else {
$_SESSION['flash_message'] = ['text' => 'Error adding category.', 'type' => 'danger'];
}
} else {
$_SESSION['flash_message'] = ['text' => 'Category name and tab ID are required.', 'type' => 'warning'];
}
} elseif ($action === 'delete_category') {
$category_id = filter_input(INPUT_POST, 'category_id', FILTER_VALIDATE_INT);
if ($category_id) {
$stmt = $pdo->prepare("DELETE FROM categories WHERE id = ?");
if ($stmt->execute([$category_id])) {
$_SESSION['flash_message'] = ['text' => 'Category and its bookmarks have been deleted.', 'type' => 'success'];
} else {
$_SESSION['flash_message'] = ['text' => 'Error deleting category.', 'type' => 'danger'];
}
}
} elseif ($action === 'edit_category') {
$category_id = filter_input(INPUT_POST, 'category_id', FILTER_VALIDATE_INT);
$category_name = trim($_POST['category_name'] ?? '');
if ($category_id && !empty($category_name)) {
$stmt = $pdo->prepare("UPDATE categories SET name = ? WHERE id = ?");
if ($stmt->execute([$category_name, $category_id])) {
$_SESSION['flash_message'] = ['text' => 'Category renamed successfully.', 'type' => 'success'];
} else {
$_SESSION['flash_message'] = ['text' => 'Error renaming category.', 'type' => 'danger'];
}
} else {
$_SESSION['flash_message'] = ['text' => 'Invalid data for renaming category.', 'type' => 'warning'];
}
}
// --- Bookmark Actions ---
elseif ($action === 'add_bookmark') {
$title = trim($_POST['title'] ?? '');
$url = trim($_POST['url'] ?? '');
if (!empty($url) && !preg_match('/^https?:\/\//i', $url)) {
$url = 'https://' . $url;
}
$category_id = filter_input(INPUT_POST, 'category_id', FILTER_VALIDATE_INT);
$icon_url = trim($_POST['icon_url'] ?? '');
$is_favorite = isset($_POST['is_favorite']) ? 1 : 0;
$icon = $icon_url; // Default to URL
$new_icon_path = handle_icon_upload();
if ($new_icon_path) {
$icon = $new_icon_path;
}
if ($title && $url && $category_id) {
$sort_stmt = $pdo->prepare("SELECT MAX(sort_order) as max_sort FROM bookmarks WHERE category_id = ?");
$sort_stmt->execute([$category_id]);
$max_sort = $sort_stmt->fetchColumn() ?: 0;
$stmt = $pdo->prepare(
"INSERT INTO bookmarks (category_id, title, url, icon, is_favorite, sort_order)
VALUES (?, ?, ?, ?, ?, ?)"
);
if ($stmt->execute([$category_id, $title, $url, $icon, $is_favorite, $max_sort + 1])) {
$bookmark_id = $pdo->lastInsertId(); // Get the ID of the new bookmark
// Handle icon upload after getting the ID
$new_icon_path = handle_icon_upload($bookmark_id, $title);
if ($new_icon_path) {
// Update the bookmark with the new icon path
$update_stmt = $pdo->prepare("UPDATE bookmarks SET icon = ? WHERE id = ?");
$update_stmt->execute([$new_icon_path, $bookmark_id]);
}
$_SESSION['flash_message'] = ['text' => 'Bookmark added successfully.', 'type' => 'success'];
} else {
$_SESSION['flash_message'] = ['text' => 'Error adding bookmark.', 'type' => 'danger'];
}
} else {
$_SESSION['flash_message'] = ['text' => 'Title, URL, and category are required.', 'type' => 'warning'];
}
} elseif ($action === 'delete_bookmark') {
$bookmark_id = filter_input(INPUT_POST, 'bookmark_id', FILTER_VALIDATE_INT);
if ($bookmark_id) {
$stmt = $pdo->prepare("DELETE FROM bookmarks WHERE id = ?");
if ($stmt->execute([$bookmark_id])) {
$_SESSION['flash_message'] = ['text' => 'Bookmark deleted.', 'type' => 'success'];
} else {
$_SESSION['flash_message'] = ['text' => 'Error deleting bookmark.', 'type' => 'danger'];
}
}
}
elseif ($action === 'edit_bookmark') {
$bookmark_id = filter_input(INPUT_POST, 'bookmark_id', FILTER_VALIDATE_INT);
$title = trim($_POST['title'] ?? '');
$url = trim($_POST['url'] ?? '');
if (!empty($url) && !preg_match('/^https?:\/\//i', $url)) {
$url = 'https://' . $url;
}
$category_id = filter_input(INPUT_POST, 'category_id', FILTER_VALIDATE_INT);
$icon_url = trim($_POST['icon_url'] ?? '');
$is_favorite = isset($_POST['is_favorite']) ? 1 : 0;
$remove_icon = ($_POST['remove_icon'] ?? '0') === '1';
if ($bookmark_id && $title && $url && $category_id) {
// Fetch current icon to manage file deletion
$stmt = $pdo->prepare("SELECT icon FROM bookmarks WHERE id = ?");
$stmt->execute([$bookmark_id]);
$current_icon = $stmt->fetchColumn();
$icon = $current_icon; // Keep old icon by default
$new_icon_path = handle_icon_upload($bookmark_id, $title);
if ($new_icon_path) {
// 1. New upload takes highest precedence
$icon = $new_icon_path;
} else if ($remove_icon) {
// 2. Remove icon takes next precedence
if ($current_icon && file_exists($current_icon) && strpos($current_icon, 'data/images/custom/') === 0) {
unlink($current_icon);
}
// After removing, use whatever is in the URL field (might be empty)
$icon = $icon_url;
} else {
// 3. No upload, no removal. Handle URL input field.
// If the current icon is NOT a custom file, we can just save the icon_url.
if (strpos($current_icon ?? '', 'data/images/custom/') !== 0) {
$icon = $icon_url;
}
// If it IS a custom file, we should only change it if the user provided a new icon_url.
else if (!empty($icon_url)) {
// User is switching from custom to URL. Delete the old file.
if (file_exists($current_icon)) {
unlink($current_icon);
}
$icon = $icon_url;
}
// Implicit else: current icon is custom, icon_url is empty. Do nothing to keep the custom icon.
}
$stmt = $pdo->prepare(
"UPDATE bookmarks SET title = ?, url = ?, category_id = ?, icon = ?, is_favorite = ? WHERE id = ?"
);
if ($stmt->execute([$title, $url, $category_id, $icon, $is_favorite, $bookmark_id])) {
$_SESSION['flash_message'] = ['text' => 'Bookmark updated successfully.', 'type' => 'success'];
} else {
$_SESSION['flash_message'] = ['text' => 'Error updating bookmark.', 'type' => 'danger'];
}
} else {
$_SESSION['flash_message'] = ['text' => 'Invalid data for updating bookmark.', 'type' => 'warning'];
}
}
// Redirect to the same page to prevent form resubmission, preserving the tab
$tab_id = $_POST['tab_id'] ?? $_GET['tab_id'] ?? 1;
header('Location: bookmarks.php?tab_id=' . $tab_id);
exit;
}
// Fetch visible tabs for the user
$current_user_id = $_SESSION['user_id'] ?? null;
$current_user_role = $_SESSION['role'] ?? null;
$tabs_stmt_sql = "SELECT DISTINCT t.* FROM tabs t ";
$params = [];
if ($current_user_id) {
if ($current_user_role === 'admin') {
// Admin sees all tabs that are not explicitly hidden for them
$tabs_stmt_sql .= "
LEFT JOIN user_tab_visibility utv ON t.id = utv.tab_id AND utv.user_id = :current_user_id
WHERE utv.user_id IS NULL
";
} else { // 'user' and 'viewer' roles
// Users/Viewers see public tabs, their own tabs, or tabs they have access to,
// as long as they are not explicitly hidden.
$tabs_stmt_sql .= "
LEFT JOIN tab_viewer_access tva ON t.id = tva.tab_id
LEFT JOIN user_tab_visibility utv ON t.id = utv.tab_id AND utv.user_id = :current_user_id
WHERE utv.user_id IS NULL
AND (t.user_id IS NULL OR t.user_id = :current_user_id OR tva.user_id = :current_user_id)
";
}
$params[':current_user_id'] = $current_user_id;
} else {
// Guest sees only public tabs
$tabs_stmt_sql .= "WHERE t.user_id IS NULL";
}
$tabs_stmt_sql .= " ORDER BY t.id";
$tabs_stmt = $pdo->prepare($tabs_stmt_sql);
$tabs_stmt->execute($params);
$tabs = $tabs_stmt->fetchAll();
// Fetch all categories and their bookmarks for display for the current tab
$current_tab_id = $_GET['tab_id'] ?? ($tabs[0]['id'] ?? 1);
// Check if the current user can edit the currently viewed tab
$can_edit = canEditTab($current_tab_id);
$stmt = $pdo->prepare("
SELECT
c.id as category_id,
c.name as category_name,
c.sort_order as category_sort_order,
b.id as bookmark_id,
b.title as bookmark_title,
b.url as bookmark_url,
b.icon as bookmark_icon,
b.is_favorite as bookmark_is_favorite,
b.sort_order as bookmark_sort_order
FROM categories c
LEFT JOIN bookmarks b ON c.id = b.category_id
WHERE c.tab_id = :tab_id
ORDER BY c.sort_order, c.name, b.sort_order, b.title
");
$stmt->execute(['tab_id' => $current_tab_id]);
$results = $stmt->fetchAll();
$categories = [];
foreach ($results as $row) {
if (!isset($categories[$row['category_id']])) {
$categories[$row['category_id']] = [
'id' => $row['category_id'],
'name' => $row['category_name'],
'bookmarks' => []
];
}
if ($row['bookmark_id']) {
$categories[$row['category_id']]['bookmarks'][] = [
'id' => $row['bookmark_id'],
'title' => $row['bookmark_title'],
'url' => $row['bookmark_url'],
'icon' => $row['bookmark_icon'],
'is_favorite' => $row['bookmark_is_favorite']
];
}
}
require_once 'include/header.php';
?>
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h1><?php echo translate('bookmarks_manage_title'); ?></h1>
<div>
<?php if (isAdmin()): ?>
<a href="tabs_settings.php" class="btn btn-outline-secondary">
<i class="bi bi-folder-symlink"></i> Manage Tabs
</a>
<?php endif; ?>
<?php if ($can_edit): ?>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addBookmarkModal">
<i class="bi bi-plus-lg"></i> <?php echo translate('bookmarks_add_bookmark_button'); ?>
</button>
<?php endif; ?>
</div>
</div>
<!-- Tab Navigation -->
<?php if (count($tabs) > 1): ?>
<ul class="nav nav-tabs mb-3">
<?php foreach ($tabs as $tab): ?>
<li class="nav-item">
<a class="nav-link <?php if ($tab['id'] == $current_tab_id) echo 'active'; ?>" href="?tab_id=<?php echo $tab['id']; ?>">
<?php echo htmlspecialchars($tab['name'] === 'Default' ? translate('tab_default_name') : $tab['name']); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<?php if ($message): ?>
<div class="alert alert-<?php echo $message_type; ?> alert-dismissible fade show" role="alert">
<?php echo htmlspecialchars($message); ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<div class="row">
<!-- Categories Column -->
<div class="col-md-5">
<h3><?php echo translate('bookmarks_categories'); ?></h3>
<div class="card">
<div class="card-body">
<!-- Add Category Form -->
<?php if ($can_edit): ?>
<form action="bookmarks.php" method="post" class="mb-3">
<input type="hidden" name="action" value="add_category">
<input type="hidden" name="tab_id" value="<?php echo $current_tab_id; ?>">
<div class="input-group">
<input type="text" name="category_name" class="form-control" placeholder="<?php echo translate('bookmarks_new_category_placeholder'); ?>" required>
<button class="btn btn-primary" type="submit"><i class="bi bi-plus-lg"></i> <?php echo translate('bookmarks_add_category_button'); ?></button>
</div>
</form>
<?php endif; ?>
<!-- Category List -->
<ul class="list-group" id="category-list">
<?php foreach ($categories as $category): ?>
<li class="list-group-item d-flex justify-content-between align-items-center" data-id="<?php echo $category['id']; ?>">
<div>
<i class="bi bi-grip-vertical sort-handle" style="cursor: move;"></i> <!-- Handle for sorting -->
<span class="ms-2"><?php echo htmlspecialchars($category['name']); ?></span>
</div>
<div>
<span class="badge bg-secondary rounded-pill me-2"><?php echo count($category['bookmarks']); ?></span>
<?php if ($can_edit): ?>
<button class="btn btn-sm btn-outline-secondary" title="Edit Category"
data-bs-toggle="modal"
data-bs-target="#editCategoryModal"
data-bs-id="<?php echo $category['id']; ?>"
data-bs-name="<?php echo htmlspecialchars($category['name']); ?>">
<i class="bi bi-pencil"></i>
</button>
<form action="bookmarks.php" method="post" class="d-inline" onsubmit="return confirm('<?php echo translate('bookmarks_delete_category_confirm'); ?>');">
<input type="hidden" name="action" value="delete_category">
<input type="hidden" name="category_id" value="<?php echo $category['id']; ?>">
<input type="hidden" name="tab_id" value="<?php echo $current_tab_id; ?>">
<button type="submit" class="btn btn-sm btn-outline-danger" title="Delete Category"><i class="bi bi-trash"></i></button>
</form>
<?php endif; ?>
</div>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>
<!-- Bookmarks Column -->
<div class="col-md-7">
<div class="d-flex justify-content-between align-items-center mb-3">
<h3><?php echo translate('bookmarks_bookmarks'); ?></h3>
</div>
<?php if (empty($categories)): ?>
<div class="card">
<div class="card-body text-center">
<p class="text-muted"><?php echo translate('bookmarks_no_category_text'); ?></p>
</div>
</div>
<?php endif; ?>
<?php foreach ($categories as $category): ?>
<div class="card mb-3">
<div class="card-header">
<?php echo htmlspecialchars($category['name']); ?>
</div>
<div class="card-body">
<?php if (empty($category['bookmarks'])): ?>
<p class="text-muted"><?php echo translate('bookmarks_category_empty'); ?></p>
<?php else: ?>
<ul class="list-group list-group-flush bookmark-list" data-category-id="<?php echo $category['id']; ?>">
<?php foreach ($category['bookmarks'] as $bookmark): ?>
<?php
$icon_src = 'include/images/default-icon.png'; // Default icon
if (!empty($bookmark['icon'])) {
// Check if it's a custom uploaded icon
if (file_exists($bookmark['icon']) && strpos($bookmark['icon'], 'data/images/custom/') === 0) {
$icon_src = htmlspecialchars($bookmark['icon']); // Add timestamp to prevent caching
}
// Check if the icon stored is a full URL
elseif (filter_var($bookmark['icon'], FILTER_VALIDATE_URL)) {
$icon_src = htmlspecialchars($bookmark['icon']);
} elseif (!empty($settings['favicon_extractor_url'])) {
// It's a domain, build the URL from the base
$base_url = rtrim($settings['favicon_extractor_url'], '/');
$domain = htmlspecialchars($bookmark['icon']);
$icon_src = "{$base_url}/favicon/{$domain}?larger=true";
}
}
?>
<li class="list-group-item d-flex justify-content-between align-items-center" data-id="<?php echo $bookmark['id']; ?>">
<span>
<i class="bi bi-grip-vertical sort-handle" style="cursor: move;"></i>
<img src="<?php echo $icon_src; ?>" class="ms-2 me-2" style="width: 16px; height: 16px;" onerror="this.onerror=null;this.src='include/images/default-icon.png';">
<a href="<?php echo htmlspecialchars($bookmark['url']); ?>" <?php if($settings['open_new_tab'] ?? '1' === '1') echo 'target="_blank"'; ?>><?php echo htmlspecialchars($bookmark['title']); ?></a>
<?php if ($bookmark['is_favorite']): ?>
<i class="bi bi-star-fill text-warning" title="Favorite"></i>
<?php endif; ?>
</span>
<div>
<?php if ($can_edit): ?>
<button class="btn btn-sm btn-outline-secondary"
title="Edit Bookmark"
data-bs-toggle="modal"
data-bs-target="#editBookmarkModal"
data-bs-id="<?php echo $bookmark['id']; ?>"
data-bs-title="<?php echo htmlspecialchars($bookmark['title']); ?>"
data-bs-url="<?php echo htmlspecialchars($bookmark['url']); ?>"
data-bs-category="<?php echo $category['id']; ?>"
data-bs-icon="<?php echo htmlspecialchars($bookmark['icon']); ?>"
data-bs-icon-src="<?php echo $icon_src; ?>"
data-bs-favorite="<?php echo $bookmark['is_favorite']; ?>">
<i class="bi bi-pencil"></i>
</button>
<form action="bookmarks.php" method="post" class="d-inline" onsubmit="return confirm('<?php echo translate('bookmarks_delete_bookmark_confirm'); ?>');">
<input type="hidden" name="action" value="delete_bookmark">
<input type="hidden" name="bookmark_id" value="<?php echo $bookmark['id']; ?>">
<input type="hidden" name="tab_id" value="<?php echo $current_tab_id; ?>">
<button type="submit" class="btn btn-sm btn-outline-danger" title="Delete Bookmark"><i class="bi bi-trash"></i></button>
</form>
<?php endif; ?>
</div>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
<!-- Add Bookmark Modal -->
<div class="modal fade" id="addBookmarkModal" tabindex="-1" aria-labelledby="addBookmarkModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addBookmarkModalLabel"><?php echo translate('modal_add_bookmark_title'); ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="bookmarks.php" method="POST" enctype="multipart/form-data">
<div class="modal-body">
<input type="hidden" name="action" value="add_bookmark">
<input type="hidden" name="tab_id" value="<?php echo $current_tab_id; ?>">
<div class="mb-3">
<label for="bookmark-title" class="form-label"><?php echo translate('modal_title'); ?></label>
<input type="text" class="form-control" id="bookmark-title" name="title" required>
</div>
<div class="mb-3">
<label for="bookmark-url" class="form-label"><?php echo translate('modal_url'); ?></label>
<input type="text" class="form-control" id="bookmark-url" name="url" required>
</div>
<div class="mb-3">
<label for="bookmark-category" class="form-label"><?php echo translate('modal_category'); ?></label>
<select class="form-select" id="bookmark-category" name="category_id">
<option value="" selected><?php echo translate('modal_select_category'); ?></option>
<?php foreach ($categories as $cat): ?>
<option value="<?php echo htmlspecialchars($cat['id']); ?>"><?php echo htmlspecialchars($cat['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label for="bookmark-icon-url" class="form-label"><?php echo translate('modal_icon_url'); ?></label>
<div class="input-group">
<input type="text" class="form-control" id="bookmark-icon-url" name="icon_url">
<button class="btn btn-outline-secondary" type="button" id="fetch-favicon-add" title="<?php echo translate('modal_fetch_favicon_button'); ?>">
<i class="bi bi-arrow-clockwise"></i>
</button>
</div>
<div class="form-text"><?php echo translate('modal_icon_url_help'); ?></div>
</div>
<div class="mb-3">
<label for="bookmark-icon-upload" class="form-label"><?php echo translate('modal_icon_upload'); ?></label>
<input class="form-control" type="file" id="bookmark-icon-upload" name="icon_upload" accept="image/*">
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="1" id="bookmark-favorite" name="is_favorite">
<label class="form-check-label" for="bookmark-favorite">
<?php echo translate('modal_mark_as_favorite'); ?>
</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo translate('modal_close_button'); ?></button>
<button type="submit" class="btn btn-primary"><?php echo translate('modal_save_bookmark_button'); ?></button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit Bookmark Modal -->
<div class="modal fade" id="editBookmarkModal" tabindex="-1" aria-labelledby="editBookmarkModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editBookmarkModalLabel"><?php echo translate('modal_edit_bookmark_title'); ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="bookmarks.php" method="POST" enctype="multipart/form-data">
<div class="modal-body">
<input type="hidden" name="action" value="edit_bookmark">
<input type="hidden" name="bookmark_id" id="edit-bookmark-id">
<input type="hidden" name="tab_id" value="<?php echo $current_tab_id; ?>">
<div class="mb-3">
<label for="edit-bookmark-title" class="form-label"><?php echo translate('modal_title'); ?></label>
<input type="text" class="form-control" id="edit-bookmark-title" name="title" required>
</div>
<div class="mb-3">
<label for="edit-bookmark-url" class="form-label"><?php echo translate('modal_url'); ?></label>
<input type="text" class="form-control" id="edit-bookmark-url" name="url" required>
</div>
<div class="mb-3">
<label for="edit-bookmark-category" class="form-label"><?php echo translate('modal_category'); ?></label>
<select class="form-select" id="edit-bookmark-category" name="category_id" required>
<?php foreach ($categories as $category): ?>
<option value="<?php echo $category['id']; ?>"><?php echo htmlspecialchars($category['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label for="edit-bookmark-icon-url" class="form-label"><?php echo translate('modal_icon_url'); ?></label>
<div class="input-group">
<input type="text" class="form-control" id="edit-bookmark-icon-url" name="icon_url">
<button class="btn btn-outline-secondary" type="button" id="fetch-favicon-edit" title="<?php echo translate('modal_fetch_favicon_button'); ?>">
<i class="bi bi-arrow-clockwise"></i>
</button>
</div>
<div class="form-text"><?php echo translate('modal_icon_url_help'); ?></div>
</div>
<div class="mb-3">
<label for="edit-bookmark-icon-upload" class="form-label"><?php echo translate('modal_icon_upload'); ?></label>
<input class="form-control" type="file" id="edit-bookmark-icon-upload" name="icon_upload" accept="image/*">
</div>
<div class="mb-3" id="current-icon-container">
<label class="form-label"><?php echo translate('modal_current_icon'); ?></label>
<div>
<img id="current-icon-preview" src="" alt="Current Icon" style="max-width: 32px; max-height: 32px; margin-right: 10px;">
<button type="button" id="remove-custom-icon" class="btn btn-sm btn-danger"><?php echo translate('modal_remove_icon_button'); ?></button>
<input type="hidden" name="remove_icon" id="remove-icon-input" value="0">
</div>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="1" id="edit-bookmark-favorite" name="is_favorite">
<label class="form-check-label" for="edit-bookmark-favorite">
<?php echo translate('modal_mark_as_favorite'); ?>
</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo translate('modal_close_button'); ?></button>
<button type="submit" class="btn btn-primary"><?php echo translate('modal_save_changes_button'); ?></button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit Category Modal -->
<div class="modal fade" id="editCategoryModal" tabindex="-1" aria-labelledby="editCategoryModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editCategoryModalLabel"><?php echo translate('modal_edit_category_title'); ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="bookmarks.php" method="POST">
<div class="modal-body">
<input type="hidden" name="action" value="edit_category">
<input type="hidden" name="category_id" id="edit-category-id">
<input type="hidden" name="tab_id" value="<?php echo $current_tab_id; ?>">
<div class="mb-3">
<label for="edit-category-name" class="form-label"><?php echo translate('modal_category_name'); ?></label>
<input type="text" class="form-control" id="edit-category-name" name="category_name" required>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo translate('modal_close_button'); ?></button>
<button type="submit" class="btn btn-primary"><?php echo translate('modal_save_changes_button'); ?></button>
</div>
</form>
</div>
</div>
</div>
<?php require_once 'include/footer.php'; ?>