3030use CodeIgniter \Entity \Cast \URICast ;
3131use CodeIgniter \Entity \Exceptions \CastException ;
3232use CodeIgniter \I18n \Time ;
33- use DateTime ;
3433use DateTimeInterface ;
3534use Exception ;
3635use JsonSerializable ;
@@ -79,14 +78,14 @@ class Entity implements JsonSerializable
7978 protected $ casts = [];
8079
8180 /**
82- * Custom convert handlers
81+ * Custom convert handlers.
8382 *
8483 * @var array<string, string>
8584 */
8685 protected $ castHandlers = [];
8786
8887 /**
89- * Default convert handlers
88+ * Default convert handlers.
9089 *
9190 * @var array<string, string>
9291 */
@@ -128,29 +127,26 @@ class Entity implements JsonSerializable
128127 /**
129128 * The data caster.
130129 */
131- protected DataCaster $ dataCaster ;
130+ protected ? DataCaster $ dataCaster = null ;
132131
133132 /**
134- * Holds info whenever properties have to be casted
133+ * Holds info whenever properties have to be casted.
135134 */
136135 private bool $ _cast = true ;
137136
138137 /**
139- * Indicates whether all attributes are scalars (for optimization)
138+ * Indicates whether all attributes are scalars (for optimization).
140139 */
141140 private bool $ _onlyScalars = true ;
142141
143142 /**
144143 * Allows filling in Entity parameters during construction.
144+ *
145+ * @param array<string, mixed> $data
145146 */
146147 public function __construct (?array $ data = null )
147148 {
148- $ this ->dataCaster = new DataCaster (
149- array_merge ($ this ->defaultCastHandlers , $ this ->castHandlers ),
150- null ,
151- null ,
152- false ,
153- );
149+ $ this ->dataCaster = $ this ->dataCaster ();
154150
155151 $ this ->syncOriginal ();
156152
@@ -162,7 +158,7 @@ public function __construct(?array $data = null)
162158 * properties, using any `setCamelCasedProperty()` methods
163159 * that may or may not exist.
164160 *
165- * @param array<string, array|bool|float|int|object|string|null> $data
161+ * @param array<string, array<int|string, mixed> |bool|float|int|object|string|null> $data
166162 *
167163 * @return $this
168164 */
@@ -184,13 +180,16 @@ public function fill(?array $data = null)
184180 * of this entity as an array. All values are accessed through the
185181 * __get() magic method so will have any casts, etc applied to them.
186182 *
187- * @param bool $onlyChanged If true, only return values that have changed since object creation
183+ * @param bool $onlyChanged If true, only return values that have changed since object creation.
188184 * @param bool $cast If true, properties will be cast.
189185 * @param bool $recursive If true, inner entities will be cast as array as well.
186+ *
187+ * @return array<string, mixed>
190188 */
191189 public function toArray (bool $ onlyChanged = false , bool $ cast = true , bool $ recursive = false ): array
192190 {
193- $ this ->_cast = $ cast ;
191+ $ originalCast = $ this ->_cast ;
192+ $ this ->_cast = $ cast ;
194193
195194 $ keys = array_filter (array_keys ($ this ->attributes ), static fn ($ key ): bool => ! str_starts_with ($ key , '_ ' ));
196195
@@ -219,16 +218,18 @@ public function toArray(bool $onlyChanged = false, bool $cast = true, bool $recu
219218 }
220219 }
221220
222- $ this ->_cast = true ;
221+ $ this ->_cast = $ originalCast ;
223222
224223 return $ return ;
225224 }
226225
227226 /**
228227 * Returns the raw values of the current attributes.
229228 *
230- * @param bool $onlyChanged If true, only return values that have changed since object creation
229+ * @param bool $onlyChanged If true, only return values that have changed since object creation.
231230 * @param bool $recursive If true, inner entities will be cast as array as well.
231+ *
232+ * @return array<string, mixed>
232233 */
233234 public function toRawArray (bool $ onlyChanged = false , bool $ recursive = false ): array
234235 {
@@ -370,8 +371,6 @@ public function syncOriginal()
370371 * Checks a property to see if it has changed since the entity
371372 * was created. Or, without a parameter, checks if any
372373 * properties have changed.
373- *
374- * @param string|null $key class property
375374 */
376375 public function hasChanged (?string $ key = null ): bool
377376 {
@@ -500,7 +499,9 @@ private function normalizeValue(mixed $data): mixed
500499 }
501500
502501 /**
503- * Set raw data array without any mutations
502+ * Set raw data array without any mutations.
503+ *
504+ * @param array<string, mixed> $data
504505 *
505506 * @return $this
506507 */
@@ -513,42 +514,30 @@ public function injectRawData(array $data)
513514 return $ this ;
514515 }
515516
516- /**
517- * Set raw data array without any mutations
518- *
519- * @return $this
520- *
521- * @deprecated Use injectRawData() instead.
522- */
523- public function setAttributes (array $ data )
524- {
525- return $ this ->injectRawData ($ data );
526- }
527-
528517 /**
529518 * Checks the datamap to see if this property name is being mapped,
530- * and returns the db column name, if any, or the original property name.
519+ * and returns the DB column name, if any, or the original property name.
531520 *
532- * @return string db column name
521+ * @return string Database column name.
533522 */
534523 protected function mapProperty (string $ key )
535524 {
536525 if ($ this ->datamap === []) {
537526 return $ key ;
538527 }
539528
540- if (! empty ( $ this ->datamap [$ key ]) ) {
529+ if (array_key_exists ( $ key , $ this ->datamap ) && $ this -> datamap [$ key ] !== '' ) {
541530 return $ this ->datamap [$ key ];
542531 }
543532
544533 return $ key ;
545534 }
546535
547536 /**
548- * Converts the given string|timestamp|DateTime|Time instance
537+ * Converts the given string|timestamp|DateTimeInterface instance
549538 * into the "CodeIgniter\I18n\Time" object.
550539 *
551- * @param DateTime |float|int|string|Time $value
540+ * @param DateTimeInterface |float|int|string $value
552541 *
553542 * @return Time
554543 *
@@ -568,22 +557,50 @@ protected function mutateDate($value)
568557 * @param string $attribute Attribute name
569558 * @param string $method Allowed to "get" and "set"
570559 *
571- * @return array|bool|float|int|object|string|null
560+ * @return array<int|string, mixed> |bool|float|int|object|string|null
572561 *
573562 * @throws CastException
574563 */
575564 protected function castAs ($ value , string $ attribute , string $ method = 'get ' )
576565 {
577- return $ this ->dataCaster
578- // @TODO if $casts is readonly, we don't need the setTypes() method.
579- ->setTypes ($ this ->casts )
580- ->castAs ($ value , $ attribute , $ method );
566+ if ($ this ->dataCaster () instanceof DataCaster) {
567+ return $ this ->dataCaster
568+ // @TODO if $casts is readonly, we don't need the setTypes() method.
569+ ->setTypes ($ this ->casts )
570+ ->castAs ($ value , $ attribute , $ method );
571+ }
572+
573+ return $ value ;
574+ }
575+
576+ /**
577+ * Returns a DataCaster instance when casts are defined.
578+ * If no casts are configured, no DataCaster is created and null is returned.
579+ */
580+ protected function dataCaster (): ?DataCaster
581+ {
582+ if ($ this ->casts === []) {
583+ $ this ->dataCaster = null ;
584+
585+ return null ;
586+ }
587+
588+ if (! $ this ->dataCaster instanceof DataCaster) {
589+ $ this ->dataCaster = new DataCaster (
590+ array_merge ($ this ->defaultCastHandlers , $ this ->castHandlers ),
591+ null ,
592+ null ,
593+ false ,
594+ );
595+ }
596+
597+ return $ this ->dataCaster ;
581598 }
582599
583600 /**
584- * Support for json_encode()
601+ * Support for json_encode().
585602 *
586- * @return array
603+ * @return array<string, mixed>
587604 */
588605 #[ReturnTypeWillChange]
589606 public function jsonSerialize ()
@@ -592,7 +609,7 @@ public function jsonSerialize()
592609 }
593610
594611 /**
595- * Change the value of the private $_cast property
612+ * Change the value of the private $_cast property.
596613 *
597614 * @return bool|Entity
598615 */
@@ -616,7 +633,7 @@ public function cast(?bool $cast = null)
616633 * $this->my_property = $p;
617634 * $this->setMyProperty() = $p;
618635 *
619- * @param array|bool|float|int|object|string|null $value
636+ * @param array<int|string, mixed> |bool|float|int|object|string|null $value
620637 *
621638 * @return void
622639 *
@@ -646,7 +663,7 @@ public function __set(string $key, $value = null)
646663 }
647664
648665 // If a "`set` + $key" method exists, it is also a setter.
649- if (method_exists ($ this , $ method ) && $ method !== ' setAttributes ' ) {
666+ if (method_exists ($ this , $ method )) {
650667 $ this ->{$ method }($ value );
651668
652669 return ;
@@ -667,11 +684,9 @@ public function __set(string $key, $value = null)
667684 * $p = $this->my_property
668685 * $p = $this->getMyProperty()
669686 *
670- * @return array|bool|float|int|object|string|null
687+ * @return array<int|string, mixed> |bool|float|int|object|string|null
671688 *
672689 * @throws Exception
673- *
674- * @params string $key class property
675690 */
676691 public function __get (string $ key )
677692 {
0 commit comments