mirror of
https://github.com/filamentphp/filament.git
synced 2026-09-24 15:42:09 +08:00
753 lines
23 KiB
PHP
753 lines
23 KiB
PHP
<?php
|
|
|
|
namespace Filament\Forms\Components\Concerns;
|
|
|
|
use Closure;
|
|
use Filament\Forms\Components\Contracts\HasNestedRecursiveValidationRules;
|
|
use Filament\Forms\Components\Field;
|
|
use Illuminate\Contracts\Support\Arrayable;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Validation\Rule;
|
|
use Illuminate\Validation\Rules\Enum;
|
|
use Illuminate\Validation\Rules\Unique;
|
|
|
|
trait CanBeValidated
|
|
{
|
|
protected bool | Closure $isRequired = false;
|
|
|
|
protected string | Closure | null $regexPattern = null;
|
|
|
|
/**
|
|
* @var array<mixed>
|
|
*/
|
|
protected array $rules = [];
|
|
|
|
/**
|
|
* @var array<string, string | Closure>
|
|
*/
|
|
protected array $validationMessages = [];
|
|
|
|
protected string | Closure | null $validationAttribute = null;
|
|
|
|
public function activeUrl(bool | Closure $condition = true): static
|
|
{
|
|
$this->rule('active_url', $condition);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function alpha(bool | Closure $condition = true): static
|
|
{
|
|
$this->rule('alpha', $condition);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function alphaDash(bool | Closure $condition = true): static
|
|
{
|
|
$this->rule('alpha_dash', $condition);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function alphaNum(bool | Closure $condition = true): static
|
|
{
|
|
$this->rule('alpha_num', $condition);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function ascii(bool | Closure $condition = true): static
|
|
{
|
|
$this->rule('ascii', $condition);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function confirmed(bool | Closure $condition = true): static
|
|
{
|
|
$this->rule('confirmed', $condition);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param array<scalar> | Arrayable | string | Closure $values
|
|
*/
|
|
public function doesntStartWith(array | Arrayable | string | Closure $values): static
|
|
{
|
|
$this->rule(static function (Field $component) use ($values) {
|
|
$values = $component->evaluate($values);
|
|
|
|
if ($values instanceof Arrayable) {
|
|
$values = $values->toArray();
|
|
}
|
|
|
|
if (is_array($values)) {
|
|
$values = implode(',', $values);
|
|
}
|
|
|
|
return 'doesnt_start_with:' . $values;
|
|
}, static function (Field $component) use ($values): bool {
|
|
$values = $component->evaluate($values);
|
|
|
|
if ($values instanceof Arrayable) {
|
|
$values = $values->toArray();
|
|
}
|
|
|
|
return is_array($values) ? count($values) : filled($values);
|
|
});
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param array<scalar> | Arrayable | string | Closure $values
|
|
*/
|
|
public function doesntEndWith(array | Arrayable | string | Closure $values): static
|
|
{
|
|
$this->rule(static function (Field $component) use ($values) {
|
|
$values = $component->evaluate($values);
|
|
|
|
if ($values instanceof Arrayable) {
|
|
$values = $values->toArray();
|
|
}
|
|
|
|
if (is_array($values)) {
|
|
$values = implode(',', $values);
|
|
}
|
|
|
|
return 'doesnt_end_with:' . $values;
|
|
}, static function (Field $component) use ($values): bool {
|
|
$values = $component->evaluate($values);
|
|
|
|
if ($values instanceof Arrayable) {
|
|
$values = $values->toArray();
|
|
}
|
|
|
|
return is_array($values) ? count($values) : filled($values);
|
|
});
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param array<scalar> | Arrayable | string | Closure $values
|
|
*/
|
|
public function endsWith(array | Arrayable | string | Closure $values): static
|
|
{
|
|
$this->rule(static function (Field $component) use ($values) {
|
|
$values = $component->evaluate($values);
|
|
|
|
if ($values instanceof Arrayable) {
|
|
$values = $values->toArray();
|
|
}
|
|
|
|
if (is_array($values)) {
|
|
$values = implode(',', $values);
|
|
}
|
|
|
|
return 'ends_with:' . $values;
|
|
}, static function (Field $component) use ($values): bool {
|
|
$values = $component->evaluate($values);
|
|
|
|
if ($values instanceof Arrayable) {
|
|
$values = $values->toArray();
|
|
}
|
|
|
|
return is_array($values) ? count($values) : filled($values);
|
|
});
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function enum(string | Closure $enum): static
|
|
{
|
|
$this->rule(static function (Field $component) use ($enum) {
|
|
$enum = $component->evaluate($enum);
|
|
|
|
return new Enum($enum);
|
|
}, static fn (Field $component): bool => filled($component->evaluate($enum)));
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function exists(string | Closure | null $table = null, string | Closure | null $column = null, ?Closure $modifyRuleUsing = null): static
|
|
{
|
|
$this->rule(static function (Field $component, ?string $model) use ($column, $modifyRuleUsing, $table) {
|
|
$table = $component->evaluate($table) ?? $model;
|
|
$column = $component->evaluate($column) ?? $component->getName();
|
|
|
|
$rule = Rule::exists($table, $column);
|
|
|
|
if ($modifyRuleUsing) {
|
|
$rule = $component->evaluate($modifyRuleUsing, [
|
|
'rule' => $rule,
|
|
]) ?? $rule;
|
|
}
|
|
|
|
return $rule;
|
|
}, static fn (Field $component, ?string $model): bool => (bool) ($component->evaluate($table) ?? $model));
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function filled(bool | Closure $condition = true): static
|
|
{
|
|
$this->rule('filled', $condition);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param array<scalar> | Arrayable | string | Closure $values
|
|
*/
|
|
public function in(array | Arrayable | string | Closure $values): static
|
|
{
|
|
$this->rule(static function (Field $component) use ($values) {
|
|
$values = $component->evaluate($values);
|
|
|
|
if ($values instanceof Arrayable) {
|
|
$values = $values->toArray();
|
|
}
|
|
|
|
if (is_string($values)) {
|
|
$values = array_map('trim', explode(',', $values));
|
|
}
|
|
|
|
return Rule::in($values);
|
|
}, static function (Field $component) use ($values): bool {
|
|
$values = $component->evaluate($values);
|
|
|
|
if ($values instanceof Arrayable) {
|
|
$values = $values->toArray();
|
|
}
|
|
|
|
return is_array($values) ? count($values) : filled($values);
|
|
});
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function ip(bool | Closure $condition = true): static
|
|
{
|
|
$this->rule('ip', $condition);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function ipv4(bool | Closure $condition = true): static
|
|
{
|
|
$this->rule('ipv4', $condition);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function ipv6(bool | Closure $condition = true): static
|
|
{
|
|
$this->rule('ipv6', $condition);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function json(bool | Closure $condition = true): static
|
|
{
|
|
$this->rule('json', $condition);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function macAddress(bool | Closure $condition = true): static
|
|
{
|
|
$this->rule('mac_address', $condition);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function multipleOf(int | Closure $value): static
|
|
{
|
|
$this->rule(static function (Field $component) use ($value) {
|
|
return 'multiple_of:' . $component->evaluate($value);
|
|
}, static fn (Field $component): bool => filled($component->evaluate($value)));
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param array<scalar> | Arrayable | string | Closure $values
|
|
*/
|
|
public function notIn(array | Arrayable | string | Closure $values): static
|
|
{
|
|
$this->rule(static function (Field $component) use ($values) {
|
|
$values = $component->evaluate($values);
|
|
|
|
if ($values instanceof Arrayable) {
|
|
$values = $values->toArray();
|
|
}
|
|
|
|
if (is_string($values)) {
|
|
$values = array_map('trim', explode(',', $values));
|
|
}
|
|
|
|
return Rule::notIn($values);
|
|
}, static function (Field $component) use ($values): bool {
|
|
$values = $component->evaluate($values);
|
|
|
|
if ($values instanceof Arrayable) {
|
|
$values = $values->toArray();
|
|
}
|
|
|
|
return is_array($values) ? count($values) : filled($values);
|
|
});
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function notRegex(string | Closure | null $pattern): static
|
|
{
|
|
$this->rule(static function (Field $component) use ($pattern) {
|
|
return 'not_regex:' . $component->evaluate($pattern);
|
|
}, static fn (Field $component): bool => filled($component->evaluate($pattern)));
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function nullable(bool | Closure $condition = true): static
|
|
{
|
|
$this->required(static function (Field $component) use ($condition): bool {
|
|
return ! $component->evaluate($condition);
|
|
});
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function prohibited(bool | Closure $condition = true): static
|
|
{
|
|
$this->rule('prohibited', $condition);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function required(bool | Closure $condition = true): static
|
|
{
|
|
$this->isRequired = $condition;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function requiredIf(string | Closure $statePath, mixed $stateValues, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->multiFieldValueComparisonRule('required_if', $statePath, $stateValues, $isStatePathAbsolute);
|
|
}
|
|
|
|
public function requiredUnless(string | Closure $statePath, mixed $stateValues, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->multiFieldValueComparisonRule('required_unless', $statePath, $stateValues, $isStatePathAbsolute);
|
|
}
|
|
|
|
/**
|
|
* @param string | array<string> | Closure $statePaths
|
|
*/
|
|
public function requiredWith(string | array | Closure $statePaths, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->multiFieldComparisonRule('required_with', $statePaths, $isStatePathAbsolute);
|
|
}
|
|
|
|
/**
|
|
* @param string | array<string> | Closure $statePaths
|
|
*/
|
|
public function requiredWithAll(string | array | Closure $statePaths, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->multiFieldComparisonRule('required_with_all', $statePaths, $isStatePathAbsolute);
|
|
}
|
|
|
|
/**
|
|
* @param string | array<string> | Closure $statePaths
|
|
*/
|
|
public function requiredWithout(string | array | Closure $statePaths, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->multiFieldComparisonRule('required_without', $statePaths, $isStatePathAbsolute);
|
|
}
|
|
|
|
/**
|
|
* @param string | array<string> | Closure $statePaths
|
|
*/
|
|
public function requiredWithoutAll(string | array | Closure $statePaths, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->multiFieldComparisonRule('required_without_all', $statePaths, $isStatePathAbsolute);
|
|
}
|
|
|
|
public function regex(string | Closure | null $pattern): static
|
|
{
|
|
$this->regexPattern = $pattern;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param array<scalar> | Arrayable | string | Closure $values
|
|
*/
|
|
public function startsWith(array | Arrayable | string | Closure $values): static
|
|
{
|
|
$this->rule(static function (Field $component) use ($values) {
|
|
$values = $component->evaluate($values);
|
|
|
|
if ($values instanceof Arrayable) {
|
|
$values = $values->toArray();
|
|
}
|
|
|
|
if (is_array($values)) {
|
|
$values = implode(',', $values);
|
|
}
|
|
|
|
return 'starts_with:' . $values;
|
|
}, static function (Field $component) use ($values): bool {
|
|
$values = $component->evaluate($values);
|
|
|
|
if ($values instanceof Arrayable) {
|
|
$values = $values->toArray();
|
|
}
|
|
|
|
return is_array($values) ? count($values) : filled($values);
|
|
});
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function string(bool | Closure $condition = true): static
|
|
{
|
|
$this->rule('string', $condition);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function uuid(bool | Closure $condition = true): static
|
|
{
|
|
$this->rule('uuid', $condition);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function rule(mixed $rule, bool | Closure $condition = true): static
|
|
{
|
|
$this->rules = [
|
|
...$this->rules,
|
|
[$rule, $condition],
|
|
];
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param string | array<mixed> $rules
|
|
*/
|
|
public function rules(string | array $rules, bool | Closure $condition = true): static
|
|
{
|
|
if (is_string($rules)) {
|
|
$rules = explode('|', $rules);
|
|
}
|
|
|
|
$this->rules = [
|
|
...$this->rules,
|
|
...array_map(static fn (string | object $rule): array => [$rule, $condition], $rules),
|
|
];
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function after(string | Closure $date, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->dateComparisonRule('after', $date, $isStatePathAbsolute);
|
|
}
|
|
|
|
public function afterOrEqual(string | Closure $date, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->dateComparisonRule('after_or_equal', $date, $isStatePathAbsolute);
|
|
}
|
|
|
|
public function before(string | Closure $date, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->dateComparisonRule('before', $date, $isStatePathAbsolute);
|
|
}
|
|
|
|
public function beforeOrEqual(string | Closure $date, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->dateComparisonRule('before_or_equal', $date, $isStatePathAbsolute);
|
|
}
|
|
|
|
public function different(string | Closure $statePath, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->fieldComparisonRule('different', $statePath, $isStatePathAbsolute);
|
|
}
|
|
|
|
public function gt(string | Closure $statePath, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->fieldComparisonRule('gt', $statePath, $isStatePathAbsolute);
|
|
}
|
|
|
|
public function gte(string | Closure $statePath, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->fieldComparisonRule('gte', $statePath, $isStatePathAbsolute);
|
|
}
|
|
|
|
public function lt(string | Closure $statePath, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->fieldComparisonRule('lt', $statePath, $isStatePathAbsolute);
|
|
}
|
|
|
|
public function lte(string | Closure $statePath, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->fieldComparisonRule('lte', $statePath, $isStatePathAbsolute);
|
|
}
|
|
|
|
public function same(string | Closure $statePath, bool $isStatePathAbsolute = false): static
|
|
{
|
|
return $this->fieldComparisonRule('same', $statePath, $isStatePathAbsolute);
|
|
}
|
|
|
|
public function unique(string | Closure | null $table = null, string | Closure | null $column = null, Model | Closure | null $ignorable = null, bool $ignoreRecord = false, ?Closure $modifyRuleUsing = null): static
|
|
{
|
|
$this->rule(static function (Field $component, ?string $model) use ($column, $ignorable, $ignoreRecord, $modifyRuleUsing, $table) {
|
|
$table = $component->evaluate($table) ?? $model;
|
|
$column = $component->evaluate($column) ?? $component->getName();
|
|
$ignorable = ($ignoreRecord && ! $ignorable) ?
|
|
$component->getRecord() :
|
|
$component->evaluate($ignorable);
|
|
|
|
$rule = Rule::unique($table, $column)
|
|
->when(
|
|
$ignorable,
|
|
fn (Unique $rule) => $rule->ignore(
|
|
$ignorable->getOriginal($ignorable->getKeyName()),
|
|
$ignorable->getQualifiedKeyName(),
|
|
),
|
|
);
|
|
|
|
if ($modifyRuleUsing) {
|
|
$rule = $component->evaluate($modifyRuleUsing, [
|
|
'rule' => $rule,
|
|
]) ?? $rule;
|
|
}
|
|
|
|
return $rule;
|
|
}, fn (Field $component, ?string $model): bool => (bool) ($component->evaluate($table) ?? $model));
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function validationAttribute(string | Closure | null $label): static
|
|
{
|
|
$this->validationAttribute = $label;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param array<string, string | Closure> $messages
|
|
*/
|
|
public function validationMessages(array $messages): static
|
|
{
|
|
$this->validationMessages = $messages;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getRegexPattern(): ?string
|
|
{
|
|
return $this->evaluate($this->regexPattern);
|
|
}
|
|
|
|
public function getRequiredValidationRule(): string
|
|
{
|
|
return $this->isRequired() ? 'required' : 'nullable';
|
|
}
|
|
|
|
public function getValidationAttribute(): string
|
|
{
|
|
return $this->evaluate($this->validationAttribute) ?? Str::lcfirst($this->getLabel());
|
|
}
|
|
|
|
/**
|
|
* @return array<string, string>
|
|
*/
|
|
public function getValidationMessages(): array
|
|
{
|
|
$messages = [];
|
|
|
|
foreach ($this->validationMessages as $rule => $message) {
|
|
$messages[$rule] = $this->evaluate($message);
|
|
}
|
|
|
|
return array_filter($messages);
|
|
}
|
|
|
|
/**
|
|
* @return array<mixed>
|
|
*/
|
|
public function getValidationRules(): array
|
|
{
|
|
$rules = [
|
|
$this->getRequiredValidationRule(),
|
|
];
|
|
|
|
if (filled($regexPattern = $this->getRegexPattern())) {
|
|
$rules[] = "regex:{$regexPattern}";
|
|
}
|
|
|
|
foreach ($this->rules as [$rule, $condition]) {
|
|
if (is_numeric($rule)) {
|
|
$rules[] = $this->evaluate($condition);
|
|
} elseif ($this->evaluate($condition)) {
|
|
$rules[] = $this->evaluate($rule);
|
|
}
|
|
}
|
|
|
|
return $rules;
|
|
}
|
|
|
|
/**
|
|
* @param array<string, array<string, string>> $messages
|
|
*/
|
|
public function dehydrateValidationMessages(array &$messages): void
|
|
{
|
|
$statePath = $this->getStatePath();
|
|
|
|
if (count($componentMessages = $this->getValidationMessages())) {
|
|
foreach ($componentMessages as $rule => $message) {
|
|
$messages["{$statePath}.{$rule}"] = $message;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param array<string, array<mixed>> $rules
|
|
*/
|
|
public function dehydrateValidationRules(array &$rules): void
|
|
{
|
|
$statePath = $this->getStatePath();
|
|
|
|
if (count($componentRules = $this->getValidationRules())) {
|
|
$rules[$statePath] = $componentRules;
|
|
}
|
|
|
|
if (! $this instanceof HasNestedRecursiveValidationRules) {
|
|
return;
|
|
}
|
|
|
|
$nestedRecursiveValidationRules = $this->getNestedRecursiveValidationRules();
|
|
|
|
if (! count($nestedRecursiveValidationRules)) {
|
|
return;
|
|
}
|
|
|
|
$rules["{$statePath}.*"] = $nestedRecursiveValidationRules;
|
|
}
|
|
|
|
public function dehydrateValidationAttributes(array &$attributes): void
|
|
{
|
|
$attributes[$this->getStatePath()] = $this->getValidationAttribute();
|
|
}
|
|
|
|
public function isRequired(): bool
|
|
{
|
|
return (bool) $this->evaluate($this->isRequired);
|
|
}
|
|
|
|
public function dateComparisonRule(string $rule, string | Closure $date, bool $isStatePathAbsolute = false): static
|
|
{
|
|
$this->rule(static function (Field $component) use ($date, $isStatePathAbsolute, $rule): string {
|
|
$date = $component->evaluate($date);
|
|
|
|
if (! (strtotime($date) || $isStatePathAbsolute)) {
|
|
$containerStatePath = $component->getContainer()->getStatePath();
|
|
|
|
if ($containerStatePath) {
|
|
$date = "{$containerStatePath}.{$date}";
|
|
}
|
|
}
|
|
|
|
return "{$rule}:{$date}";
|
|
}, fn (Field $component): bool => (bool) $component->evaluate($date));
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function fieldComparisonRule(string $rule, string | Closure $statePath, bool $isStatePathAbsolute = false): static
|
|
{
|
|
$this->rule(static function (Field $component) use ($isStatePathAbsolute, $rule, $statePath): string {
|
|
$statePath = $component->evaluate($statePath);
|
|
|
|
if (! $isStatePathAbsolute) {
|
|
$containerStatePath = $component->getContainer()->getStatePath();
|
|
|
|
if ($containerStatePath) {
|
|
$statePath = "{$containerStatePath}.{$statePath}";
|
|
}
|
|
}
|
|
|
|
return "{$rule}:{$statePath}";
|
|
}, fn (Field $component): bool => (bool) $component->evaluate($statePath));
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param array<string> | string | Closure $statePaths
|
|
*/
|
|
public function multiFieldComparisonRule(string $rule, array | string | Closure $statePaths, bool $isStatePathAbsolute = false): static
|
|
{
|
|
$this->rule(static function (Field $component) use ($isStatePathAbsolute, $rule, $statePaths): string {
|
|
$statePaths = $component->evaluate($statePaths);
|
|
|
|
if (! $isStatePathAbsolute) {
|
|
if (is_string($statePaths)) {
|
|
$statePaths = explode(',', $statePaths);
|
|
}
|
|
|
|
$containerStatePath = $component->getContainer()->getStatePath();
|
|
|
|
if ($containerStatePath) {
|
|
$statePaths = array_map(function ($statePath) use ($containerStatePath) {
|
|
$statePath = trim($statePath);
|
|
|
|
return "{$containerStatePath}.{$statePath}";
|
|
}, $statePaths);
|
|
}
|
|
}
|
|
|
|
if (is_array($statePaths)) {
|
|
$statePaths = implode(',', $statePaths);
|
|
}
|
|
|
|
return "{$rule}:{$statePaths}";
|
|
}, fn (Field $component): bool => (bool) $component->evaluate($statePaths));
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function multiFieldValueComparisonRule(string $rule, string | Closure $statePath, mixed $stateValues, bool $isStatePathAbsolute = false): static
|
|
{
|
|
$this->rule(static function (Field $component) use ($isStatePathAbsolute, $rule, $statePath, $stateValues): string {
|
|
$statePath = $component->evaluate($statePath);
|
|
$stateValues = $component->evaluate($stateValues);
|
|
|
|
if (! $isStatePathAbsolute) {
|
|
$containerStatePath = $component->getContainer()->getStatePath();
|
|
|
|
if ($containerStatePath) {
|
|
$statePath = "{$containerStatePath}.{$statePath}";
|
|
}
|
|
}
|
|
|
|
if (is_array($stateValues)) {
|
|
$stateValues = implode(',', $stateValues);
|
|
}
|
|
|
|
return "{$rule}:{$statePath},{$stateValues}";
|
|
}, fn (Field $component): bool => (bool) $component->evaluate($statePath));
|
|
|
|
return $this;
|
|
}
|
|
}
|