Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FZ-120 unique validation #183

Merged
merged 3 commits into from
Dec 10, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/Http/Controllers/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public function __construct(private readonly Request $request)

protected function validate(array $rules): array
{
Valid::reset();
return $this->request->validate($rules + ['dry_run' => Valid::bool(['declined'], sometimes: true)]);
}

Expand Down
16 changes: 13 additions & 3 deletions app/Models/Meeting.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use App\Models\Traits\HasValidator;
use App\Models\UuidEnum\DictionaryUuidEnum;
use App\Rules\MemberExistsRule;
use App\Rules\UniqueWithMemoryRule;
use App\Rules\Valid;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
Expand Down Expand Up @@ -69,10 +70,19 @@ protected static function fieldValidator(string $field): string|array
'staff.*', 'clients.*' => Valid::array(keys: ['user_id', 'attendance_status_dict_id']),
'staff.*.attendance_status_dict_id', 'clients.*.attendance_status_dict_id' =>
Valid::dict(DictionaryUuidEnum::AttendanceStatus, sometimes: true, nullable: true),
'staff.*.user_id' => Valid::uuid([new MemberExistsRule(AttendanceType::Staff)]),
'clients.*.user_id' => Valid::uuid([new MemberExistsRule(AttendanceType::Client)]),
'staff.*.user_id' => Valid::uuid([
new UniqueWithMemoryRule('attendant'),
new MemberExistsRule(AttendanceType::Staff),
]),
'clients.*.user_id' => Valid::uuid([
new UniqueWithMemoryRule('attendant'),
new MemberExistsRule(AttendanceType::Client),
]),
'resources.*' => Valid::array(keys: ['resource_dict_id']),
'resources.*.resource_dict_id' => MeetingResource::fieldValidator('resource_dict_id'),
'resources.*.resource_dict_id' =>Valid::dict(
DictionaryUuidEnum::MeetingResource,
[new UniqueWithMemoryRule('resource')],
),
};
}

Expand Down
13 changes: 0 additions & 13 deletions app/Models/MeetingResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@

use App\Models\QueryBuilders\MeetingResourceBuilder;
use App\Models\Traits\BaseModel;
use App\Models\Traits\HasValidator;
use App\Models\UuidEnum\DictionaryUuidEnum;
use App\Rules\Valid;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Validation\Rule;

/**
* @property string meeting_id
Expand All @@ -18,7 +14,6 @@
class MeetingResource extends Model
{
use BaseModel;
use HasValidator;

protected $table = 'meeting_resources';

Expand All @@ -28,12 +23,4 @@ class MeetingResource extends Model
];

protected $casts = self::BASE_CASTS;

public static function fieldValidator(string $field): string|array
{
return match ($field) {
'meeting_id' => Valid::uuid([Rule::exists('meetings')]),
'resource_dict_id' => Valid::dict(DictionaryUuidEnum::MeetingResource),
};
}
}
29 changes: 29 additions & 0 deletions app/Rules/UniqueWithMemoryRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace App\Rules;

use Closure;

final class UniqueWithMemoryRule extends AbstractRule
{
private static array $values = [];

public function __construct(
private readonly string $key,
) {
}

public static function reset(): void
{
self::$values = [];
}

public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (!array_key_exists($this->key, self::$values) || !in_array($value, self::$values[$this->key], true)) {
self::$values[$this->key][] = $value;
return;
}
$this->validator->addFailure($attribute, 'custom.unique_items');
}
}
9 changes: 8 additions & 1 deletion app/Rules/Valid.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
*/
class Valid extends AbstractDataRule
{
/** reset all rules having state */
public static function reset(): void
{
UniqueWithMemoryRule::reset();
}

public static function bool(array $rules = [], bool $sometimes = false, bool $nullable = false): array
{
return self::base($sometimes, $nullable, ['boolean', DataTypeRule::bool()], $rules);
Expand Down Expand Up @@ -60,12 +66,13 @@ public static function uuid(

public static function dict(
string|Dictionary|DictionaryUuidEnum $dictionary,
array $rules = [],
bool $sometimes = false,
bool $nullable = false,
): array {
$dictionaryId = ($dictionary instanceof DictionaryUuidEnum) ? $dictionary->value
: (($dictionary instanceof Dictionary) ? $dictionary->id : $dictionary);
return self::uuid([new PositionInDictionaryRule($dictionaryId)], $sometimes, $nullable);
return self::uuid([new PositionInDictionaryRule($dictionaryId), ...$rules], $sometimes, $nullable);
}

public static function array(
Expand Down
1 change: 1 addition & 0 deletions resources/lang/pl_PL/validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ uuid: "Pole „{{attribute}}” musi być poprawnym identyfikatorem UUID."
custom:
require_present: "Pole „{{attribute}}” wymaga pola „{{other}}”."
data_type: "Pole „{{attribute}}” musi być typu „{{type}}”."
unique_items: "Wartość „{{attribute}}” nie może się powtarzać."
trimmed: "Pole „{{attribute}}” nie może się zaczynać ani kończyć białymi znakami."
regexp_is_valid: "Pole „{{attribute}}” musi być poprawnym wyrażeniem regularnym."
position_in_dictionary: "Pole „{{attribute}}” musi być należeć do słownika {{dictionary}}."
Expand Down