WebOrbiton
v2.0.0.0

Publisium

178 lines · 5.9 KB
  1. <?php
  2. declare(strict_types=1);
  3. require_once __DIR__ . '/../includes/icons.php';
  4. require_once __DIR__ . '/../includes/social-icons.php';
  5. if (!Auth::hasRoleAtLeast(Auth::ROLE_EDITOR_IN_CHIEF)) {
  6. return;
  7. }
  8. $db = Database::site();
  9. $action = $_POST['action'] ?? '';
  10. function nextNavSortOrder(PDO $db): int
  11. {
  12. $max = $db->query('SELECT COALESCE(MAX(sort_order), -1) AS m FROM nav_items')->fetch();
  13. return ((int) $max['m']) + 1;
  14. }
  15. function sanitizeNavIcon(string $iconKeyRaw, string $iconSvgRaw): array
  16. {
  17. $iconKeyRaw = trim($iconKeyRaw);
  18. if ($iconKeyRaw === '' || $iconKeyRaw === 'none') {
  19. return [null, null];
  20. }
  21. if ($iconKeyRaw === 'custom') {
  22. $svg = SocialIcons::sanitizeCustomSvg($iconSvgRaw);
  23. return $svg !== '' ? ['custom', $svg] : [null, null];
  24. }
  25. if (Icons::isNavIcon($iconKeyRaw)) {
  26. return [$iconKeyRaw, null];
  27. }
  28. return [null, null];
  29. }
  30. if ($action === 'add_nav_item') {
  31. $itemType = in_array($_POST['item_type'] ?? '', ['category', 'page', 'custom'], true) ? $_POST['item_type'] : 'category';
  32. $labelOverride = trim((string) ($_POST['label_override'] ?? ''));
  33. [$iconKey, $iconSvg] = sanitizeNavIcon((string) ($_POST['icon_key'] ?? ''), (string) ($_POST['icon_svg'] ?? ''));
  34. if ($itemType === 'category') {
  35. $refId = (int) ($_POST['category_ref_id'] ?? 0);
  36. if ($refId <= 0) {
  37. return;
  38. }
  39. $exists = $db->prepare('SELECT id FROM categories WHERE id = :id LIMIT 1');
  40. $exists->execute(['id' => $refId]);
  41. if (!$exists->fetch()) {
  42. return;
  43. }
  44. $statement = $db->prepare(
  45. 'INSERT INTO nav_items (item_type, ref_id, label, icon_key, icon_svg, sort_order) VALUES (:type, :ref_id, :label, :icon_key, :icon_svg, :sort_order)'
  46. );
  47. $statement->execute([
  48. 'type' => 'category',
  49. 'ref_id' => $refId,
  50. 'label' => $labelOverride !== '' ? $labelOverride : null,
  51. 'icon_key' => $iconKey,
  52. 'icon_svg' => $iconSvg,
  53. 'sort_order' => nextNavSortOrder($db),
  54. ]);
  55. }
  56. if ($itemType === 'page') {
  57. $refId = (int) ($_POST['page_ref_id'] ?? 0);
  58. if ($refId <= 0) {
  59. return;
  60. }
  61. $exists = $db->prepare('SELECT id FROM pages WHERE id = :id LIMIT 1');
  62. $exists->execute(['id' => $refId]);
  63. if (!$exists->fetch()) {
  64. return;
  65. }
  66. $statement = $db->prepare(
  67. 'INSERT INTO nav_items (item_type, ref_id, label, icon_key, icon_svg, sort_order) VALUES (:type, :ref_id, :label, :icon_key, :icon_svg, :sort_order)'
  68. );
  69. $statement->execute([
  70. 'type' => 'page',
  71. 'ref_id' => $refId,
  72. 'label' => $labelOverride !== '' ? $labelOverride : null,
  73. 'icon_key' => $iconKey,
  74. 'icon_svg' => $iconSvg,
  75. 'sort_order' => nextNavSortOrder($db),
  76. ]);
  77. }
  78. if ($itemType === 'custom') {
  79. $label = trim((string) ($_POST['custom_label'] ?? ''));
  80. $url = trim((string) ($_POST['custom_url'] ?? ''));
  81. $target = isset($_POST['custom_new_tab']) ? '_blank' : '_self';
  82. if ($label === '' || $url === '') {
  83. return;
  84. }
  85. $statement = $db->prepare(
  86. 'INSERT INTO nav_items (item_type, ref_id, label, url, target, icon_key, icon_svg, sort_order) VALUES (:type, NULL, :label, :url, :target, :icon_key, :icon_svg, :sort_order)'
  87. );
  88. $statement->execute([
  89. 'type' => 'custom',
  90. 'label' => $label,
  91. 'url' => $url,
  92. 'target' => $target,
  93. 'icon_key' => $iconKey,
  94. 'icon_svg' => $iconSvg,
  95. 'sort_order' => nextNavSortOrder($db),
  96. ]);
  97. }
  98. }
  99. if ($action === 'update_nav_item_icon') {
  100. $navItemId = (int) ($_POST['nav_item_id'] ?? 0);
  101. if ($navItemId <= 0) {
  102. return;
  103. }
  104. [$iconKey, $iconSvg] = sanitizeNavIcon((string) ($_POST['icon_key'] ?? ''), (string) ($_POST['icon_svg'] ?? ''));
  105. $statement = $db->prepare('UPDATE nav_items SET icon_key = :icon_key, icon_svg = :icon_svg WHERE id = :id');
  106. $statement->execute([
  107. 'icon_key' => $iconKey,
  108. 'icon_svg' => $iconSvg,
  109. 'id' => $navItemId,
  110. ]);
  111. }
  112. if ($action === 'move_nav_item') {
  113. $navItemId = (int) ($_POST['nav_item_id'] ?? 0);
  114. $direction = $_POST['direction'] ?? '';
  115. if ($navItemId <= 0 || !in_array($direction, ['up', 'down'], true)) {
  116. return;
  117. }
  118. $currentStatement = $db->prepare('SELECT id, sort_order FROM nav_items WHERE id = :id LIMIT 1');
  119. $currentStatement->execute(['id' => $navItemId]);
  120. $current = $currentStatement->fetch();
  121. if (!$current) {
  122. return;
  123. }
  124. if ($direction === 'up') {
  125. $neighborStatement = $db->prepare(
  126. 'SELECT id, sort_order FROM nav_items WHERE sort_order < :sort_order ORDER BY sort_order DESC LIMIT 1'
  127. );
  128. } else {
  129. $neighborStatement = $db->prepare(
  130. 'SELECT id, sort_order FROM nav_items WHERE sort_order > :sort_order ORDER BY sort_order ASC LIMIT 1'
  131. );
  132. }
  133. $neighborStatement->execute(['sort_order' => $current['sort_order']]);
  134. $neighbor = $neighborStatement->fetch();
  135. if (!$neighbor) {
  136. return;
  137. }
  138. $swap = $db->prepare('UPDATE nav_items SET sort_order = :sort_order WHERE id = :id');
  139. $swap->execute(['sort_order' => $neighbor['sort_order'], 'id' => $current['id']]);
  140. $swap->execute(['sort_order' => $current['sort_order'], 'id' => $neighbor['id']]);
  141. }
  142. if ($action === 'delete_nav_item') {
  143. $navItemId = (int) ($_POST['nav_item_id'] ?? 0);
  144. if ($navItemId > 0) {
  145. $statement = $db->prepare('DELETE FROM nav_items WHERE id = :id');
  146. $statement->execute(['id' => $navItemId]);
  147. }
  148. }
  149. ​