Lines 100.00% 14 / 14
Methods 100.00% 5 / 5
Classes 100.00% 1 / 1
Name Lines Methods CRAP
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 defaultMessage 100.00% 1 / 1 100.00% 1 / 1 1
 validate 100.00% 4 / 4 100.00% 1 / 1 4
 [Lucent\Validation\Constraint] withMessage 100.00% 2 / 2 100.00% 1 / 1 1
 [Lucent\Validation\Constraint] message 100.00% 6 / 6 100.00% 1 / 1 3
30final class Unique extends Constraint
31{
32    /**
33     * Create a unique constraint backed by an existence check.
34     *
35     * @param Closure(mixed): bool $exists A callable that receives the field
36     *        value and returns true when a conflicting row already exists.
37     */
38    public function __construct(private readonly Closure $exists) {}
39
40    /**
41     * @return string|Closure(FieldContext): string The default error message.
42     */
43    #[Override]
44    protected function defaultMessage(): string|Closure|null
45    {
46        return fn(FieldContext $ctx) => "The {$ctx->field} has already been taken.";
47    }
48
49    /**
50     * Validate that the value does not already exist.
51     *
52     * Empty values always pass, deferring presence to the
53     * {@see \Lucent\Validation\Constraints\Required} constraint. Otherwise the
54     * value is passed to the existence callable; the constraint fails when a
55     * conflicting row exists.
56     *
57     * @param FieldContext $ctx The context of the field being validated.
58     * @return bool True if the value is empty or no conflicting row exists, false otherwise.
59     */
60    #[Override]
61    public function validate(FieldContext $ctx): bool
62    {
63        $value = $ctx->value;
64
65        if ($value === null || $value === '' || $value === []) {
66            return true;
67        }
68
69        return !call_user_func($this->exists, $value);
70    }
71}

Inherited from Lucent\Validation\Constraint

38    final public function withMessage(string|\Closure $message): static
39    {
40        $this->customMessage = $message;
41        return $this;
42    }
56    final public function message(FieldContext $ctx): ?string
57    {
58        $message = $this->customMessage ?? $this->defaultMessage();
59
60        if ($message === null) {
61            return null;
62        }
63
64        if ($message instanceof \Closure) {
65            return call_user_func($message, $ctx);
66        }
67
68        return $message;
69    }