22
33namespace Jenssegers \Mongodb \Eloquent ;
44
5+ use function array_key_exists ;
56use DateTimeInterface ;
7+ use function explode ;
68use Illuminate \Contracts \Queue \QueueableCollection ;
79use Illuminate \Contracts \Queue \QueueableEntity ;
10+ use Illuminate \Contracts \Support \Arrayable ;
811use Illuminate \Database \Eloquent \Model as BaseModel ;
912use Illuminate \Database \Eloquent \Relations \Relation ;
1013use Illuminate \Support \Arr ;
1114use Illuminate \Support \Facades \Date ;
1215use Illuminate \Support \Str ;
16+ use function in_array ;
1317use Jenssegers \Mongodb \Query \Builder as QueryBuilder ;
1418use MongoDB \BSON \Binary ;
1519use MongoDB \BSON \ObjectID ;
1620use MongoDB \BSON \UTCDateTime ;
21+ use function uniqid ;
1722
1823abstract class Model extends BaseModel
1924{
@@ -94,7 +99,7 @@ public function fromDateTime($value)
9499 $ value = parent ::asDateTime ($ value );
95100 }
96101
97- return new UTCDateTime ($ value-> format ( ' Uv ' ) );
102+ return new UTCDateTime ($ value );
98103 }
99104
100105 /**
@@ -182,7 +187,7 @@ protected function getAttributeFromArray($key)
182187 /**
183188 * @inheritdoc
184189 */
185- public function setAttribute ($ key , $ value )
190+ public function setAttribute ($ key , $ value ): static
186191 {
187192 // Convert _id to ObjectID.
188193 if ($ key == '_id ' && is_string ($ value )) {
@@ -191,13 +196,14 @@ public function setAttribute($key, $value)
191196 $ value = $ builder ->convertKey ($ value );
192197 } // Support keys in dot notation.
193198 elseif (Str::contains ($ key , '. ' )) {
194- if ( in_array ( $ key , $ this -> getDates ()) && $ value ) {
195- $ value = $ this -> fromDateTime ( $ value );
196- }
199+ // Store to a temporary key, then move data to the actual key
200+ $ uniqueKey = uniqid ( $ key );
201+ parent :: setAttribute ( $ uniqueKey , $ value );
197202
198- Arr::set ($ this ->attributes , $ key , $ value );
203+ Arr::set ($ this ->attributes , $ key , $ this ->attributes [$ uniqueKey ] ?? null );
204+ unset($ this ->attributes [$ uniqueKey ]);
199205
200- return ;
206+ return $ this ;
201207 }
202208
203209 return parent ::setAttribute ($ key , $ value );
@@ -222,13 +228,6 @@ public function attributesToArray()
222228 }
223229 }
224230
225- // Convert dot-notation dates.
226- foreach ($ this ->getDates () as $ key ) {
227- if (Str::contains ($ key , '. ' ) && Arr::has ($ attributes , $ key )) {
228- Arr::set ($ attributes , $ key , (string ) $ this ->asDateTime (Arr::get ($ attributes , $ key )));
229- }
230- }
231-
232231 return $ attributes ;
233232 }
234233
@@ -515,4 +514,58 @@ public function __call($method, $parameters)
515514
516515 return parent ::__call ($ method , $ parameters );
517516 }
517+
518+ /**
519+ * @inheritdoc
520+ */
521+ protected function addCastAttributesToArray (array $ attributes , array $ mutatedAttributes ): array
522+ {
523+ foreach ($ this ->getCasts () as $ key => $ castType ) {
524+ if (! Arr::has ($ attributes , $ key ) || Arr::has ($ mutatedAttributes , $ key )) {
525+ continue ;
526+ }
527+
528+ $ originalValue = Arr::get ($ attributes , $ key );
529+
530+ // Here we will cast the attribute. Then, if the cast is a date or datetime cast
531+ // then we will serialize the date for the array. This will convert the dates
532+ // to strings based on the date format specified for these Eloquent models.
533+ $ castValue = $ this ->castAttribute (
534+ $ key , $ originalValue
535+ );
536+
537+ // If the attribute cast was a date or a datetime, we will serialize the date as
538+ // a string. This allows the developers to customize how dates are serialized
539+ // into an array without affecting how they are persisted into the storage.
540+ if ($ castValue !== null && in_array ($ castType , ['date ' , 'datetime ' , 'immutable_date ' , 'immutable_datetime ' ])) {
541+ $ castValue = $ this ->serializeDate ($ castValue );
542+ }
543+
544+ if ($ castValue !== null && ($ this ->isCustomDateTimeCast ($ castType ) ||
545+ $ this ->isImmutableCustomDateTimeCast ($ castType ))) {
546+ $ castValue = $ castValue ->format (explode (': ' , $ castType , 2 )[1 ]);
547+ }
548+
549+ if ($ castValue instanceof DateTimeInterface &&
550+ $ this ->isClassCastable ($ key )) {
551+ $ castValue = $ this ->serializeDate ($ castValue );
552+ }
553+
554+ if ($ castValue !== null && $ this ->isClassSerializable ($ key )) {
555+ $ castValue = $ this ->serializeClassCastableAttribute ($ key , $ castValue );
556+ }
557+
558+ if ($ this ->isEnumCastable ($ key ) && (! $ castValue instanceof Arrayable)) {
559+ $ castValue = $ castValue !== null ? $ this ->getStorableEnumValue ($ attributes [$ key ]) : null ;
560+ }
561+
562+ if ($ castValue instanceof Arrayable) {
563+ $ castValue = $ castValue ->toArray ();
564+ }
565+
566+ Arr::set ($ attributes , $ key , $ castValue );
567+ }
568+
569+ return $ attributes ;
570+ }
518571}
0 commit comments