2
2
3
3
namespace Kalnoy \Nestedset ;
4
4
5
- use Illuminate \Database \Eloquent \Builder as EloquentBuilder ;
6
- use Illuminate \Database \Eloquent \Collection as EloquentCollection ;
7
5
use Illuminate \Database \Eloquent \Model ;
8
- use Illuminate \Database \Eloquent \Relations \Relation ;
9
- use Illuminate \Database \Query \Builder ;
10
- use InvalidArgumentException ;
11
- use RuntimeException ;
12
6
13
- class AncestorsRelation extends Relation
7
+ class AncestorsRelation extends BaseRelation
14
8
{
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
-
100
9
/**
101
10
* Set the base constraints on the relation query.
102
11
*
@@ -110,95 +19,39 @@ public function addConstraints()
110
19
}
111
20
112
21
/**
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
162
24
*
163
- * @return array
25
+ * @return bool
164
26
*/
165
- public function match ( array $ models , EloquentCollection $ results , $ relation )
27
+ protected function matches ( Model $ model , $ related )
166
28
{
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 );
174
30
}
175
31
176
32
/**
177
- * Get the results of the relationship.
33
+ * @param QueryBuilder $query
34
+ * @param Model $model
178
35
*
179
- * @return mixed
36
+ * @return void
180
37
*/
181
- public function getResults ( )
38
+ protected function addEagerConstraint ( $ query , $ model )
182
39
{
183
- return $ this -> query ->get ( );
40
+ $ query ->orWhereAncestorOf ( $ model );
184
41
}
185
42
186
43
/**
187
- * @param Model $model
188
- * @param EloquentCollection $results
44
+ * @param $hash
45
+ * @param $table
46
+ * @param $lft
47
+ * @param $rgt
189
48
*
190
- * @return Collection
49
+ * @return string
191
50
*/
192
- protected function getAncestorsForModel ( Model $ model , EloquentCollection $ results )
51
+ protected function relationExistenceCondition ( $ hash , $ table , $ lft , $ rgt )
193
52
{
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 ());
201
54
202
- return $ result ;
55
+ return "{ $ table } . { $ rgt } between { $ hash } . { $ lft } and { $ hash } . { $ rgt } and $ table . $ key <> $ hash . $ key " ;
203
56
}
204
57
}
0 commit comments