77use Illuminate \Database \Eloquent \Model as Eloquent ;
88use Illuminate \Database \Eloquent \Relations \BelongsTo ;
99use Illuminate \Database \Eloquent \Relations \HasMany ;
10+ use Illuminate \Database \Eloquent \Relations \HasOne ;
1011use Illuminate \Database \Eloquent \SoftDeletes ;
1112use Franzose \ClosureTable \Scope \Ancestor ;
1213use Franzose \ClosureTable \Scope \DirectChild ;
2324 * However, if you named, for example, the position column to be "pos",
2425 * remember you can get its value either by $this->pos or $this->position.
2526 *
26- * @property int position Alias for the current position attribute name
27+ * @property int|null position Alias for the current position attribute name
2728 * @property mixed parent_id Alias for the direct ancestor identifier attribute name
29+ * @property int|null depth Current node depth
2830 * @property EntityCollection children Child nodes loaded from the database
2931 */
3032class Entity extends Eloquent
@@ -35,6 +37,7 @@ class Entity extends Eloquent
3537 use DirectChild;
3638 use Sibling;
3739
40+ private const DEPTH_RELATION_NAME = 'closureDepth ' ;
3841 public const CHILDREN_RELATION_NAME = 'children ' ;
3942
4043 /**
@@ -69,6 +72,15 @@ class Entity extends Eloquent
6972 */
7073 public $ timestamps = false ;
7174
75+ /**
76+ * The relations to eager load on every query.
77+ *
78+ * @var string[]
79+ */
80+ protected $ with = [
81+ self ::DEPTH_RELATION_NAME ,
82+ ];
83+
7284 /**
7385 * Entity constructor.
7486 */
@@ -182,6 +194,42 @@ public function getPositionColumn(): string
182194 return 'position ' ;
183195 }
184196
197+ /**
198+ * Returns the closure row with the max depth for the current node.
199+ *
200+ * @internal
201+ */
202+ public function closureDepth (): HasOne
203+ {
204+ $ relatedClass = get_class ($ this ->closure );
205+ $ descendantColumn = $ this ->closure ->getDescendantColumn ();
206+ $ depthColumn = $ this ->closure ->getDepthColumn ();
207+
208+ $ relation = $ this ->hasOne ($ relatedClass , $ descendantColumn , $ this ->getKeyName ());
209+ $ relation ->getRelated ()->setTable ($ this ->closure ->getTable ());
210+
211+ return $ relation ->ofMany ($ depthColumn , 'max ' );
212+ }
213+
214+ /**
215+ * Gets the current node depth.
216+ */
217+ public function getDepthAttribute (): ?int
218+ {
219+ if (!$ this ->exists ) {
220+ return null ;
221+ }
222+
223+ if ($ this ->relationLoaded (static ::DEPTH_RELATION_NAME )) {
224+ $ depth = $ this ->getRelation (static ::DEPTH_RELATION_NAME )?->getAttribute($ this ->closure ->getDepthColumn ());
225+ return $ depth !== null ? (int ) $ depth : 0 ;
226+ }
227+
228+ $ depth = $ this ->closureDepth ()->value ($ this ->closure ->getDepthColumn ());
229+
230+ return $ depth !== null ? (int ) $ depth : 0 ;
231+ }
232+
185233 /**
186234 * Checks if the current model table has the given column.
187235 */
0 commit comments