WebOrbiton
v1.0.0.0

StocketBase

85 lines · 2.9 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. $db = Database::site();
  11. $canManageAny = Auth::hasRoleAtLeast(Auth::ROLE_STORE_OWNER);
  12. ​
  13. $loadTrashed = static function (int $id) use ($db): ?array {
  14. $statement = $db->prepare('SELECT * FROM products WHERE id = :id AND deleted_at IS NOT NULL LIMIT 1');
  15. $statement->execute(['id' => $id]);
  16. ​
  17. return $statement->fetch() ?: null;
  18. };
  19. ​
  20. $canTouch = static fn (array $product): bool => $canManageAny || (int) $product['created_by'] === (int) $currentUser['id'];
  21. ​
  22. require_once __DIR__ . '/../includes/digital-files.php';
  23. ​
  24. $deleteFiles = ($_POST['file_action'] ?? 'keep') === 'delete';
  25. ​
  26. $purge = static function (int $id, string $title) use ($db, $deleteFiles): void {
  27. if ($deleteFiles) {
  28. DigitalFiles::deleteForProduct($id);
  29. } else {
  30. DigitalFiles::detachForProduct($id, $title);
  31. }
  32. $db->prepare('DELETE FROM product_versions WHERE product_id = :id')->execute(['id' => $id]);
  33. $db->prepare('DELETE FROM product_tags WHERE product_id = :id')->execute(['id' => $id]);
  34. $db->prepare('DELETE FROM products WHERE id = :id')->execute(['id' => $id]);
  35. };
  36. ​
  37. $productId = (int) ($_POST['product_id'] ?? 0);
  38. ​
  39. if ($action === 'restore_product') {
  40. $product = $productId > 0 ? $loadTrashed($productId) : null;
  41. if ($product === null || !$canTouch($product)) {
  42. return 0;
  43. }
  44. ​
  45. $restoredStatus = in_array($product['trashed_status'], ['published', 'pending_review', 'rejected'], true) ? $product['trashed_status'] : 'draft';
  46. ​
  47. $db->prepare('UPDATE products SET status = :status, deleted_at = NULL, trashed_status = NULL WHERE id = :id')
  48. ->execute(['status' => $restoredStatus, 'id' => $productId]);
  49. ActivityLog::record('product.restore', 'product', $productId, (string) $product['title']);
  50. ​
  51. return $productId;
  52. }
  53. ​
  54. if ($action === 'purge_product') {
  55. $product = $productId > 0 ? $loadTrashed($productId) : null;
  56. if ($product === null || !$canTouch($product)) {
  57. return 0;
  58. }
  59. ​
  60. $purge($productId, (string) $product['title']);
  61. ActivityLog::record('product.purge', 'product', $productId, (string) $product['title'] . ($deleteFiles ? ' [files deleted]' : ' [files kept]'));
  62. ​
  63. return 0;
  64. }
  65. ​
  66. if ($action === 'empty_trash') {
  67. $statement = $canManageAny
  68. ? $db->query('SELECT id, title FROM products WHERE deleted_at IS NOT NULL')
  69. : $db->prepare('SELECT id, title FROM products WHERE deleted_at IS NOT NULL AND created_by = :author');
  70. ​
  71. if (!$canManageAny) {
  72. $statement->execute(['author' => $currentUser['id']]);
  73. }
  74. ​
  75. $trashedRows = $statement->fetchAll();
  76. foreach ($trashedRows as $trashedRow) {
  77. $purge((int) $trashedRow['id'], (string) $trashedRow['title']);
  78. }
  79. ActivityLog::record('product.empty_trash', 'product', null, count($trashedRows) . ' products' . ($deleteFiles ? ' [files deleted]' : ' [files kept]'));
  80. ​
  81. return 0;
  82. }
  83. ​
  84. return 0;
  85. ​