summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/Http/RequestHandlers/BroadcastAction.php31
-rw-r--r--app/Http/RequestHandlers/BroadcastPage.php25
-rw-r--r--app/Http/RequestHandlers/ControlPanel.php11
-rw-r--r--app/Http/Routes/WebRoutes.php4
-rw-r--r--app/Services/MessageService.php30
-rw-r--r--resources/views/admin/broadcast.phtml22
-rw-r--r--resources/views/admin/control-panel.phtml19
-rw-r--r--tests/app/Http/RequestHandlers/ControlPanelControllerTest.php5
8 files changed, 67 insertions, 80 deletions
diff --git a/app/Http/RequestHandlers/BroadcastAction.php b/app/Http/RequestHandlers/BroadcastAction.php
index 8a5c09ed6c..fcbda6983c 100644
--- a/app/Http/RequestHandlers/BroadcastAction.php
+++ b/app/Http/RequestHandlers/BroadcastAction.php
@@ -58,14 +58,13 @@ class BroadcastAction implements RequestHandlerInterface
*/
public function handle(ServerRequestInterface $request): ResponseInterface
{
- $user = Validator::attributes($request)->user();
- $params = (array) $request->getParsedBody();
- $body = $params['body'];
- $subject = $params['subject'];
- $to = $params['to'];
+ $recipients = $this->message_service->recipientTypes();
- $ip = Validator::attributes($request)->string('client-ip');
- $to_users = $this->message_service->recipientUsers($to);
+ $user = Validator::attributes($request)->user();
+ $to = Validator::attributes($request)->isInArrayKeys($recipients)->string('to');
+ $ip = Validator::attributes($request)->string('client-ip');
+ $body = Validator::parsedBody($request)->isNotEmpty()->string('body');
+ $subject = Validator::parsedBody($request)->isNotEmpty()->string('subject');
if ($body === '' || $subject === '') {
return redirect(route(BroadcastPage::class, [
@@ -75,20 +74,20 @@ class BroadcastAction implements RequestHandlerInterface
]));
}
- $errors = false;
-
- foreach ($to_users as $to_user) {
+ foreach ($this->message_service->recipientUsers($to) as $to_user) {
if ($this->message_service->deliverMessage($user, $to_user, $subject, $body, '', $ip)) {
- FlashMessages::addMessage(I18N::translate('The message was successfully sent to %s.', e($to_user->realName())), 'success');
+ FlashMessages::addMessage(
+ I18N::translate('The message was successfully sent to %s.', e($to_user->realName())),
+ 'success'
+ );
} else {
- $errors = true;
+ FlashMessages::addMessage(
+ I18N::translate('The message was not sent to %s.', e($to_user->realName())),
+ 'danger'
+ );
}
}
- if ($errors) {
- FlashMessages::addMessage(I18N::translate('The message was not sent.'), 'danger');
- }
-
return redirect(route(ControlPanel::class));
}
}
diff --git a/app/Http/RequestHandlers/BroadcastPage.php b/app/Http/RequestHandlers/BroadcastPage.php
index 9de46dae2c..87f499f1d4 100644
--- a/app/Http/RequestHandlers/BroadcastPage.php
+++ b/app/Http/RequestHandlers/BroadcastPage.php
@@ -19,7 +19,6 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Http\RequestHandlers;
-use Fisharebest\Webtrees\Contracts\UserInterface;
use Fisharebest\Webtrees\Http\ViewResponseTrait;
use Fisharebest\Webtrees\Services\MessageService;
use Fisharebest\Webtrees\Validator;
@@ -53,28 +52,20 @@ class BroadcastPage implements RequestHandlerInterface
*/
public function handle(ServerRequestInterface $request): ResponseInterface
{
- $user = Validator::attributes($request)->user();
- $params = $request->getQueryParams();
- $body = $params['body'] ?? '';
- $subject = $params['subject'] ?? '';
- $to = $params['to'];
+ $recipient_types = $this->message_service->recipientTypes();
- $to_names = $this->message_service->recipientUsers($to)
- ->map(static function (UserInterface $user): string {
- return $user->realName();
- });
+ $user = Validator::attributes($request)->user();
+ $to = Validator::attributes($request)->isInArrayKeys($recipient_types)->string('to');
- $title = $this->message_service->recipientDescription($to);
+ $title = $recipient_types[$to];
$this->layout = 'layouts/administration';
return $this->viewResponse('admin/broadcast', [
- 'body' => $body,
- 'from' => $user,
- 'subject' => $subject,
- 'title' => $title,
- 'to' => $to,
- 'to_names' => $to_names,
+ 'from' => $user,
+ 'title' => $title,
+ 'to' => $to,
+ 'recipients' => $this->message_service->recipientUsers($to),
]);
}
}
diff --git a/app/Http/RequestHandlers/ControlPanel.php b/app/Http/RequestHandlers/ControlPanel.php
index 8c0db3ee7c..e1a7e234e5 100644
--- a/app/Http/RequestHandlers/ControlPanel.php
+++ b/app/Http/RequestHandlers/ControlPanel.php
@@ -53,6 +53,7 @@ use Fisharebest\Webtrees\Registry;
use Fisharebest\Webtrees\Repository;
use Fisharebest\Webtrees\Services\AdminService;
use Fisharebest\Webtrees\Services\HousekeepingService;
+use Fisharebest\Webtrees\Services\MessageService;
use Fisharebest\Webtrees\Services\ModuleService;
use Fisharebest\Webtrees\Services\ServerCheckService;
use Fisharebest\Webtrees\Services\TreeService;
@@ -79,10 +80,12 @@ class ControlPanel implements RequestHandlerInterface
private AdminService $admin_service;
- private ModuleService $module_service;
-
private HousekeepingService $housekeeping_service;
+ private MessageService $message_service;
+
+ private ModuleService $module_service;
+
private ServerCheckService $server_check_service;
private TreeService $tree_service;
@@ -96,6 +99,7 @@ class ControlPanel implements RequestHandlerInterface
*
* @param AdminService $admin_service
* @param HousekeepingService $housekeeping_service
+ * @param MessageService $message_service
* @param ModuleService $module_service
* @param ServerCheckService $server_check_service
* @param TreeService $tree_service
@@ -105,6 +109,7 @@ class ControlPanel implements RequestHandlerInterface
public function __construct(
AdminService $admin_service,
HousekeepingService $housekeeping_service,
+ MessageService $message_service,
ModuleService $module_service,
ServerCheckService $server_check_service,
TreeService $tree_service,
@@ -113,6 +118,7 @@ class ControlPanel implements RequestHandlerInterface
) {
$this->admin_service = $admin_service;
$this->housekeeping_service = $housekeeping_service;
+ $this->message_service = $message_service;
$this->module_service = $module_service;
$this->server_check_service = $server_check_service;
$this->tree_service = $tree_service;
@@ -152,6 +158,7 @@ class ControlPanel implements RequestHandlerInterface
'moderators' => $this->user_service->moderators(),
'unapproved' => $this->user_service->unapproved(),
'unverified' => $this->user_service->unverified(),
+ 'recipients' => $this->message_service->recipientTypes(),
'all_trees' => $this->tree_service->all(),
'changes' => $this->totalChanges(),
'individuals' => $this->totalIndividuals(),
diff --git a/app/Http/Routes/WebRoutes.php b/app/Http/Routes/WebRoutes.php
index 3e3033ff55..f160252a78 100644
--- a/app/Http/Routes/WebRoutes.php
+++ b/app/Http/Routes/WebRoutes.php
@@ -348,8 +348,8 @@ class WebRoutes
]);
$router->get(ControlPanel::class, '');
- $router->get(BroadcastPage::class, '/broadcast');
- $router->post(BroadcastAction::class, '/broadcast');
+ $router->get(BroadcastPage::class, '/broadcast/{to}');
+ $router->post(BroadcastAction::class, '/broadcast/{to}');
$router->get(CleanDataFolder::class, '/clean');
$router->post(DeletePath::class, '/delete-path');
$router->get(EmailPreferencesPage::class, '/email');
diff --git a/app/Services/MessageService.php b/app/Services/MessageService.php
index f3788f1c7d..4e543e66b1 100644
--- a/app/Services/MessageService.php
+++ b/app/Services/MessageService.php
@@ -38,6 +38,10 @@ use function view;
*/
class MessageService
{
+ private const BROADCAST_ALL = 'all';
+ private const BROADCAST_NEVER = 'never';
+ private const BROADCAST_GONE = 'gone';
+
private EmailService $email_service;
private UserService $user_service;
@@ -178,13 +182,13 @@ class MessageService
{
switch ($to) {
default:
- case 'all':
+ case self::BROADCAST_ALL:
return $this->user_service->all();
- case 'never_logged':
+ case self::BROADCAST_NEVER:
return $this->user_service->all()->filter(static function (UserInterface $user): bool {
return $user->getPreference(UserInterface::PREF_IS_ACCOUNT_APPROVED) === '1' && $user->getPreference(UserInterface::PREF_TIMESTAMP_REGISTERED) > $user->getPreference(UserInterface::PREF_TIMESTAMP_ACTIVE);
});
- case 'last_6mo':
+ case self::BROADCAST_GONE:
$six_months_ago = Registry::timestampFactory()->now()->subtractMonths(6)->timestamp();
return $this->user_service->all()->filter(static function (UserInterface $user) use ($six_months_ago): bool {
@@ -196,21 +200,17 @@ class MessageService
}
/**
- * @param string $to
+ * Recipients for broadcast messages
*
- * @return string
+ * @return array<string,string>
*/
- public function recipientDescription(string $to): string
+ public function recipientTypes(): array
{
- switch ($to) {
- default:
- case 'all':
- return I18N::translate('Send a message to all users');
- case 'never_logged':
- return I18N::translate('Send a message to users who have never signed in');
- case 'last_6mo':
- return I18N::translate('Send a message to users who have not signed in for 6 months');
- }
+ return [
+ self::BROADCAST_ALL => I18N::translate('Send a message to all users'),
+ self::BROADCAST_NEVER => I18N::translate('Send a message to users who have never signed in'),
+ self::BROADCAST_GONE => I18N::translate('Send a message to users who have not signed in for 6 months'),
+ ];
}
/**
diff --git a/resources/views/admin/broadcast.phtml b/resources/views/admin/broadcast.phtml
index 44e25076af..e204e62feb 100644
--- a/resources/views/admin/broadcast.phtml
+++ b/resources/views/admin/broadcast.phtml
@@ -3,17 +3,14 @@
use Fisharebest\Webtrees\Contracts\UserInterface;
use Fisharebest\Webtrees\Http\RequestHandlers\BroadcastAction;
use Fisharebest\Webtrees\Http\RequestHandlers\ControlPanel;
-use Fisharebest\Webtrees\Http\RequestHandlers\HomePage;
use Fisharebest\Webtrees\I18N;
use Illuminate\Support\Collection;
/**
- * @var string $body
- * @var UserInterface $from
- * @var string $subject
- * @var string $title
- * @var string $to
- * @var Collection<int,string> $to_names
+ * @var UserInterface $from
+ * @var string $title
+ * @var string $to
+ * @var Collection<int,UserInterface> $recipients
*/
?>
@@ -22,7 +19,7 @@ use Illuminate\Support\Collection;
<h1><?= $title ?></h1>
-<form method="post" action="<?= e(route(BroadcastAction::class)) ?>">
+<form method="post" action="<?= e(route(BroadcastAction::class, ['to' => $to])) ?>">
<?= csrf_field() ?>
<div class="row form-group mb-3">
@@ -39,8 +36,7 @@ use Illuminate\Support\Collection;
<?= I18N::translateContext('Email recipient', 'To') ?>
</label>
<div class="col-sm-9">
- <input type="hidden" name="to" value="<?= e($to) ?>">
- <input class="form-control" id="to" type="text" value="<?= e($to_names->implode(', ')) ?>" disabled>
+ <input class="form-control" id="to" type="text" value="<?= $recipients->map(static fn (UserInterface $user): string => e($user->realName()))->implode(', ') ?>" disabled>
</div>
</div>
@@ -49,7 +45,7 @@ use Illuminate\Support\Collection;
<?= I18N::translate('Subject') ?>
</label>
<div class="col-sm-9">
- <input class="form-control" id="subject" type="text" name="subject" value="<?= e($subject) ?>" required="required">
+ <input class="form-control" id="subject" type="text" name="subject" required="required">
</div>
</div>
@@ -58,7 +54,7 @@ use Illuminate\Support\Collection;
<?= I18N::translate('Message') ?>
</label>
<div class="col-sm-9">
- <textarea class="form-control" id="body" name="body" rows="5" dir="auto" required="required"><?= e($body) ?></textarea>
+ <textarea class="form-control" id="body" name="body" rows="5" dir="auto" required="required"></textarea>
</div>
</div>
@@ -68,7 +64,7 @@ use Illuminate\Support\Collection;
<button type="submit" class="btn btn-primary">
<?= I18N::translate('Send') ?>
</button>
- <a class="btn btn-link" href="<?= e(route(HomePage::class)) ?>">
+ <a class="btn btn-link" href="<?= e(route(ControlPanel::class)) ?>">
<?= I18N::translate('cancel') ?>
</a>
</div>
diff --git a/resources/views/admin/control-panel.phtml b/resources/views/admin/control-panel.phtml
index 0e40e4e45b..36cd60f1d2 100644
--- a/resources/views/admin/control-panel.phtml
+++ b/resources/views/admin/control-panel.phtml
@@ -128,6 +128,7 @@ use Illuminate\Support\Collection;
* @var Collection<array-key,int> $notes
* @var NoteListModule|null $note_list_module
* @var Collection<int,ModuleInterface> $other_modules
+ * @var array<string,string> $recipients
* @var Collection<int,ModuleReportInterface> $report_modules_disabled
* @var Collection<int,ModuleReportInterface> $report_modules_enabled
* @var Collection<array-key,int> $repositories
@@ -534,24 +535,14 @@ use Illuminate\Support\Collection;
</div>
<div class="col-sm-6">
<ul class="fa-ul mx-0">
+ <?php foreach ($recipients as $to => $recipient) : ?>
<li>
<span class="fa-li"><?= view('icons/email') ?></span>
- <a href="<?= e(route(BroadcastPage::class, ['to' => 'all'])) ?>">
- <?= I18N::translate('Send a message to all users') ?>
- </a>
- </li>
- <li>
- <span class="fa-li"><?= view('icons/email') ?></span>
- <a href="<?= e(route(BroadcastPage::class, ['to' => 'never_logged'])) ?>">
- <?= I18N::translate('Send a message to users who have never signed in') ?>
- </a>
- </li>
- <li>
- <span class="fa-li"><?= view('icons/email') ?></span>
- <a href="<?= e(route(BroadcastPage::class, ['to' => 'last_6mo'])) ?>">
- <?= I18N::translate('Send a message to users who have not signed in for 6 months') ?>
+ <a href="<?= e(route(BroadcastPage::class, ['to' => $to])) ?>">
+ <?= $recipient ?>
</a>
</li>
+ <?php endforeach ?>
</ul>
</div>
</div>
diff --git a/tests/app/Http/RequestHandlers/ControlPanelControllerTest.php b/tests/app/Http/RequestHandlers/ControlPanelControllerTest.php
index b4ef19fd97..29bbc233a6 100644
--- a/tests/app/Http/RequestHandlers/ControlPanelControllerTest.php
+++ b/tests/app/Http/RequestHandlers/ControlPanelControllerTest.php
@@ -21,8 +21,10 @@ namespace Fisharebest\Webtrees\Http\RequestHandlers;
use Fig\Http\Message\StatusCodeInterface;
use Fisharebest\Webtrees\Services\AdminService;
+use Fisharebest\Webtrees\Services\EmailService;
use Fisharebest\Webtrees\Services\GedcomImportService;
use Fisharebest\Webtrees\Services\HousekeepingService;
+use Fisharebest\Webtrees\Services\MessageService;
use Fisharebest\Webtrees\Services\ModuleService;
use Fisharebest\Webtrees\Services\ServerCheckService;
use Fisharebest\Webtrees\Services\TimeoutService;
@@ -46,6 +48,7 @@ class ControlPanelControllerTest extends TestCase
public function testControlPanel(): void
{
$admin_service = new AdminService();
+ $message_service = new MessageService(new EmailService(), new UserService());
$module_service = new ModuleService();
$housekeeping_service = new HousekeepingService();
$server_check_service = new ServerCheckService();
@@ -54,7 +57,7 @@ class ControlPanelControllerTest extends TestCase
$tree_service = new TreeService($gedcom_import_service);
$upgrade_service = new UpgradeService($timeout_service);
$user_service = new UserService();
- $handler = new ControlPanel($admin_service, $housekeeping_service, $module_service, $server_check_service, $tree_service, $upgrade_service, $user_service);
+ $handler = new ControlPanel($admin_service, $housekeeping_service, $message_service, $module_service, $server_check_service, $tree_service, $upgrade_service, $user_service);
$request = self::createRequest();
$response = $handler->handle($request);