Skip to content

Commit 3129237

Browse files
committed
Add validation rules to ensure attributes are morphable
1 parent 635d813 commit 3129237

6 files changed

+59
-3
lines changed

src/Attributes/PropertyForMorph.php

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Spatie\LaravelData\Attributes;
4+
5+
use Attribute;
6+
7+
#[Attribute(Attribute::TARGET_PROPERTY)]
8+
class PropertyForMorph
9+
{
10+
}

src/Resolvers/DataValidationRulesResolver.php

+5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Spatie\LaravelData\Support\DataProperty;
1515
use Spatie\LaravelData\Support\Validation\DataRules;
1616
use Spatie\LaravelData\Support\Validation\PropertyRules;
17+
use Spatie\LaravelData\Support\Validation\RequiresPropertyMorphableClassRule;
1718
use Spatie\LaravelData\Support\Validation\RuleDenormalizer;
1819
use Spatie\LaravelData\Support\Validation\RuleNormalizer;
1920
use Spatie\LaravelData\Support\Validation\ValidationContext;
@@ -77,6 +78,10 @@ public function execute(
7778
$path,
7879
);
7980

81+
if ($dataProperty->isForMorph) {
82+
$rules[] = new RequiresPropertyMorphableClassRule($dataClass);
83+
}
84+
8085
$dataRules->add($propertyPath, $rules);
8186
}
8287

src/Support/DataProperty.php

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public function __construct(
2929
public readonly ?string $inputMappedName,
3030
public readonly ?string $outputMappedName,
3131
public readonly Collection $attributes,
32+
public readonly bool $isForMorph,
3233
) {
3334
}
3435
}

src/Support/Factories/DataPropertyFactory.php

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Spatie\LaravelData\Attributes\Computed;
1010
use Spatie\LaravelData\Attributes\GetsCast;
1111
use Spatie\LaravelData\Attributes\Hidden;
12+
use Spatie\LaravelData\Attributes\PropertyForMorph;
1213
use Spatie\LaravelData\Attributes\WithCastAndTransformer;
1314
use Spatie\LaravelData\Attributes\WithoutValidation;
1415
use Spatie\LaravelData\Attributes\WithTransformer;
@@ -108,6 +109,7 @@ className: $reflectionProperty->class,
108109
inputMappedName: $inputMappedName,
109110
outputMappedName: $outputMappedName,
110111
attributes: $attributes,
112+
isForMorph: ! empty($reflectionProperty->getAttributes(PropertyForMorph::class)),
111113
);
112114
}
113115
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Spatie\LaravelData\Support\Validation;
4+
5+
use Closure;
6+
use Illuminate\Contracts\Validation\ValidationRule;
7+
use Spatie\LaravelData\Attributes\Validation\ObjectValidationAttribute;
8+
use Spatie\LaravelData\Support\DataClass;
9+
10+
class RequiresPropertyMorphableClassRule extends ObjectValidationAttribute implements ValidationRule
11+
{
12+
public function __construct(protected DataClass $dataClass)
13+
{
14+
}
15+
16+
public function getRule(ValidationPath $path): object|string
17+
{
18+
return $this;
19+
}
20+
21+
public static function keyword(): string
22+
{
23+
return 'requires_property_morphable_class';
24+
}
25+
26+
public static function create(string ...$parameters): static
27+
{
28+
return new static(...$parameters);
29+
}
30+
31+
public function validate(string $attribute, mixed $value, Closure $fail): void
32+
{
33+
if (! $this->dataClass->propertyMorphable || $this->dataClass->isAbstract) {
34+
$fail('The selected :attribute is invalid for morph.');
35+
}
36+
}
37+
}

tests/ValidationTest.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Spatie\LaravelData\Attributes\MapInputName;
2222
use Spatie\LaravelData\Attributes\MapName;
2323
use Spatie\LaravelData\Attributes\MergeValidationRules;
24+
use Spatie\LaravelData\Attributes\PropertyForMorph;
2425
use Spatie\LaravelData\Attributes\Validation\ArrayType;
2526
use Spatie\LaravelData\Attributes\Validation\Bail;
2627
use Spatie\LaravelData\Attributes\Validation\BooleanType;
@@ -2611,7 +2612,7 @@ public static function rules(): array
26112612
abstract class TestValidationAbstractPropertyMorphableData extends Data implements PropertyMorphableData
26122613
{
26132614
public function __construct(
2614-
#[In('a', 'b')]
2615+
#[PropertyForMorph]
26152616
public string $variant,
26162617
) {
26172618
}
@@ -2650,7 +2651,7 @@ public function __construct(public string $b)
26502651
->assertErrors([
26512652
'variant' => 'c',
26522653
], [
2653-
'variant' => ['The selected variant is invalid.'],
2654+
'variant' => ['The selected variant is invalid for morph.'],
26542655
])
26552656
->assertErrors([
26562657
'variant' => 'a',
@@ -2700,7 +2701,7 @@ public function __construct(
27002701
->assertErrors([
27012702
'nestedCollection' => [['variant' => 'c']],
27022703
], [
2703-
'nestedCollection.0.variant' => ['The selected nested collection.0.variant is invalid.'],
2704+
'nestedCollection.0.variant' => ['The selected nested collection.0.variant is invalid for morph.'],
27042705
])
27052706
->assertErrors([
27062707
'nestedCollection' => [['variant' => 'a'], ['variant' => 'b']],

0 commit comments

Comments
 (0)