Skip to content
This repository was archived by the owner on Jan 2, 2024. It is now read-only.

Commit 84611aa

Browse files
committed
Support for Date and DateTime casting, fixes #53
1 parent 6d71bdc commit 84611aa

File tree

6 files changed

+160
-3
lines changed

6 files changed

+160
-3
lines changed

src/Components/HandlesBoundValues.php

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
namespace ProtoneMedia\LaravelFormComponents\Components;
44

5+
use DateTimeInterface;
56
use Illuminate\Database\Eloquent\Model;
67
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
78
use Illuminate\Database\Eloquent\Relations\MorphMany;
9+
use Illuminate\Support\Carbon;
810
use ProtoneMedia\LaravelFormComponents\FormDataBinder;
911

1012
trait HandlesBoundValues
@@ -52,9 +54,51 @@ private function getBoundValue($bind, string $name)
5254

5355
$bind = $bind ?: $this->getBoundTarget();
5456

55-
return $this->manyRelation
56-
? $this->getAttachedKeysFromRelation($bind, $name)
57-
: data_get($bind, $name);
57+
if ($this->manyRelation) {
58+
return $this->getAttachedKeysFromRelation($bind, $name);
59+
}
60+
61+
$boundValue = data_get($bind, $name);
62+
63+
if ($bind instanceof Model && $boundValue instanceof DateTimeInterface) {
64+
return $this->formatDateTime($bind, $name, $boundValue);
65+
}
66+
67+
return $boundValue;
68+
}
69+
70+
/**
71+
* Formats a DateTimeInterface if the key is specified as a date or datetime in the model.
72+
*
73+
* @param \Illuminate\Database\Eloquent\Model $model
74+
* @param string $key
75+
* @param DateTimeInterface $date
76+
* @return void
77+
*/
78+
private function formatDateTime(Model $model, string $key, DateTimeInterface $date)
79+
{
80+
$cast = $model->getCasts()[$key] ?? null;
81+
82+
if (!$cast || $cast === 'date' || $cast === 'datetime') {
83+
return Carbon::instance($date)->toJSON();
84+
}
85+
86+
if ($this->isCustomDateTimeCast($cast)) {
87+
return $date->format(explode(':', $cast, 2)[1]);
88+
}
89+
90+
return $date;
91+
}
92+
93+
/**
94+
* Determine if the cast type is a custom date time cast.
95+
*
96+
* @param string $cast
97+
* @return bool
98+
*/
99+
protected function isCustomDateTimeCast($cast)
100+
{
101+
return strncmp($cast, 'date:', 5) === 0 || strncmp($cast, 'datetime:', 9) === 0;
58102
}
59103

60104
/**

tests/Feature/ActivityModel.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace ProtoneMedia\LaravelFormComponents\Tests\Feature;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
7+
class ActivityModel extends Model
8+
{
9+
public $casts = [
10+
'date_b' => 'date',
11+
'date_c' => 'datetime',
12+
'date_d' => 'date:Y',
13+
'date_e' => 'datetime:Y-m',
14+
];
15+
16+
public $dates = ['date_a'];
17+
}

tests/Feature/DateTimeCastTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace ProtoneMedia\LaravelFormComponents\Tests\Feature;
4+
5+
use Illuminate\Support\Carbon;
6+
use Illuminate\Support\Facades\View;
7+
use ProtoneMedia\LaravelFormComponents\Tests\TestCase;
8+
9+
class DateTimeCastTest extends TestCase
10+
{
11+
/** @test */
12+
public function it_supports_date_casts_and_custom_casts()
13+
{
14+
$this->registerTestRoute('date-time-casts');
15+
16+
Carbon::setTestNow(Carbon::parse('2021-11-01 12:00:00'));
17+
18+
ActivityModel::unguard();
19+
20+
View::share('model', new ActivityModel([
21+
'date_a' => now(),
22+
'date_b' => now(),
23+
'date_c' => now(),
24+
'date_d' => now(),
25+
'date_e' => now(),
26+
]));
27+
28+
$this->visit('/date-time-casts')
29+
->seeElement('input[name="date_a"][value="2021-11-01T12:00:00.000000Z"]')
30+
->seeElement('input[name="date_b"][value="2021-11-01T00:00:00.000000Z"]')
31+
->seeElement('input[name="date_c"][value="2021-11-01T12:00:00.000000Z"]')
32+
->seeElement('input[name="date_d"][value="2021"]')
33+
->seeElement('input[name="date_e"][value="2021-11"]');
34+
}
35+
}

tests/Feature/DateTimeModel.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace ProtoneMedia\LaravelFormComponents\Tests\Feature;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
7+
class ActivityModel extends Model
8+
{
9+
public $casts = [
10+
'date_b' => 'date',
11+
'date_c' => 'datetime',
12+
'date_d' => 'date:Y',
13+
'date_e' => 'datetime:Y-m',
14+
];
15+
16+
public $dates = ['date_a'];
17+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
class CreateActivitiesTable extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::create('activities', function (Blueprint $table) {
17+
$table->date('date_a');
18+
$table->date('date_b');
19+
$table->dateTime('date_c');
20+
$table->date('date_d');
21+
$table->dateTime('date_e');
22+
});
23+
}
24+
/**
25+
* Reverse the migrations.
26+
*
27+
* @return void
28+
*/
29+
public function down()
30+
{
31+
Schema::dropIfExists('activities');
32+
}
33+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<x-form>
2+
@bind($model)
3+
<x-form-input name="date_a" />
4+
<x-form-input name="date_b" />
5+
<x-form-input name="date_c" />
6+
<x-form-input name="date_d" />
7+
<x-form-input name="date_e" />
8+
9+
<x-form-submit />
10+
@endbind
11+
</x-form>

0 commit comments

Comments
 (0)