22
33namespace Kalnoy \Nestedset ;
44
5- use Illuminate \Database \Eloquent \Builder as EloquentBuilder ;
6- use Illuminate \Database \Eloquent \Collection as EloquentCollection ;
75use Illuminate \Database \Eloquent \Model ;
8- use Illuminate \Database \Eloquent \Relations \Relation ;
9- use Illuminate \Database \Query \Builder ;
10- use InvalidArgumentException ;
11- use RuntimeException ;
126
13- class AncestorsRelation extends Relation
7+ class AncestorsRelation extends BaseRelation
148{
15- /**
16- * @var QueryBuilder
17- */
18- protected $ query ;
19-
20- /**
21- * @var NodeTrait|Model
22- */
23- protected $ parent ;
24-
25- /**
26- * AncestorsRelation constructor.
27- *
28- * @param QueryBuilder $builder
29- * @param Model $model
30- */
31- public function __construct (QueryBuilder $ builder , Model $ model )
32- {
33- if ( ! NestedSet::isNode ($ model )) {
34- throw new InvalidArgumentException ('Model must be node. ' );
35- }
36-
37- parent ::__construct ($ builder , $ model );
38- }
39-
40- /**
41- * @param EloquentBuilder $query
42- * @param EloquentBuilder $parentQuery
43- *
44- * @return null
45- */
46- public function getRelationExistenceCountQuery (EloquentBuilder $ query , EloquentBuilder $ parentQuery )
47- {
48- throw new RuntimeException ('Cannot count ancestors, use depth functionality instead ' );
49- }
50-
51- /**
52- * @param EloquentBuilder $query
53- * @param EloquentBuilder $parent
54- * @param array $columns
55- *
56- * @return mixed
57- */
58- public function getRelationExistenceQuery (EloquentBuilder $ query , EloquentBuilder $ parent ,
59- $ columns = [ '* ' ]
60- ) {
61- $ query ->select ($ columns );
62-
63- $ table = $ query ->getModel ()->getTable ();
64-
65- $ query ->from ($ table .' as ' .$ hash = $ this ->getRelationSubSelectHash ());
66-
67- $ grammar = $ query ->getQuery ()->getGrammar ();
68-
69- $ table = $ grammar ->wrapTable ($ table );
70- $ hash = $ grammar ->wrapTable ($ hash );
71- $ parentIdName = $ grammar ->wrap ($ this ->parent ->getParentIdName ());
72-
73- return $ query ->whereRaw ("{$ hash }. {$ parentIdName } = {$ table }. {$ parentIdName }" );
74- }
75-
76- /**
77- * @param EloquentBuilder $query
78- * @param EloquentBuilder $parent
79- * @param array $columns
80- *
81- * @return mixed
82- */
83- public function getRelationQuery (
84- EloquentBuilder $ query , EloquentBuilder $ parent ,
85- $ columns = [ '* ' ]
86- ) {
87- return $ this ->getRelationExistenceQuery ($ query , $ parent , $ columns );
88- }
89-
90- /**
91- * Get a relationship join table hash.
92- *
93- * @return string
94- */
95- public function getRelationSubSelectHash ()
96- {
97- return 'self_ ' .md5 (microtime (true ));
98- }
99-
1009 /**
10110 * Set the base constraints on the relation query.
10211 *
@@ -110,95 +19,39 @@ public function addConstraints()
11019 }
11120
11221 /**
113- * Set the constraints for an eager load of the relation.
114- *
115- * @param array $models
116- *
117- * @return void
118- */
119- public function addEagerConstraints (array $ models )
120- {
121- $ model = $ this ->query ->getModel ();
122- $ table = $ model ->getTable ();
123- $ key = $ model ->getKeyName ();
124-
125- $ grammar = $ this ->query ->getQuery ()->getGrammar ();
126-
127- $ table = $ grammar ->wrapTable ($ table );
128- $ hash = $ grammar ->wrap ($ this ->getRelationSubSelectHash ());
129- $ key = $ grammar ->wrap ($ key );
130- $ lft = $ grammar ->wrap ($ this ->parent ->getLftName ());
131- $ rgt = $ grammar ->wrap ($ this ->parent ->getRgtName ());
132-
133- $ sql = "$ key IN (SELECT DISTINCT( $ key) FROM {$ table } INNER JOIN "
134- . "(SELECT {$ lft }, {$ rgt } FROM {$ table } WHERE {$ key } IN ( " . implode (', ' , $ this ->getKeys ($ models ))
135- . ")) AS $ hash ON {$ table }. {$ lft } <= {$ hash }. {$ lft } AND {$ table }. {$ rgt } >= {$ hash }. {$ rgt }) " ;
136-
137- $ this ->query ->whereNested (function (Builder $ inner ) use ($ sql ) {
138- $ inner ->whereRaw ($ sql );
139- });
140- $ this ->query ->orderBy ($ this ->parent ->getLftName (), 'ASC ' );
141- }
142-
143- /**
144- * Initialize the relation on a set of models.
145- *
146- * @param array $models
147- * @param string $relation
148- *
149- * @return array
150- */
151- public function initRelation (array $ models , $ relation )
152- {
153- return $ models ;
154- }
155-
156- /**
157- * Match the eagerly loaded results to their parents.
158- *
159- * @param array $models
160- * @param EloquentCollection $results
161- * @param string $relation
22+ * @param Model $model
23+ * @param $related
16224 *
163- * @return array
25+ * @return bool
16426 */
165- public function match ( array $ models , EloquentCollection $ results , $ relation )
27+ protected function matches ( Model $ model , $ related )
16628 {
167- foreach ($ models as $ model ) {
168- $ ancestors = $ this ->getAncestorsForModel ($ model , $ results );
169-
170- $ model ->setRelation ($ relation , $ ancestors );
171- }
172-
173- return $ models ;
29+ return $ related ->isAncestorOf ($ model );
17430 }
17531
17632 /**
177- * Get the results of the relationship.
33+ * @param QueryBuilder $query
34+ * @param Model $model
17835 *
179- * @return mixed
36+ * @return void
18037 */
181- public function getResults ( )
38+ protected function addEagerConstraint ( $ query , $ model )
18239 {
183- return $ this -> query ->get ( );
40+ $ query ->orWhereAncestorOf ( $ model );
18441 }
18542
18643 /**
187- * @param Model $model
188- * @param EloquentCollection $results
44+ * @param $hash
45+ * @param $table
46+ * @param $lft
47+ * @param $rgt
18948 *
190- * @return Collection
49+ * @return string
19150 */
192- protected function getAncestorsForModel ( Model $ model , EloquentCollection $ results )
51+ protected function relationExistenceCondition ( $ hash , $ table , $ lft , $ rgt )
19352 {
194- $ result = $ this ->related ->newCollection ();
195-
196- foreach ($ results as $ ancestor ) {
197- if ($ ancestor ->isAncestorOf ($ model )) {
198- $ result ->push ($ ancestor );
199- }
200- }
53+ $ key = $ this ->getBaseQuery ()->getGrammar ()->wrap ($ this ->parent ->getKeyName ());
20154
202- return $ result ;
55+ return "{ $ table } . { $ rgt } between { $ hash } . { $ lft } and { $ hash } . { $ rgt } and $ table . $ key <> $ hash . $ key " ;
20356 }
20457}
0 commit comments