|
| 1 | +<?php |
| 2 | + |
| 3 | +/** |
| 4 | + * SPDX-License-Identifier: MIT |
| 5 | + * Copyright (c) 2017-2018 Tobias Reich |
| 6 | + * Copyright (c) 2018-2026 LycheeOrg. |
| 7 | + */ |
| 8 | + |
| 9 | +namespace App\Http\Controllers\Contact; |
| 10 | + |
| 11 | +use App\Http\Requests\Contact\ContactMessagesListRequest; |
| 12 | +use App\Http\Requests\Contact\DeleteContactMessageRequest; |
| 13 | +use App\Http\Requests\Contact\StoreContactMessageRequest; |
| 14 | +use App\Http\Requests\Contact\UpdateContactMessageRequest; |
| 15 | +use App\Http\Resources\Collections\ContactMessageCollectionResource; |
| 16 | +use App\Http\Resources\GalleryConfigs\ContactConfig; |
| 17 | +use App\Http\Resources\Models\ContactMessageResource; |
| 18 | +use App\Models\ContactMessage; |
| 19 | +use Illuminate\Http\Response; |
| 20 | +use Illuminate\Routing\Controller; |
| 21 | + |
| 22 | +class ContactController extends Controller |
| 23 | +{ |
| 24 | + /** |
| 25 | + * Return the contact form configuration values. |
| 26 | + * |
| 27 | + * @return ContactConfig |
| 28 | + */ |
| 29 | + public function init(): ContactConfig |
| 30 | + { |
| 31 | + return new ContactConfig(); |
| 32 | + } |
| 33 | + |
| 34 | + /** |
| 35 | + * Store a new contact message from a public visitor. |
| 36 | + * |
| 37 | + * @param StoreContactMessageRequest $request |
| 38 | + * |
| 39 | + * @return array{success:bool,message:string} |
| 40 | + */ |
| 41 | + public function store(StoreContactMessageRequest $request): array |
| 42 | + { |
| 43 | + // Validate security answer if configured |
| 44 | + $security_question = $request->configs()->getValueAsString('contact_form_security_question'); |
| 45 | + $security_answer = $request->configs()->getValueAsString('contact_form_security_answer'); |
| 46 | + if ($security_question !== '' && $security_answer !== '') { |
| 47 | + if (strcasecmp(trim($request->securityAnswer()), trim($security_answer)) !== 0) { |
| 48 | + abort(422, 'Incorrect answer to the security question.'); |
| 49 | + } |
| 50 | + } |
| 51 | + |
| 52 | + // Validate consent if configured |
| 53 | + $is_consent_required = $request->configs()->getValueAsBool('contact_form_custom_consent_required'); |
| 54 | + if ($is_consent_required && !$request->consentAgreed()) { |
| 55 | + abort(422, 'You must agree to the privacy policy.'); |
| 56 | + } |
| 57 | + |
| 58 | + ContactMessage::create([ |
| 59 | + 'name' => $request->senderName(), |
| 60 | + 'email' => $request->senderEmail(), |
| 61 | + 'message' => $request->senderMessage(), |
| 62 | + 'ip_address' => $request->ip(), |
| 63 | + 'user_agent' => $request->userAgent(), |
| 64 | + ]); |
| 65 | + |
| 66 | + return ['success' => true, 'message' => 'Thank you for your message. We will get back to you soon.']; |
| 67 | + } |
| 68 | + |
| 69 | + /** |
| 70 | + * List all contact messages (admin only). |
| 71 | + * |
| 72 | + * @param ContactMessagesListRequest $request |
| 73 | + * |
| 74 | + * @return ContactMessageCollectionResource |
| 75 | + */ |
| 76 | + public function index(ContactMessagesListRequest $request): ContactMessageCollectionResource |
| 77 | + { |
| 78 | + $per_page = min((int) $request->query('per_page', 20), 100); |
| 79 | + $page = max((int) $request->query('page', 1), 1); |
| 80 | + $search = $request->query('search', ''); |
| 81 | + $is_read_filter = $request->query('is_read', null); |
| 82 | + |
| 83 | + $query = ContactMessage::query()->orderBy('created_at', 'desc'); |
| 84 | + |
| 85 | + if (is_string($search) && $search !== '') { |
| 86 | + $escaped = str_replace(['\\', '%', '_'], ['\\\\', '\\%', '\\_'], $search); |
| 87 | + $query->where(function ($q) use ($escaped): void { |
| 88 | + $q->where('name', 'like', '%' . $escaped . '%') |
| 89 | + ->orWhere('email', 'like', '%' . $escaped . '%') |
| 90 | + ->orWhere('message', 'like', '%' . $escaped . '%'); |
| 91 | + }); |
| 92 | + } |
| 93 | + |
| 94 | + if ($is_read_filter !== null) { |
| 95 | + $query->where('is_read', filter_var($is_read_filter, FILTER_VALIDATE_BOOLEAN)); |
| 96 | + } |
| 97 | + |
| 98 | + $total = $query->count(); |
| 99 | + $messages = $query->offset(($page - 1) * $per_page)->limit($per_page)->get(); |
| 100 | + |
| 101 | + return new ContactMessageCollectionResource( |
| 102 | + $messages->map(fn (ContactMessage $m) => new ContactMessageResource($m)), |
| 103 | + $total, |
| 104 | + $per_page, |
| 105 | + $page, |
| 106 | + ); |
| 107 | + } |
| 108 | + |
| 109 | + /** |
| 110 | + * Update a contact message (mark as read/unread). |
| 111 | + * |
| 112 | + * @param UpdateContactMessageRequest $request |
| 113 | + * |
| 114 | + * @return ContactMessageResource |
| 115 | + */ |
| 116 | + public function update(UpdateContactMessageRequest $request): ContactMessageResource |
| 117 | + { |
| 118 | + $message = $request->contactMessage(); |
| 119 | + $message->is_read = $request->isRead(); |
| 120 | + $message->save(); |
| 121 | + |
| 122 | + return new ContactMessageResource($message); |
| 123 | + } |
| 124 | + |
| 125 | + /** |
| 126 | + * Delete a contact message. |
| 127 | + * |
| 128 | + * @param DeleteContactMessageRequest $request |
| 129 | + * |
| 130 | + * @return Response |
| 131 | + */ |
| 132 | + public function destroy(DeleteContactMessageRequest $request): Response |
| 133 | + { |
| 134 | + $request->contactMessage()->delete(); |
| 135 | + |
| 136 | + return response()->noContent(); |
| 137 | + } |
| 138 | +} |
0 commit comments