CustomFilterController.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Models\CustomFilter;
  4. use App\Models\CustomFilterKeyword;
  5. use Illuminate\Http\Request;
  6. use Illuminate\Support\Facades\DB;
  7. class CustomFilterController extends Controller
  8. {
  9. public function __construct()
  10. {
  11. $this->middleware('auth');
  12. }
  13. public function index(Request $request)
  14. {
  15. $filters = CustomFilter::where('profile_id', $request->user()->profile_id)
  16. ->unexpired()
  17. ->with(['keywords', 'statuses'])
  18. ->get();
  19. return response()->json([
  20. 'filters' => $filters,
  21. ]);
  22. }
  23. public function show(CustomFilter $filter)
  24. {
  25. $this->authorize('view', $filter);
  26. $filter->load(['keywords', 'statuses']);
  27. return response()->json([
  28. 'filter' => $filter,
  29. ]);
  30. }
  31. public function store(Request $request)
  32. {
  33. $validatedData = $request->validate([
  34. 'title' => 'required|string',
  35. 'context' => 'required|array',
  36. 'context.*' => 'string|in:'.implode(',', CustomFilter::VALID_CONTEXTS),
  37. 'filter_action' => 'integer|in:0,1,2',
  38. 'expires_in' => 'nullable|integer|min:0',
  39. 'irreversible' => 'boolean',
  40. 'keywords' => 'array',
  41. 'keywords.*.keyword' => 'required|string',
  42. 'keywords.*.whole_word' => 'boolean',
  43. 'status_ids' => 'array',
  44. 'status_ids.*' => 'integer|exists:statuses,id',
  45. ]);
  46. DB::beginTransaction();
  47. try {
  48. $expiresAt = null;
  49. if (isset($validatedData['expires_in']) && $validatedData['expires_in'] > 0) {
  50. $expiresAt = now()->addSeconds($validatedData['expires_in']);
  51. }
  52. $filter = CustomFilter::create([
  53. 'phrase' => $validatedData['title'],
  54. 'context' => $validatedData['context'],
  55. 'action' => $validatedData['filter_action'] ??
  56. (isset($validatedData['irreversible']) && $validatedData['irreversible'] ?
  57. CustomFilter::ACTION_HIDE : CustomFilter::ACTION_WARN),
  58. 'expires_at' => $expiresAt,
  59. 'profile_id' => $request->user()->profile_id,
  60. ]);
  61. if (isset($validatedData['keywords'])) {
  62. foreach ($validatedData['keywords'] as $keywordData) {
  63. $filter->keywords()->create([
  64. 'keyword' => $keywordData['keyword'],
  65. 'whole_word' => $keywordData['whole_word'] ?? true,
  66. ]);
  67. }
  68. }
  69. if (isset($validatedData['status_ids'])) {
  70. foreach ($validatedData['status_ids'] as $statusId) {
  71. $filter->statuses()->create([
  72. 'status_id' => $statusId,
  73. ]);
  74. }
  75. }
  76. DB::commit();
  77. $filter->load(['keywords', 'statuses']);
  78. return response()->json([
  79. 'filter' => $filter,
  80. ], 201);
  81. } catch (\Exception $e) {
  82. DB::rollBack();
  83. return response()->json([
  84. 'error' => 'Failed to create filter',
  85. 'message' => $e->getMessage(),
  86. ], 500);
  87. }
  88. }
  89. public function update(Request $request, CustomFilter $filter)
  90. {
  91. $this->authorize('update', $filter);
  92. $validatedData = $request->validate([
  93. 'title' => 'string',
  94. 'context' => 'array',
  95. 'context.*' => 'string|in:'.implode(',', CustomFilter::VALID_CONTEXTS),
  96. 'filter_action' => 'integer|in:0,1,2',
  97. 'expires_in' => 'nullable|integer|min:0',
  98. 'irreversible' => 'boolean',
  99. 'keywords' => 'array',
  100. 'keywords.*.id' => 'nullable|exists:custom_filter_keywords,id',
  101. 'keywords.*.keyword' => 'required|string',
  102. 'keywords.*.whole_word' => 'boolean',
  103. 'keywords.*._destroy' => 'boolean',
  104. 'status_ids' => 'array',
  105. 'status_ids.*' => 'integer|exists:statuses,id',
  106. ]);
  107. DB::beginTransaction();
  108. try {
  109. if (isset($validatedData['expires_in'])) {
  110. if ($validatedData['expires_in'] > 0) {
  111. $filter->expires_at = now()->addSeconds($validatedData['expires_in']);
  112. } else {
  113. $filter->expires_at = null;
  114. }
  115. }
  116. if (isset($validatedData['title'])) {
  117. $filter->phrase = $validatedData['title'];
  118. }
  119. if (isset($validatedData['context'])) {
  120. $filter->context = $validatedData['context'];
  121. }
  122. if (isset($validatedData['filter_action'])) {
  123. $filter->action = $validatedData['filter_action'];
  124. } elseif (isset($validatedData['irreversible'])) {
  125. $filter->irreversible = $validatedData['irreversible'];
  126. }
  127. $filter->save();
  128. if (isset($validatedData['keywords'])) {
  129. $existingKeywordIds = $filter->keywords->pluck('id')->toArray();
  130. $processedIds = [];
  131. foreach ($validatedData['keywords'] as $keywordData) {
  132. if (isset($keywordData['id']) && isset($keywordData['_destroy']) && $keywordData['_destroy']) {
  133. CustomFilterKeyword::destroy($keywordData['id']);
  134. continue;
  135. }
  136. if (isset($keywordData['id']) && in_array($keywordData['id'], $existingKeywordIds)) {
  137. $keyword = CustomFilterKeyword::find($keywordData['id']);
  138. $keyword->update([
  139. 'keyword' => $keywordData['keyword'],
  140. 'whole_word' => $keywordData['whole_word'] ?? $keyword->whole_word,
  141. ]);
  142. $processedIds[] = $keywordData['id'];
  143. } else {
  144. $newKeyword = $filter->keywords()->create([
  145. 'keyword' => $keywordData['keyword'],
  146. 'whole_word' => $keywordData['whole_word'] ?? true,
  147. ]);
  148. $processedIds[] = $newKeyword->id;
  149. }
  150. }
  151. $keywordsToDelete = array_diff($existingKeywordIds, $processedIds);
  152. if (! empty($keywordsToDelete)) {
  153. CustomFilterKeyword::destroy($keywordsToDelete);
  154. }
  155. }
  156. if (isset($validatedData['status_ids'])) {
  157. $filter->statuses()->delete();
  158. foreach ($validatedData['status_ids'] as $statusId) {
  159. $filter->statuses()->create([
  160. 'status_id' => $statusId,
  161. ]);
  162. }
  163. }
  164. DB::commit();
  165. $filter->load(['keywords', 'statuses']);
  166. return response()->json([
  167. 'filter' => $filter,
  168. ]);
  169. } catch (\Exception $e) {
  170. DB::rollBack();
  171. return response()->json([
  172. 'error' => 'Failed to update filter',
  173. 'message' => $e->getMessage(),
  174. ], 500);
  175. }
  176. }
  177. public function destroy(CustomFilter $filter)
  178. {
  179. $this->authorize('delete', $filter);
  180. $filter->delete();
  181. return response()->json(null, 204);
  182. }
  183. }