33namespace ProAI \Inheritance ;
44
55use Illuminate \Support \Str ;
6+ use Exception ;
67
78trait Inheritance
89{
@@ -20,14 +21,35 @@ trait Inheritance
2021 */
2122 public static $ inheritanceType ;
2223
24+ /**
25+ * Create a new Eloquent model instance.
26+ *
27+ * @param array $attributes
28+ * @return void
29+ */
30+ public function __construct (array $ attributes = [])
31+ {
32+ $ type = $ attributes [static ::$ inheritanceColumn ] ?? null ;
33+
34+ if (static ::isRootModel () && $ type ) {
35+ [$ one , $ caller ] = debug_backtrace (DEBUG_BACKTRACE_IGNORE_ARGS , 2 );
36+
37+ if (! isset ($ caller ['class ' ]) || ! $ caller ['class ' ] || ! $ this instanceof $ caller ['class ' ]) {
38+ throw new Exception ('Model cannot be instantiated. Please use ' .static ::class.'::new instead. ' );
39+ }
40+ }
41+
42+ parent ::__construct ($ attributes );
43+ }
44+
2345 /**
2446 * Bootstrap the inheritance trait.
2547 *
2648 * @return void
2749 */
2850 protected static function bootInheritance ()
2951 {
30- if (! static ::modelInherited ()) {
52+ if (static ::isRootModel ()) {
3153 return ;
3254 }
3355
@@ -41,13 +63,13 @@ protected static function bootInheritance()
4163 }
4264
4365 /**
44- * Check if model is inherited .
66+ * Check if model is root model .
4567 *
4668 * @return bool
4769 */
48- protected static function modelInherited ()
70+ protected static function isRootModel ()
4971 {
50- return self ::class ! == static ::class;
72+ return self ::class = == static ::class;
5173 }
5274
5375 /**
@@ -61,7 +83,88 @@ protected static function getInheritanceType()
6183 return static ::$ inheritanceType ;
6284 }
6385
64- return static ::$ inheritanceType = static ::class;
86+ $ class = static ::class;
87+ $ flippedMap = array_flip (static ::$ inheritanceMap ?? []);
88+
89+ if (isset ($ flippedMap [$ class ])) {
90+ $ type = $ flippedMap [$ class ];
91+ } else {
92+ $ type = $ class ;
93+ }
94+
95+ return static ::$ inheritanceType = $ type ;
96+ }
97+
98+ /**
99+ * Create a new instance of the model by type.
100+ *
101+ * @param array $attributes
102+ * @return static
103+ */
104+ public static function new ($ attributes = [])
105+ {
106+ $ class = static ::getChildClass ($ attributes );
107+
108+ if ($ class ) {
109+ return new $ class ($ attributes );
110+ }
111+
112+ return new static ($ attributes );
113+ }
114+
115+ /**
116+ * Create a new instance of the model by type.
117+ *
118+ * @param array $attributes
119+ * @param bool $exists
120+ * @return static
121+ */
122+ public function newInstance ($ attributes = [], $ exists = false )
123+ {
124+ $ class = static ::getChildClass ($ attributes );
125+
126+ // This method just provides a convenient way for us to generate fresh model
127+ // instances of this current model. It is particularly useful during the
128+ // hydration of new objects via the Eloquent query builder instances.
129+ $ model = $ class ? new $ class : new static ;
130+
131+ $ model ->exists = $ exists ;
132+
133+ $ model ->setConnection (
134+ $ this ->getConnectionName ()
135+ );
136+
137+ $ model ->setTable ($ this ->getTable ());
138+
139+ $ model ->mergeCasts ($ this ->casts );
140+
141+ $ model ->fill ((array ) $ attributes );
142+
143+ return $ model ;
144+ }
145+
146+ /**
147+ * Create a new model instance that is existing.
148+ *
149+ * @param array $attributes
150+ * @param string|null $connection
151+ * @return static
152+ */
153+ public function newFromBuilder ($ attributes = [], $ connection = null )
154+ {
155+ $ attributes = (array ) $ attributes ;
156+
157+ $ type = $ attributes [static ::$ inheritanceColumn ] ?? null ;
158+
159+ $ model = $ this ->newInstance ([static ::$ inheritanceColumn => $ type ], true );
160+
161+ $ model ->setRawAttributes ($ attributes , true );
162+
163+ $ model ->setConnection ($ connection ?: $ this ->getConnectionName ());
164+
165+ $ model ->fireModelEvent ('retrieved ' , false );
166+
167+ return $ model ;
65168 }
66169
67170 /**
@@ -93,4 +196,29 @@ protected function getRootClass()
93196 {
94197 return self ::class;
95198 }
199+
200+ /**
201+ * Get the class name of the child class.
202+ *
203+ * @param array $attributes
204+ * @return ?string
205+ */
206+ protected static function getChildClass ($ attributes )
207+ {
208+ if (! static ::isRootModel ()) {
209+ return null ;
210+ }
211+
212+ if (! isset ($ attributes [static ::$ inheritanceColumn ])) {
213+ return null ;
214+ }
215+
216+ $ type = $ attributes [static ::$ inheritanceColumn ];
217+
218+ if (! isset (static ::$ inheritanceMap )) {
219+ return $ type ;
220+ }
221+
222+ return static ::$ inheritanceMap [$ type ] ?? $ type ;
223+ }
96224}
0 commit comments