Skip to content

Commit

Permalink
Update handling of dates for Laravel 10
Browse files Browse the repository at this point in the history
  • Loading branch information
alcaeus committed Feb 9, 2023
1 parent 452a0bb commit 2ea1a7c
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 20 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,6 @@ use Jenssegers\Mongodb\Eloquent\SoftDeletes;
class User extends Model
{
use SoftDeletes;

protected $dates = ['deleted_at'];
}
```

Expand All @@ -279,7 +277,7 @@ use Jenssegers\Mongodb\Eloquent\Model;

class User extends Model
{
protected $dates = ['birthday'];
protected $casts = ['birthday' => 'datetime'];
}
```

Expand Down
83 changes: 70 additions & 13 deletions src/Eloquent/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,23 @@

namespace Jenssegers\Mongodb\Eloquent;

use function array_key_exists;
use DateTimeInterface;
use function explode;
use Illuminate\Contracts\Queue\QueueableCollection;
use Illuminate\Contracts\Queue\QueueableEntity;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Database\Eloquent\Model as BaseModel;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Str;
use function in_array;
use Jenssegers\Mongodb\Query\Builder as QueryBuilder;
use MongoDB\BSON\Binary;
use MongoDB\BSON\ObjectID;
use MongoDB\BSON\UTCDateTime;
use function uniqid;

abstract class Model extends BaseModel
{
Expand Down Expand Up @@ -94,7 +99,7 @@ public function fromDateTime($value)
$value = parent::asDateTime($value);
}

return new UTCDateTime($value->format('Uv'));
return new UTCDateTime($value);
}

/**
Expand Down Expand Up @@ -191,13 +196,14 @@ public function setAttribute($key, $value)
$value = $builder->convertKey($value);
} // Support keys in dot notation.
elseif (Str::contains($key, '.')) {
if (in_array($key, $this->getDates()) && $value) {
$value = $this->fromDateTime($value);
}
// Store to a temporary key, then move data to the actual key
$uniqueKey = uniqid($key);
parent::setAttribute($uniqueKey, $value);

Arr::set($this->attributes, $key, $value);
Arr::set($this->attributes, $key, $this->attributes[$uniqueKey] ?? null);
unset($this->attributes[$uniqueKey]);

return;
return $this;
}

return parent::setAttribute($key, $value);
Expand All @@ -222,13 +228,6 @@ public function attributesToArray()
}
}

// Convert dot-notation dates.
foreach ($this->getDates() as $key) {
if (Str::contains($key, '.') && Arr::has($attributes, $key)) {
Arr::set($attributes, $key, (string) $this->asDateTime(Arr::get($attributes, $key)));
}
}

return $attributes;
}

Expand Down Expand Up @@ -515,4 +514,62 @@ public function __call($method, $parameters)

return parent::__call($method, $parameters);
}

/**
* Add the casted attributes to the attributes array.
*
* @param array $attributes
* @param array $mutatedAttributes
* @return array
*/
protected function addCastAttributesToArray(array $attributes, array $mutatedAttributes)
{
foreach ($this->getCasts() as $key => $castType) {
if (! Arr::has($attributes, $key) || Arr::has($mutatedAttributes, $key)) {
continue;
}

$originalValue = Arr::get($attributes, $key);

// Here we will cast the attribute. Then, if the cast is a date or datetime cast
// then we will serialize the date for the array. This will convert the dates
// to strings based on the date format specified for these Eloquent models.
$castValue = $this->castAttribute(
$key, $originalValue
);

// If the attribute cast was a date or a datetime, we will serialize the date as
// a string. This allows the developers to customize how dates are serialized
// into an array without affecting how they are persisted into the storage.
if ($castValue !== null && in_array($castType, ['date', 'datetime', 'immutable_date', 'immutable_datetime'])) {
$castValue = $this->serializeDate($castValue);
}

if ($castValue !== null && ($this->isCustomDateTimeCast($castType) ||
$this->isImmutableCustomDateTimeCast($castType))) {
$castValue = $castValue->format(explode(':', $castType, 2)[1]);
}

if ($castValue instanceof DateTimeInterface &&
$this->isClassCastable($key)) {
$castValue = $this->serializeDate($castValue);
}

if ($castValue !== null && $this->isClassSerializable($key)) {
$castValue = $this->serializeClassCastableAttribute($key, $castValue);
}

if ($this->isEnumCastable($key) && (! $castValue instanceof Arrayable)) {
$castValue = $castValue !== null ? $this->getStorableEnumValue($attributes[$key]) : null;
}

if ($castValue instanceof Arrayable) {
$castValue = $castValue->toArray();
}

Arr::set($attributes, $key, $castValue);
}

return $attributes;
}
}
3 changes: 1 addition & 2 deletions tests/ModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -577,8 +577,7 @@ public function testDates(): void
$this->assertInstanceOf(Carbon::class, $user->getAttribute('entry.date'));

$data = $user->toArray();
$this->assertNotInstanceOf(UTCDateTime::class, $data['entry']['date']);
$this->assertEquals((string) $user->getAttribute('entry.date')->format('Y-m-d H:i:s'), $data['entry']['date']);
$this->assertIsString($data['entry']['date']);
}

public function testCarbonDateMockingWorks()
Expand Down
2 changes: 1 addition & 1 deletion tests/models/Soft.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ class Soft extends Eloquent
protected $connection = 'mongodb';
protected $collection = 'soft';
protected static $unguarded = true;
protected $dates = ['deleted_at'];
protected $casts = ['deleted_at' => 'datetime'];
}
5 changes: 4 additions & 1 deletion tests/models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ class User extends Eloquent implements AuthenticatableContract, CanResetPassword
use Notifiable;

protected $connection = 'mongodb';
protected $dates = ['birthday', 'entry.date'];
protected $casts = [
'birthday' => 'datetime',
'entry.date' => 'datetime',
];
protected static $unguarded = true;

public function books()
Expand Down

0 comments on commit 2ea1a7c

Please sign in to comment.