Apple icon
This commit is contained in:
1 parent
5274da2c70
commit
91e73b1f1d
2 files changed
+131
-4
No files matched your search
@@ -57,6 +57,11 @@ if ($theme === 'dark' || in_array('dark-background-active', $body_classes)) {
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<title><?php echo htmlspecialchars($settings['site_title'] ?? 'Bookmarkly'); ?></title>
|
||||
<link rel="icon" href="<?php echo htmlspecialchars($settings['site_favicon'] ?? $settings['site_logo'] ?? 'include/images/favicon.ico'); ?>">
|
||||
|
||||
<!-- Apple Touch Icons -->
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="<?php echo htmlspecialchars($settings['site_favicon'] ?? $settings['site_logo'] ?? 'include/images/favicon.ico'); ?>">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="<?php echo htmlspecialchars($settings['site_favicon'] ?? $settings['site_logo'] ?? 'include/images/favicon.ico'); ?>">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="<?php echo htmlspecialchars($settings['site_favicon'] ?? $settings['site_logo'] ?? 'include/images/favicon.ico'); ?>">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet">
|
||||
<link href="include/css/style.css" rel="stylesheet">
|
||||
|
||||
+126
-4
@@ -6,6 +6,86 @@ $GLOBALS['body_class'] = 'settings-page';
|
||||
|
||||
require_once 'include/auth.php';
|
||||
|
||||
/**
|
||||
* Resize an image while maintaining aspect ratio and transparency
|
||||
* @param string $source_path Path to source image
|
||||
* @param string $destination_path Path to save resized image
|
||||
* @param int $max_width Maximum width
|
||||
* @param int $max_height Maximum height
|
||||
* @param string $extension File extension
|
||||
* @return bool Success status
|
||||
*/
|
||||
function resizeImage($source_path, $destination_path, $max_width, $max_height, $extension) {
|
||||
// Get original image dimensions
|
||||
$image_info = getimagesize($source_path);
|
||||
if ($image_info === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$original_width = $image_info[0];
|
||||
$original_height = $image_info[1];
|
||||
|
||||
// Calculate new dimensions maintaining aspect ratio
|
||||
$ratio = min($max_width / $original_width, $max_height / $original_height);
|
||||
$new_width = round($original_width * $ratio);
|
||||
$new_height = round($original_height * $ratio);
|
||||
|
||||
// Create image resource based on file type
|
||||
switch (strtolower($extension)) {
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
$source_image = imagecreatefromjpeg($source_path);
|
||||
break;
|
||||
case 'png':
|
||||
$source_image = imagecreatefrompng($source_path);
|
||||
break;
|
||||
case 'gif':
|
||||
$source_image = imagecreatefromgif($source_path);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($source_image === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create new image with transparency support
|
||||
$new_image = imagecreatetruecolor($new_width, $new_height);
|
||||
|
||||
// Preserve transparency for PNG and GIF
|
||||
if ($extension === 'png' || $extension === 'gif') {
|
||||
imagealphablending($new_image, false);
|
||||
imagesavealpha($new_image, true);
|
||||
$transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127);
|
||||
imagefilledrectangle($new_image, 0, 0, $new_width, $new_height, $transparent);
|
||||
}
|
||||
|
||||
// Resize the image
|
||||
imagecopyresampled($new_image, $source_image, 0, 0, 0, 0, $new_width, $new_height, $original_width, $original_height);
|
||||
|
||||
// Save the resized image
|
||||
$result = false;
|
||||
switch (strtolower($extension)) {
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
$result = imagejpeg($new_image, $destination_path, 90);
|
||||
break;
|
||||
case 'png':
|
||||
$result = imagepng($new_image, $destination_path, 9);
|
||||
break;
|
||||
case 'gif':
|
||||
$result = imagegif($new_image, $destination_path);
|
||||
break;
|
||||
}
|
||||
|
||||
// Clean up memory
|
||||
imagedestroy($source_image);
|
||||
imagedestroy($new_image);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Flash messages for feedback
|
||||
$message = '';
|
||||
$message_type = '';
|
||||
@@ -68,10 +148,44 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (in_array($favicon_ext, $allowed_favicon_ext)) {
|
||||
$favicon_filename = 'favicon.' . $favicon_ext;
|
||||
$favicon_path = $uploadDir . $favicon_filename;
|
||||
if (move_uploaded_file($_FILES['site_favicon']['tmp_name'], $favicon_path)) {
|
||||
$upsert_stmt->execute(['site_favicon', $favicon_path . '?v=' . time()]);
|
||||
|
||||
// Check if it's an image file (not SVG or ICO)
|
||||
if (in_array($favicon_ext, ['png', 'jpg', 'jpeg', 'gif'])) {
|
||||
// Get image dimensions
|
||||
$image_info = getimagesize($_FILES['site_favicon']['tmp_name']);
|
||||
if ($image_info === false) {
|
||||
$_SESSION['flash_message'] = ['text' => 'Invalid image file for favicon.', 'type' => 'danger'];
|
||||
} else {
|
||||
$width = $image_info[0];
|
||||
$height = $image_info[1];
|
||||
|
||||
// Validate dimensions (minimum 180x180, maximum 256x256)
|
||||
if ($width < 180 || $height < 180) {
|
||||
$_SESSION['flash_message'] = ['text' => 'Favicon must be at least 180x180 pixels for Apple Touch Icon compatibility.', 'type' => 'danger'];
|
||||
} elseif ($width > 256 || $height > 256) {
|
||||
// Resize if too large
|
||||
if (resizeImage($_FILES['site_favicon']['tmp_name'], $favicon_path, 256, 256, $favicon_ext)) {
|
||||
$upsert_stmt->execute(['site_favicon', $favicon_path . '?v=' . time()]);
|
||||
$_SESSION['flash_message'] = ['text' => 'Favicon uploaded and resized to 256x256 pixels for optimal Apple Touch Icon compatibility.', 'type' => 'success'];
|
||||
} else {
|
||||
$_SESSION['flash_message'] = ['text' => 'Failed to resize favicon.', 'type' => 'danger'];
|
||||
}
|
||||
} else {
|
||||
// Size is acceptable, just move the file
|
||||
if (move_uploaded_file($_FILES['site_favicon']['tmp_name'], $favicon_path)) {
|
||||
$upsert_stmt->execute(['site_favicon', $favicon_path . '?v=' . time()]);
|
||||
} else {
|
||||
$_SESSION['flash_message'] = ['text' => 'Failed to move uploaded favicon.', 'type' => 'danger'];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$_SESSION['flash_message'] = ['text' => 'Failed to move uploaded favicon.', 'type' => 'danger'];
|
||||
// For SVG and ICO files, just move them without resizing
|
||||
if (move_uploaded_file($_FILES['site_favicon']['tmp_name'], $favicon_path)) {
|
||||
$upsert_stmt->execute(['site_favicon', $favicon_path . '?v=' . time()]);
|
||||
} else {
|
||||
$_SESSION['flash_message'] = ['text' => 'Failed to move uploaded favicon.', 'type' => 'danger'];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$_SESSION['flash_message'] = ['text' => 'Invalid file type for favicon.', 'type' => 'danger'];
|
||||
@@ -277,7 +391,15 @@ require_once 'include/header.php';
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="site_favicon" class="form-label">Site Favicon</label>
|
||||
<input type="file" class="form-control" id="site_favicon" name="site_favicon">
|
||||
<input type="file" class="form-control" id="site_favicon" name="site_favicon" accept="image/png,image/jpeg,image/gif,image/svg+xml,image/x-icon">
|
||||
<div class="form-text">
|
||||
<strong>Apple Touch Icon Requirements:</strong><br>
|
||||
• Minimum size: 180x180 pixels<br>
|
||||
• Maximum size: 256x256 pixels<br>
|
||||
• Supported formats: PNG, JPG, GIF, SVG, ICO<br>
|
||||
• Images larger than 256x256 will be automatically resized<br>
|
||||
• Images smaller than 180x180 will be rejected
|
||||
</div>
|
||||
<?php if (!empty($settings['site_favicon'])): ?>
|
||||
<small class="form-text text-muted d-block mt-2">Current favicon: <img src="<?php echo htmlspecialchars($settings['site_favicon']); ?>" alt="Current Favicon" style="max-height: 16px; vertical-align: middle;"></small>
|
||||
<?php endif; ?>
|
||||
|
||||
Reference in new issue
Block a user