Skip to content

Commit 381768b

Browse files
committed
Add BooleanDateTime attribute
1 parent 36a9bf8 commit 381768b

File tree

4 files changed

+138
-1
lines changed

4 files changed

+138
-1
lines changed

docs/attributes.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,21 @@ Date::make('dob');
4242
DateTime::make('publishedAt');
4343
```
4444

45+
### BooleanDateTime
46+
47+
The `BooleanDateTime` attribute behaves like the `Boolean` attribute, except
48+
that before setting the value to the model, a `true` value is set as the current
49+
date, and a `false` value is set as `null`. This can be used to represent a
50+
field that is stored internally as a timestamp as a boolean in the API.
51+
52+
```php
53+
use Tobyz\JsonApiServer\Field\DateTime;
54+
55+
BooleanDateTime::make('isDeleted')
56+
->property('deleted_at')
57+
->writable();
58+
```
59+
4560
### Number and Integer
4661

4762
The `Number` attribute serializes values to floats, and performs validation to

src/Schema/Field/BooleanDateTime.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Tobyz\JsonApiServer\Schema\Field;
4+
5+
use Tobyz\JsonApiServer\Context;
6+
7+
class BooleanDateTime extends Boolean
8+
{
9+
public function setValue(mixed $model, mixed $value, Context $context): void
10+
{
11+
parent::setValue($model, $value ? new \DateTime() : null, $context);
12+
}
13+
14+
public function saveValue(mixed $model, mixed $value, Context $context): void
15+
{
16+
parent::saveValue($model, $value ? new \DateTime() : null, $context);
17+
}
18+
}

tests/feature/BooleanDateTimeTest.php

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
3+
namespace Tobyz\Tests\JsonApiServer\feature;
4+
5+
use Tobyz\JsonApiServer\Endpoint\Create;
6+
use Tobyz\JsonApiServer\Endpoint\Update;
7+
use Tobyz\JsonApiServer\Exception\UnprocessableEntityException;
8+
use Tobyz\JsonApiServer\JsonApi;
9+
use Tobyz\JsonApiServer\Schema\Field\BooleanDateTime;
10+
use Tobyz\Tests\JsonApiServer\AbstractTestCase;
11+
use Tobyz\Tests\JsonApiServer\MockResource;
12+
13+
class BooleanDateTimeTest extends AbstractTestCase
14+
{
15+
private JsonApi $api;
16+
17+
public function setUp(): void
18+
{
19+
$this->api = new JsonApi();
20+
}
21+
22+
public function test_validates_boolean()
23+
{
24+
$this->api->resource(
25+
new MockResource(
26+
'users',
27+
endpoints: [Create::make()],
28+
fields: [
29+
BooleanDateTime::make('isDeleted')
30+
->property('deletedAt')
31+
->writable(),
32+
],
33+
),
34+
);
35+
36+
$this->expectException(UnprocessableEntityException::class);
37+
38+
$this->api->handle(
39+
$this->buildRequest('POST', '/users')->withParsedBody([
40+
'data' => ['type' => 'users', 'attributes' => ['isDeleted' => 'hello']],
41+
]),
42+
);
43+
}
44+
45+
public function test_sets_value_as_date_time()
46+
{
47+
$this->api->resource(
48+
new MockResource(
49+
'users',
50+
models: [($user = (object) ['id' => '1'])],
51+
endpoints: [Update::make()],
52+
fields: [
53+
BooleanDateTime::make('isDeleted')
54+
->property('deletedAt')
55+
->writable(),
56+
],
57+
),
58+
);
59+
60+
$response = $this->api->handle(
61+
$this->buildRequest('PATCH', '/users/1')->withParsedBody([
62+
'data' => ['type' => 'users', 'id' => '1', 'attributes' => ['isDeleted' => true]],
63+
]),
64+
);
65+
66+
$this->assertInstanceOf(\DateTime::class, $user->deletedAt);
67+
68+
$this->assertJsonApiDocumentSubset(
69+
['data' => ['attributes' => ['isDeleted' => true]]],
70+
$response->getBody(),
71+
true,
72+
);
73+
}
74+
75+
public function test_sets_value_as_null()
76+
{
77+
$this->api->resource(
78+
new MockResource(
79+
'users',
80+
models: [($user = (object) ['id' => '1'])],
81+
endpoints: [Update::make()],
82+
fields: [
83+
BooleanDateTime::make('isDeleted')
84+
->property('deletedAt')
85+
->writable(),
86+
],
87+
),
88+
);
89+
90+
$response = $this->api->handle(
91+
$this->buildRequest('PATCH', '/users/1')->withParsedBody([
92+
'data' => ['type' => 'users', 'id' => '1', 'attributes' => ['isDeleted' => false]],
93+
]),
94+
);
95+
96+
$this->assertNull($user->deletedAt);
97+
98+
$this->assertJsonApiDocumentSubset(
99+
['data' => ['attributes' => ['isDeleted' => false]]],
100+
$response->getBody(),
101+
true,
102+
);
103+
}
104+
}

tests/feature/BooleanTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public function test_validates_boolean()
5151

5252
$this->expectException(UnprocessableEntityException::class);
5353

54-
$response = $this->api->handle(
54+
$this->api->handle(
5555
$this->buildRequest('POST', '/users')->withParsedBody([
5656
'data' => ['type' => 'users', 'attributes' => ['name' => 'hello']],
5757
]),

0 commit comments

Comments
 (0)