Skip to content

Commit

Permalink
Merge pull request #4 from whitecube/fix-model-serialize
Browse files Browse the repository at this point in the history
Fixed models serialization
  • Loading branch information
voidgraphics authored Apr 12, 2023
2 parents e8d6336 + 1a3775b commit 279f13f
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 2 deletions.
24 changes: 23 additions & 1 deletion src/Casts/TimezonedDatetime.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
use Illuminate\Support\Facades\Date;
use Whitecube\LaravelTimezones\Facades\Timezone;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Carbon\Carbon;
use Illuminate\Support\Facades\Config;
use Illuminate\Database\Eloquent\Model;

class TimezonedDatetime implements CastsAttributes
{
Expand Down Expand Up @@ -40,6 +43,10 @@ public function get($model, $key, $value, $attributes)
if(!$value && $value !== 0) {
return null;
}

if ($this->isTimestamp($model, $key)) {
$value = Carbon::parse($value)->format($this->format ?? $model->getDateFormat());
}

$original = Timezone::store($value, fn($raw, $tz) => $this->asDateTime($raw, $tz, $model));

Expand All @@ -61,10 +68,25 @@ public function set($model, $key, $value, $attributes)
return null;
}

if ($this->isTimestamp($model, $key) && is_string($value)) {
$value = Carbon::parse($value, Config::get('app.timezone'));
}

$requested = Timezone::date($value, fn($raw, $tz) => $this->asDateTime($raw, $tz, $model));

return Timezone::store($requested)->format($this->format ?? $model->getDateFormat());
}

/**
* Check if the given key is part of the model's known timestamps
* @param Model $model
* @param string $key
* @return bool
*/
protected function isTimestamp(Model $model, string $key): bool
{
return $model->usesTimestamps() && in_array($key, $model->getDates());
}

/**
* Create a new date value from raw material
Expand All @@ -82,4 +104,4 @@ public function asDateTime($value, $timezone, $model)
$timezone,
);
}
}
}
24 changes: 23 additions & 1 deletion tests/CastTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

use Carbon\Carbon;
use Illuminate\Support\Facades\Config;
use Whitecube\LaravelTimezones\Casts\TimezonedDatetime;

it('can access UTC database date with application timezone', function() {
Expand Down Expand Up @@ -138,4 +140,24 @@

$output = $cast->get(fakeModel(), 'id', $input, []);
expect($output->format('H'))->toEqual(4);
});
});

test('a model with a timezone date cast can be json serialized', function () {
setupFacade();

Config::shouldReceive('get')
->with('app.timezone')
->andReturn('UTC');

$date = new Carbon('2022-12-15 09:00:00', 'UTC');
$model = fakeModelWithCast();

$model->test_at = $date;
$model->updated_at = $date;

expect($model->jsonSerialize())
->toBe([
'test_at' => $date->toJSON(),
'updated_at' => $date->toJSON()
]);
});
17 changes: 17 additions & 0 deletions tests/Pest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use Whitecube\LaravelTimezones\Timezone;
use Whitecube\LaravelTimezones\Facades\Timezone as Facade;
use Illuminate\Database\Eloquent\Model;
use Whitecube\LaravelTimezones\Casts\TimezonedDatetime;

/*
|--------------------------------------------------------------------------
Expand Down Expand Up @@ -60,3 +61,19 @@ public function getDateFormat()
}
};
}

function fakeModelWithCast()
{
return new class() extends Model {
protected $casts = [
'test_at' => TimezonedDatetime::class,
'created_at' => TimezonedDatetime::class,
'updated_at' => TimezonedDatetime::class,
];

public function getDateFormat()
{
return 'Y-m-d H:i:s';
}
};
}

0 comments on commit 279f13f

Please sign in to comment.