galleries.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. <?php
  2. /**
  3. * Gallery overview: create new galleries, list and delete existing ones.
  4. */
  5. require dirname(__DIR__) . '/app/bootstrap.php';
  6. auth_require();
  7. if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  8. csrf_verify();
  9. $action = $_POST['action'] ?? '';
  10. if ($action === 'create') {
  11. $title = trim((string)($_POST['title'] ?? ''));
  12. if ($title === '') {
  13. flash_set('Please enter a gallery title.', 'error');
  14. redirect('galleries.php');
  15. }
  16. $slug = slugify($title) . '-' . random_token(6);
  17. $password = (string)($_POST['password'] ?? '');
  18. $gallery = [
  19. 'slug' => $slug,
  20. 'title' => $title,
  21. 'created_at' => date('Y-m-d H:i:s'),
  22. 'password_hash' => $password !== '' ? password_hash($password, PASSWORD_DEFAULT) : null,
  23. 'expires_at' => trim((string)($_POST['expires_at'] ?? '')) ?: null,
  24. // Longest edge the browser downscales uploads to; null = original.
  25. 'max_resolution' => parse_max_resolution($_POST),
  26. 'images' => [],
  27. ];
  28. // A guest upload link is just a per-gallery secret in the URL; presence
  29. // of upload_key = guest uploads enabled (revocable from the edit page).
  30. if (!empty($_POST['allow_uploads'])) {
  31. $gallery['upload_key'] = random_token(24);
  32. }
  33. gallery_save($gallery);
  34. flash_set('Gallery created. Now add images.');
  35. redirect('gallery-edit.php?g=' . rawurlencode($slug));
  36. }
  37. if ($action === 'delete') {
  38. $gallery = gallery_load((string)($_POST['slug'] ?? ''));
  39. if ($gallery !== null) {
  40. s3_delete_gallery_objects($gallery);
  41. gallery_delete($gallery['slug']);
  42. flash_set('Gallery and its S3 images deleted.');
  43. }
  44. redirect('galleries.php');
  45. }
  46. }
  47. $galleries = galleries_all();
  48. admin_header('Galleries', 'galleries');
  49. flash_render();
  50. ?>
  51. <h1>Galleries</h1>
  52. <form method="post" class="card">
  53. <?= csrf_field() ?>
  54. <input type="hidden" name="action" value="create">
  55. <h2 style="margin-top:0">New gallery</h2>
  56. <label for="t">Title</label>
  57. <input type="text" id="t" name="title" placeholder="Wedding Miller — June 2026" required>
  58. <label for="p">Password <span style="text-transform:none;letter-spacing:0">(optional — leave blank for a public link)</span></label>
  59. <input type="text" id="p" name="password" autocomplete="off">
  60. <label for="ex">Expiry date <span style="text-transform:none;letter-spacing:0">(optional — gallery is hidden after this day)</span></label>
  61. <input type="date" id="ex" name="expires_at">
  62. <?php resolution_field() ?>
  63. <p class="help"><label style="display:inline;text-transform:none;letter-spacing:0">
  64. <input type="checkbox" name="allow_uploads" value="1"> Allow guest uploads via a shared link
  65. </label></p>
  66. <button type="submit">Create gallery</button>
  67. </form>
  68. <h2>Existing galleries (<?= count($galleries) ?>)</h2>
  69. <?php if (!$galleries): ?>
  70. <p class="help">No galleries yet.</p>
  71. <?php else: ?>
  72. <div class="card"><table>
  73. <tr><th>Title</th><th>Images</th><th>Protection</th><th>Expires</th><th>Created</th><th style="width:200px">Actions</th></tr>
  74. <?php foreach ($galleries as $g): $expired = gallery_is_expired($g); ?>
  75. <tr>
  76. <td><?= e($g['title']) ?></td>
  77. <td><?= count($g['images'] ?? []) ?></td>
  78. <td>
  79. <?= !empty($g['password_hash']) ? '<span class="tag tag-lock">password</span>' : '<span class="tag">open</span>' ?>
  80. <?= !empty($g['upload_key']) ? ' <span class="tag">uploads</span>' : '' ?>
  81. <?= isset($g['max_resolution']) ? ' <span class="tag">' . e(resolution_label((int)$g['max_resolution'])) . '</span>' : '' ?>
  82. </td>
  83. <td>
  84. <?= e($g['expires_at'] ?? '—') ?>
  85. <?= $expired ? ' <span class="tag tag-expired">expired</span>' : '' ?>
  86. </td>
  87. <td><?= e(substr($g['created_at'] ?? '', 0, 10)) ?></td>
  88. <td>
  89. <a href="gallery-edit.php?g=<?= e(rawurlencode($g['slug'])) ?>">Edit</a> ·
  90. <a href="../gallery.php?g=<?= e(rawurlencode($g['slug'])) ?>" target="_blank" rel="noopener">View ↗</a>
  91. <form method="post" style="display:inline"
  92. onsubmit="return confirm('Delete this gallery AND all its images on S3? This cannot be undone.')">
  93. <?= csrf_field() ?>
  94. <input type="hidden" name="action" value="delete">
  95. <input type="hidden" name="slug" value="<?= e($g['slug']) ?>">
  96. <button class="btn-danger" style="margin:0;padding:.25rem .7rem">Delete</button>
  97. </form>
  98. </td>
  99. </tr>
  100. <?php endforeach; ?>
  101. </table></div>
  102. <?php endif; ?>
  103. <?php admin_footer(); ?>