galleries.php 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. <?php
  2. /**
  3. * Gallery overview: create new galleries, list and delete existing ones.
  4. */
  5. require dirname(__DIR__, 2) . '/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. 'images' => [],
  25. ];
  26. gallery_save($gallery);
  27. flash_set('Gallery created. Now add images.');
  28. redirect('gallery-edit.php?g=' . rawurlencode($slug));
  29. }
  30. if ($action === 'delete') {
  31. $gallery = gallery_load((string)($_POST['slug'] ?? ''));
  32. if ($gallery !== null) {
  33. s3_delete_gallery_objects($gallery);
  34. gallery_delete($gallery['slug']);
  35. flash_set('Gallery and its S3 images deleted.');
  36. }
  37. redirect('galleries.php');
  38. }
  39. }
  40. $galleries = galleries_all();
  41. admin_header('Galleries', 'galleries');
  42. flash_render();
  43. ?>
  44. <h1>Galleries</h1>
  45. <form method="post" class="card">
  46. <?= csrf_field() ?>
  47. <input type="hidden" name="action" value="create">
  48. <h2 style="margin-top:0">New gallery</h2>
  49. <label for="t">Title</label>
  50. <input type="text" id="t" name="title" placeholder="Wedding Miller — June 2026" required>
  51. <label for="p">Password <span style="text-transform:none;letter-spacing:0">(optional — leave blank for a public link)</span></label>
  52. <input type="text" id="p" name="password" autocomplete="off">
  53. <label for="ex">Expiry date <span style="text-transform:none;letter-spacing:0">(optional — gallery is hidden after this day)</span></label>
  54. <input type="date" id="ex" name="expires_at">
  55. <button type="submit">Create gallery</button>
  56. </form>
  57. <h2>Existing galleries (<?= count($galleries) ?>)</h2>
  58. <?php if (!$galleries): ?>
  59. <p class="help">No galleries yet.</p>
  60. <?php else: ?>
  61. <div class="card"><table>
  62. <tr><th>Title</th><th>Images</th><th>Protection</th><th>Expires</th><th>Created</th><th style="width:200px">Actions</th></tr>
  63. <?php foreach ($galleries as $g): $expired = gallery_is_expired($g); ?>
  64. <tr>
  65. <td><?= e($g['title']) ?></td>
  66. <td><?= count($g['images'] ?? []) ?></td>
  67. <td><?= !empty($g['password_hash']) ? '<span class="tag tag-lock">password</span>' : '<span class="tag">open</span>' ?></td>
  68. <td>
  69. <?= e($g['expires_at'] ?? '—') ?>
  70. <?= $expired ? ' <span class="tag tag-expired">expired</span>' : '' ?>
  71. </td>
  72. <td><?= e(substr($g['created_at'] ?? '', 0, 10)) ?></td>
  73. <td>
  74. <a href="gallery-edit.php?g=<?= e(rawurlencode($g['slug'])) ?>">Edit</a> ·
  75. <a href="../gallery.php?g=<?= e(rawurlencode($g['slug'])) ?>" target="_blank" rel="noopener">View ↗</a>
  76. <form method="post" style="display:inline"
  77. onsubmit="return confirm('Delete this gallery AND all its images on S3? This cannot be undone.')">
  78. <?= csrf_field() ?>
  79. <input type="hidden" name="action" value="delete">
  80. <input type="hidden" name="slug" value="<?= e($g['slug']) ?>">
  81. <button class="btn-danger" style="margin:0;padding:.25rem .7rem">Delete</button>
  82. </form>
  83. </td>
  84. </tr>
  85. <?php endforeach; ?>
  86. </table></div>
  87. <?php endif; ?>
  88. <?php admin_footer(); ?>