Added the ability to send notifications by email when a new review is added.

This commit is contained in:
Leonid Nikitin 2024-07-27 00:29:28 +05:00
parent c84ed9f12b
commit 46da639055
Signed by: kor-elf
GPG Key ID: 3C0F720C170F6E1D
7 changed files with 112 additions and 5 deletions

View File

@ -1,4 +1,4 @@
APP_NAME=Laravel APP_NAME="My Projects Website"
APP_ENV=local APP_ENV=local
APP_KEY= APP_KEY=
APP_DEBUG=true APP_DEBUG=true
@ -11,6 +11,10 @@ CAPTCHA_PRIVATE_TOKEN=
CAPTCHA_STATIC_PATH=http://your-domain-captcha-or-IP:8081/captcha CAPTCHA_STATIC_PATH=http://your-domain-captcha-or-IP:8081/captcha
CAPTCHA_PUBLIC_TOKEN= CAPTCHA_PUBLIC_TOKEN=
# Don't forget to configure MAIL_MAILER to send mail.
FEEDBACK_MAIL_NOTIFICATIONS=false
FEEDBACK_MAIL_TO=
APP_FORCE_HTTPS=false APP_FORCE_HTTPS=false
APP_DEFAULT_LOCALE=ru APP_DEFAULT_LOCALE=ru
@ -59,7 +63,7 @@ REDIS_HOST=app-redis
REDIS_PASSWORD=null REDIS_PASSWORD=null
REDIS_PORT=6379 REDIS_PORT=6379
MAIL_MAILER=log MAIL_MAILER=smtp
MAIL_HOST=127.0.0.1 MAIL_HOST=127.0.0.1
MAIL_PORT=2525 MAIL_PORT=2525
MAIL_USERNAME=null MAIL_USERNAME=null

View File

@ -0,0 +1,60 @@
<?php declare(strict_types=1);
namespace App\Notifications;
use App\Enums\Site\ProjectSection;
use App\Models\ProjectFeedback;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
final class ReviewAdded extends Notification implements ShouldQueue
{
use Queueable;
/**
* Create a new notification instance.
*/
public function __construct(
private readonly ProjectFeedback $feedback
) { }
/**
* Get the notification's delivery channels.
*
* @return array<int, string>
*/
public function via(object $notifiable): array
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
$project = $this->feedback->project;
return (new MailMessage)
->subject(__('notification.Review Added: :name', ['name' => $project->name]))
->line(__('notification.Added a new review.'))
->action(__('notification.Project :name', ['name' => $project->name]), \url(ProjectSection::Home->url($project)))
->line( __('site.attributes.name') . ': ' . $this->feedback->name)
->line( __('site.attributes.email') . ': ' . $this->feedback->email)
->line(__('site.attributes.message') . ': ' . $this->feedback->message);
}
/**
* Get the array representation of the notification.
*
* @return array<string, mixed>
*/
public function toArray(object $notifiable): array
{
return [
//
];
}
}

View File

@ -3,8 +3,10 @@
namespace App\Providers; namespace App\Providers;
use App\Enums\Morph; use App\Enums\Morph;
use App\Services\ProjectFeedback\ProjectFeedbackCommandHandler;
use App\Services\Search\CreateSearchInstanceCommand; use App\Services\Search\CreateSearchInstanceCommand;
use App\Services\Search\Search; use App\Services\Search\Search;
use App\Services\Site\FeedbackService;
use App\Services\Storage\Image\ResizeCommandHandler; use App\Services\Storage\Image\ResizeCommandHandler;
use App\Services\Storage\ImageService; use App\Services\Storage\ImageService;
use App\Services\Storage\StorageCommandHandler; use App\Services\Storage\StorageCommandHandler;
@ -31,7 +33,15 @@ public function register(): void
}); });
$this->app->bind(StorageCommandHandler::class, function () { $this->app->bind(StorageCommandHandler::class, function () {
return new StorageCommandHandler(disc: (string) config('storage.disk')); return new StorageCommandHandler(disc: (string) \config('storage.disk'));
});
$this->app->bind(FeedbackService::class, function (Application $app) {
return new FeedbackService(
$app->make(ProjectFeedbackCommandHandler::class),
(bool) \config('feedback.mail_notifications', false),
\config('feedback.mail_to', null),
);
}); });
$this->app->bind(ImageService::class, function (Application $app) { $this->app->bind(ImageService::class, function (Application $app) {

View File

@ -5,32 +5,44 @@
use App\Dto\Service\Site\Feedback\Send; use App\Dto\Service\Site\Feedback\Send;
use App\Models\Project; use App\Models\Project;
use App\Models\User; use App\Models\User;
use App\Notifications\ReviewAdded;
use App\ServiceResults\ServiceResultError; use App\ServiceResults\ServiceResultError;
use App\ServiceResults\ServiceResultSuccess; use App\ServiceResults\ServiceResultSuccess;
use App\Services\ProjectFeedback\ProjectFeedbackCommandHandler; use App\Services\ProjectFeedback\ProjectFeedbackCommandHandler;
use App\Services\Service; use App\Services\Service;
use App\Services\WebsiteTranslations; use App\Services\WebsiteTranslations;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Notification;
final class FeedbackService extends Service final class FeedbackService extends Service
{ {
public function __construct( public function __construct(
private readonly ProjectFeedbackCommandHandler $feedbackCommandHandler, private readonly ProjectFeedbackCommandHandler $feedbackCommandHandler,
private readonly bool $isNotifications = false,
private readonly ?string $mailNotifications = null,
) { } ) { }
public function send(Send $send, Project $project, WebsiteTranslations $websiteTranslations, ?User $user = null): ServiceResultError | ServiceResultSuccess public function send(Send $send, Project $project, WebsiteTranslations $websiteTranslations, ?User $user = null): ServiceResultError | ServiceResultSuccess
{ {
try { try {
DB::transaction(function () use ($send, $project, $user) { $feedback = DB::transaction(function () use ($send, $project, $user) {
$data = $this->getDataFeedback($send); $data = $this->getDataFeedback($send);
$data['user_id'] = $user?->id; $data['user_id'] = $user?->id;
$this->feedbackCommandHandler->handleStore($project, $data); return $this->feedbackCommandHandler->handleStore($project, $data);
}); });
} catch (\Throwable $e) { } catch (\Throwable $e) {
report($e); report($e);
return $this->errService($websiteTranslations->translate('Server Error')); return $this->errService($websiteTranslations->translate('Server Error'));
} }
try {
if ($this->isNotifications) {
Notification::route('mail', $this->mailNotifications)->notify(new ReviewAdded($feedback));
}
} catch (\Throwable $e) {
report($e);
}
return $this->ok($websiteTranslations->translate('site.Message sent successfully')); return $this->ok($websiteTranslations->translate('site.Message sent successfully'));
} }

View File

@ -0,0 +1,9 @@
<?php
return [
/**
* Enable new review alerts.
*/
'mail_notifications' => (bool) env('FEEDBACK_MAIL_NOTIFICATIONS', false),
'mail_to' => env('FEEDBACK_MAIL_TO', null),
];

View File

@ -0,0 +1,6 @@
<?php
return [
'Added a new review.' => 'Added a new review.',
'Review Added: :name' => 'Review Added: :name',
'Project :name' => 'Project :name',
];

View File

@ -0,0 +1,6 @@
<?php
return [
'Added a new review.' => 'Добавили новый отзыв.',
'Review Added: :name' => 'Отзыв добавлен: :name',
'Project :name' => 'Проект :name',
];