Skip to content

Commit 10a99e2

Browse files
committed
FIX: RequiredIf rule
RequiredIf was formatting its error message string incorrectly when using the spatie RequiredIf attribute.
1 parent 23752d0 commit 10a99e2

File tree

2 files changed

+116
-6
lines changed

2 files changed

+116
-6
lines changed

src/Services/MessageResolutionService.php

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,6 @@ private function getDefaultMessage(): string
9393
$lowerRule = strtolower($this->ruleName);
9494
$snakeRule = Str::snake($this->ruleName);
9595

96-
$messageParameters = $this->parameters;
97-
$messageParameters['attribute'] = $this->field;
98-
9996
$originalData = $this->validator->getData();
10097
$tempData = $originalData;
10198
$dataModified = false;
@@ -105,10 +102,17 @@ private function getDefaultMessage(): string
105102
$dataModified = true;
106103
}
107104

108-
if ($snakeRule === 'required_if' && $this->applyRequiredIfValue($tempData)) {
109-
$dataModified = true;
105+
if ($snakeRule === 'required_if') {
106+
if ($this->applyRequiredIfValue($tempData)) {
107+
$dataModified = true;
108+
} else {
109+
$this->normalizeRequiredIfParameters();
110+
}
110111
}
111112

113+
$messageParameters = $this->parameters;
114+
$messageParameters['attribute'] = $this->field;
115+
112116
if ($dataModified) {
113117
$this->validator->setData($tempData);
114118
}
@@ -180,7 +184,15 @@ private function applyRequiredIfValue(array &$data): bool
180184

181185
$value = $values[0] ?? null;
182186

183-
$this->setNestedValue($data, $otherField, $value);
187+
$normalizedField = $this->normalizeDependentField($otherField);
188+
189+
if ($normalizedField === '') {
190+
$normalizedField = $otherField;
191+
}
192+
193+
$this->parameters[0] = $normalizedField;
194+
195+
$this->setNestedValue($data, $normalizedField, $value);
184196

185197
return true;
186198
}
@@ -424,4 +436,67 @@ private function assignValueToSegments(&$target, array $segments, $value): void
424436

425437
$this->assignValueToSegments($target[$segment], $segments, $value);
426438
}
439+
440+
private function normalizeRequiredIfParameters(): void
441+
{
442+
if (! isset($this->parameters[0]) || ! is_string($this->parameters[0])) {
443+
return;
444+
}
445+
446+
$normalized = $this->normalizeDependentField($this->parameters[0]);
447+
448+
if ($normalized !== '' && $normalized !== $this->parameters[0]) {
449+
$this->parameters[0] = $normalized;
450+
}
451+
}
452+
453+
private function normalizeDependentField(string $dependentField): string
454+
{
455+
$dependentField = trim($dependentField);
456+
457+
if ($dependentField === '') {
458+
return '';
459+
}
460+
461+
$fieldSegments = array_values(array_filter(
462+
explode('.', $this->field),
463+
static fn (string $segment): bool => $segment !== ''
464+
));
465+
466+
$dependentSegments = array_values(array_filter(
467+
explode('.', $dependentField),
468+
static fn (string $segment): bool => $segment !== ''
469+
));
470+
471+
if (empty($fieldSegments) || empty($dependentSegments)) {
472+
return $dependentField;
473+
}
474+
475+
$fieldSegmentCount = count($fieldSegments);
476+
477+
if (count($dependentSegments) <= $fieldSegmentCount) {
478+
return $dependentField;
479+
}
480+
481+
for ($index = 0; $index < $fieldSegmentCount; $index++) {
482+
if (! isset($dependentSegments[$index]) || $dependentSegments[$index] !== $fieldSegments[$index]) {
483+
return $dependentField;
484+
}
485+
}
486+
487+
$parentSegments = array_slice($fieldSegments, 0, -1);
488+
$remainingSegments = array_slice($dependentSegments, $fieldSegmentCount);
489+
490+
if (empty($remainingSegments)) {
491+
return $dependentField;
492+
}
493+
494+
$normalizedSegments = array_merge($parentSegments, $remainingSegments);
495+
496+
if (empty($normalizedSegments)) {
497+
return '';
498+
}
499+
500+
return implode('.', $normalizedSegments);
501+
}
427502
}

tests/Unit/Services/LaravelValidationResolverTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,41 @@ public function it_resolves_required_if_messages_with_expected_value(): void
645645
);
646646
}
647647

648+
#[Test]
649+
public function it_normalizes_required_if_messages_from_relative_field_references(): void
650+
{
651+
$translator = new \Illuminate\Translation\Translator(new \Illuminate\Translation\ArrayLoader, 'en');
652+
$translator->addLines([
653+
'validation.required_if' => 'The :attribute field is required when :other is :value.',
654+
], 'en');
655+
656+
$validator = new \Illuminate\Validation\Validator(
657+
$translator,
658+
[
659+
'connection_type' => 'new',
660+
'existing_account_id' => null,
661+
],
662+
[
663+
'connection_type' => 'nullable|in:new,existing',
664+
'existing_account_id' => 'required_if:existing_account_id.connection_type,existing|string',
665+
]
666+
);
667+
668+
$result = $this->resolver->resolve(
669+
'existing_account_id',
670+
'required_if:existing_account_id.connection_type,existing|string',
671+
$validator
672+
);
673+
674+
$requiredIfValidation = $result->getValidation('RequiredIf');
675+
676+
$this->assertNotNull($requiredIfValidation);
677+
$this->assertSame(
678+
'The existing account id field is required when connection type is existing.',
679+
$requiredIfValidation->message
680+
);
681+
}
682+
648683
#[Test]
649684
public function it_never_returns_translation_keys_as_messages()
650685
{

0 commit comments

Comments
 (0)