Skip to content

Commit 91b092c

Browse files
committed
feat: add validation contract to map field
1 parent 74403d6 commit 91b092c

File tree

2 files changed

+91
-2
lines changed

2 files changed

+91
-2
lines changed

src/Fields/Map.php

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace LaravelJsonApi\Eloquent\Fields;
1313

1414
use Illuminate\Database\Eloquent\Model;
15+
use Illuminate\Http\Request;
1516
use Illuminate\Support\Arr;
1617
use InvalidArgumentException;
1718
use LaravelJsonApi\Contracts\Resources\Serializer\Attribute as SerializableContract;
@@ -23,16 +24,17 @@
2324
use LaravelJsonApi\Eloquent\Fields\Concerns\Hideable;
2425
use LaravelJsonApi\Eloquent\Fields\Concerns\IsReadOnly;
2526
use LaravelJsonApi\Eloquent\Fields\Concerns\OnRelated;
27+
use LaravelJsonApi\Validation\Fields\IsValidated;
2628
use LogicException;
2729

2830
class Map implements
2931
AttributeContract,
3032
EagerLoadableField,
3133
Fillable,
3234
Selectable,
33-
SerializableContract
35+
SerializableContract,
36+
IsValidated
3437
{
35-
3638
use Hideable;
3739
use OnRelated;
3840
use IsReadOnly;
@@ -215,6 +217,50 @@ public function serialize(object $model)
215217
return $values ?: null;
216218
}
217219

220+
/**
221+
* @inheritDoc
222+
*/
223+
public function rulesForCreation(?Request $request): ?array
224+
{
225+
$fields = [];
226+
$rules = [];
227+
228+
/** @var AttributeContract $attr */
229+
foreach ($this->map as $attr) {
230+
if ($attr instanceof IsValidated) {
231+
$fields[] = $name = $attr->name();
232+
$rules[$name] = $attr->rulesForCreation($request);
233+
}
234+
}
235+
236+
return !empty($fields) ? [
237+
'.' => 'array:' . implode(',', $fields),
238+
...$rules,
239+
] : null;
240+
}
241+
242+
/**
243+
* @inheritDoc
244+
*/
245+
public function rulesForUpdate(?Request $request, object $model): ?array
246+
{
247+
$fields = [];
248+
$rules = [];
249+
250+
/** @var AttributeContract $attr */
251+
foreach ($this->map as $attr) {
252+
if ($attr instanceof IsValidated) {
253+
$fields[] = $name = $attr->name();
254+
$rules[$name] = $attr->rulesForUpdate($request, $model);
255+
}
256+
}
257+
258+
return !empty($fields) ? [
259+
'.' => 'array:' . implode(',', $fields),
260+
...$rules,
261+
] : null;
262+
}
263+
218264
/**
219265
* Set all values to null.
220266
*

tests/lib/Integration/Fields/MapTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
use LaravelJsonApi\Eloquent\Fields\Number;
2020
use LaravelJsonApi\Eloquent\Fields\Str;
2121
use LaravelJsonApi\Eloquent\Tests\Integration\TestCase;
22+
use LaravelJsonApi\Validation\Fields\IsValidated;
23+
use LaravelJsonApi\Validation\Rules\JsonNumber;
24+
use LaravelJsonApi\Validation\Rules\JsonObject;
2225

2326
class MapTest extends TestCase
2427
{
@@ -283,4 +286,44 @@ public function testHiddenCallback(): void
283286
$this->assertTrue($map->isHidden($mock));
284287
}
285288

289+
public function testItIsValidatedOnCreate(): void
290+
{
291+
$request = $this->createMock(Request::class);
292+
$model = new \stdClass();
293+
294+
$map = Map::make('options', [
295+
Str::make('foo', 'option_foo')
296+
->creationRules(function ($r) use ($request) {
297+
$this->assertSame($request, $r);
298+
return ['foo1'];
299+
})
300+
->updateRules(function ($r, $m) use ($request, $model) {
301+
$this->assertSame($request, $r);
302+
$this->assertSame($model, $m);
303+
return ['foo2'];
304+
}),
305+
Number::make('bar', 'option_bar')
306+
->creationRules(function ($r) use ($request) {
307+
$this->assertSame($request, $r);
308+
return ['bar1'];
309+
})
310+
->updateRules(function ($r, $m) use ($request, $model) {
311+
$this->assertSame($request, $r);
312+
$this->assertSame($model, $m);
313+
return ['bar2'];
314+
}),
315+
]);
316+
317+
$this->assertInstanceOf(IsValidated::class, $map);
318+
$this->assertEquals([
319+
'.' => 'array:bar,foo',
320+
'foo' => ['string', 'foo1'],
321+
'bar' => [new JsonNumber(), 'bar1'],
322+
], $map->rulesForCreation($request));
323+
$this->assertEquals([
324+
'.' => 'array:bar,foo',
325+
'foo' => ['string', 'foo2'],
326+
'bar' => [new JsonNumber(), 'bar2'],
327+
], $map->rulesForUpdate($request, $model));
328+
}
286329
}

0 commit comments

Comments
 (0)