33namespace Elasticquent ;
44
55use Exception ;
6+ use Illuminate \Database \Eloquent \Model ;
7+ use Illuminate \Database \Eloquent \Relations \Relation ;
68
79/**
810 * Elasticquent Trait
@@ -583,11 +585,10 @@ public static function typeExists()
583585 */
584586 public function newFromHitBuilder ($ hit = array ())
585587 {
586- $ instance = $ this ->newInstance (array (), true );
587- $ keyname = $ instance ->getKeyName ();
588+ $ keyname = $ this ->getKeyName ();
588589
589- $ attributes = $ hit ['_source ' ];
590- $ attributes [$ keyname ] = $ hit ['_id ' ];
590+ $ attributes = $ hit ['_source ' ];
591+ $ attributes [$ keyname ] = is_numeric ( $ hit [ ' _id ' ]) ? intval ( $ hit [ ' _id ' ]) : $ hit ['_id ' ];
591592
592593 // Add fields to attributes
593594 if (isset ($ hit ['fields ' ])) {
@@ -596,7 +597,7 @@ public function newFromHitBuilder($hit = array())
596597 }
597598 }
598599
599- $ instance-> setRawAttributes (( array ) $ attributes , true );
600+ $ instance = $ this :: newFromBuilderRecursive ( $ this , $ attributes );
600601
601602 // In addition to setting the attributes
602603 // from the index, we will set the score as well.
@@ -614,4 +615,107 @@ public function newFromHitBuilder($hit = array())
614615 return $ instance ;
615616 }
616617
618+ /**
619+ * Create a new model instance that is existing recursive.
620+ *
621+ * @param \Illuminate\Database\Eloquent\Model $model
622+ * @param array $attributes
623+ * @param \Illuminate\Database\Eloquent\Relation $parentRelation
624+ * @return static
625+ */
626+ public static function newFromBuilderRecursive (Model $ model , array $ attributes = [], Relation $ parentRelation = null )
627+ {
628+ $ instance = $ model ->newInstance ([], $ exists = true );
629+
630+ $ instance ->setRawAttributes ((array )$ attributes , $ sync = true );
631+
632+ // Load relations recursive
633+ static ::loadRelationsAttributesRecursive ($ instance );
634+ // Load pivot
635+ static ::loadPivotAttribute ($ instance , $ parentRelation );
636+
637+ return $ instance ;
638+ }
639+
640+ /**
641+ * Create a collection of models from plain arrays recursive.
642+ *
643+ * @param \Illuminate\Database\Eloquent\Model $model
644+ * @param \Illuminate\Database\Eloquent\Relation $parentRelation
645+ * @param array $items
646+ * @return \Illuminate\Database\Eloquent\Collection
647+ */
648+ public static function hydrateRecursive (Model $ model , array $ items , Relation $ parentRelation = null )
649+ {
650+ $ instance = $ model ;
651+
652+ $ items = array_map (function ($ item ) use ($ instance , $ parentRelation ) {
653+ return static ::newFromBuilderRecursive ($ instance , $ item , $ parentRelation );
654+ }, $ items );
655+
656+ return $ instance ->newCollection ($ items );
657+ }
658+
659+ /**
660+ * Get the relations attributes from a model.
661+ *
662+ * @param \Illuminate\Database\Eloquent\Model $model
663+ */
664+ public static function loadRelationsAttributesRecursive (Model $ model )
665+ {
666+ $ attributes = $ model ->getAttributes ();
667+
668+ foreach ($ attributes as $ key => $ value ) {
669+ if (method_exists ($ model , $ key )) {
670+ $ relation = $ model ->$ key ();
671+ if ($ relation instanceof Relation) {
672+ // Check if the relation field is single model or collections
673+ if (!static ::isMultiLevelArray ($ value )) {
674+ $ value = [$ value ];
675+ }
676+ $ models = static ::hydrateRecursive ($ relation ->getModel (), $ value , $ relation );
677+ // Unset attribute before match relation
678+ unset($ model [$ key ]);
679+ $ relation ->match ([$ model ], $ models , $ key );
680+ }
681+ }
682+ }
683+ }
684+
685+ /**
686+ * Get the pivot attribute from a model.
687+ *
688+ * @param \Illuminate\Database\Eloquent\Model $model
689+ * @param \Illuminate\Database\Eloquent\Relation $parentRelation
690+ */
691+ public static function loadPivotAttribute (Model $ model , Relation $ parentRelation = null )
692+ {
693+ $ attributes = $ model ->getAttributes ();
694+
695+ foreach ($ attributes as $ key => $ value ) {
696+ if ($ key === 'pivot ' ) {
697+ unset($ model [$ key ]);
698+ $ pivot = $ parentRelation ->newExistingPivot ($ value );
699+ $ model ->setRelation ($ key , $ pivot );
700+ }
701+ }
702+ }
703+
704+ /**
705+ * Check if an array is multi-level array like [[id], [id], [id]].
706+ *
707+ * For detect if a relation field is single model or collections.
708+ *
709+ * @param array $array
710+ * @return boolean
711+ */
712+ private static function isMultiLevelArray (array $ array )
713+ {
714+ foreach ($ array as $ key => $ value ) {
715+ if (!is_array ($ value )) {
716+ return false ;
717+ }
718+ }
719+ return true ;
720+ }
617721}
0 commit comments