WebOrbiton
v1.0.0.1

StocketBase

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