Add notification filters
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Concerns;
|
||||
|
||||
use App\Actions\Notifications\NormalizeNotificationFilters;
|
||||
use App\Enums\NotificationFilterAttribute;
|
||||
use App\Enums\NotificationFilterOperator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
trait InteractsWithNotificationFilters
|
||||
{
|
||||
protected function prepareNotificationFiltersForValidation(): void
|
||||
{
|
||||
$rawFilters = $this->input('filters');
|
||||
|
||||
if (! is_string($rawFilters)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$decodedFilters = json_decode($rawFilters, true);
|
||||
|
||||
if (json_last_error() === JSON_ERROR_NONE) {
|
||||
$this->merge([
|
||||
'filters' => $decodedFilters,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function notificationFilterRules(): array
|
||||
{
|
||||
return [
|
||||
'filters' => ['nullable', 'array', 'max:25'],
|
||||
'filters.*' => ['required', 'array'],
|
||||
'filters.*.attribute' => ['required', 'string', Rule::in(NotificationFilterAttribute::values())],
|
||||
'filters.*.operator' => ['required', 'string', Rule::in(NotificationFilterOperator::values())],
|
||||
'filters.*.value' => ['nullable'],
|
||||
];
|
||||
}
|
||||
|
||||
protected function withNotificationFilterValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(function (Validator $validator): void {
|
||||
$filters = $this->input('filters');
|
||||
|
||||
if (! is_array($filters)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$normalizer = app(NormalizeNotificationFilters::class);
|
||||
|
||||
foreach ($filters as $index => $filter) {
|
||||
if (! is_array($filter)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$operator = NotificationFilterOperator::tryFrom((string) ($filter['operator'] ?? null));
|
||||
|
||||
if ($operator === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$normalizedValue = $normalizer->handle([$filter])[0]['value'] ?? null;
|
||||
|
||||
if (in_array($operator, [NotificationFilterOperator::Equals, NotificationFilterOperator::NotEquals], true)
|
||||
&& ! is_string($normalizedValue)
|
||||
) {
|
||||
$validator->errors()->add(
|
||||
"filters.{$index}.value",
|
||||
'A non-empty value is required for equals and not equals operators.',
|
||||
);
|
||||
}
|
||||
|
||||
if ($operator === NotificationFilterOperator::In
|
||||
&& (! is_array($normalizedValue) || $normalizedValue === [])
|
||||
) {
|
||||
$validator->errors()->add(
|
||||
"filters.{$index}.value",
|
||||
'The in operator requires at least one value.',
|
||||
);
|
||||
}
|
||||
|
||||
if (in_array($operator, [NotificationFilterOperator::Exists, NotificationFilterOperator::NotExists], true)
|
||||
&& $this->hasProvidedFilterValue($filter['value'] ?? null)
|
||||
) {
|
||||
$validator->errors()->add(
|
||||
"filters.{$index}.value",
|
||||
'The exists and not exists operators do not accept a value.',
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private function hasProvidedFilterValue(mixed $value): bool
|
||||
{
|
||||
if ($value === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_string($value)) {
|
||||
return trim($value) !== '';
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $candidate) {
|
||||
if (is_string($candidate) && trim($candidate) !== '') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! is_string($candidate) && $candidate !== null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,16 @@ namespace App\Http\Requests;
|
||||
|
||||
use App\Enums\NotificationChannel;
|
||||
use App\Enums\NotificationEventType;
|
||||
use App\Http\Requests\Concerns\InteractsWithNotificationFilters;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
class StoreProjectNotificationActionRequest extends FormRequest
|
||||
{
|
||||
use InteractsWithNotificationFilters;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
@@ -32,9 +36,20 @@ class StoreProjectNotificationActionRequest extends FormRequest
|
||||
'enabled' => ['required', 'boolean'],
|
||||
'delivery_url' => ['required', 'string', 'max:2048', 'url'],
|
||||
'message_template' => $this->messageTemplateRules(),
|
||||
...$this->notificationFilterRules(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->prepareNotificationFiltersForValidation();
|
||||
}
|
||||
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$this->withNotificationFilterValidator($validator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
|
||||
@@ -4,12 +4,16 @@ namespace App\Http\Requests;
|
||||
|
||||
use App\Enums\NotificationChannel;
|
||||
use App\Enums\NotificationEventType;
|
||||
use App\Http\Requests\Concerns\InteractsWithNotificationFilters;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
class UpdateProjectNotificationActionRequest extends FormRequest
|
||||
{
|
||||
use InteractsWithNotificationFilters;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
@@ -32,9 +36,20 @@ class UpdateProjectNotificationActionRequest extends FormRequest
|
||||
'enabled' => ['required', 'boolean'],
|
||||
'delivery_url' => ['nullable', 'string', 'max:2048', 'url'],
|
||||
'message_template' => $this->messageTemplateRules(),
|
||||
...$this->notificationFilterRules(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->prepareNotificationFiltersForValidation();
|
||||
}
|
||||
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$this->withNotificationFilterValidator($validator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user