1
1
var Schema = require ( 'mongoose' ) . Schema ;
2
- var _ = require ( 'underscore' ) ;
2
+
3
3
4
4
module . exports = exports = tree ;
5
5
6
+
6
7
/**
7
8
* @class tree
8
9
* Tree Behavior for Mongoose
@@ -14,6 +15,7 @@ module.exports = exports = tree;
14
15
* @param {Object } options
15
16
*/
16
17
function tree ( schema , options ) {
18
+
17
19
var pathSeparator = options && options . pathSeparator || '#'
18
20
, onDelete = options && options . onDelete || 'DELETE' ; //'REPARENT'
19
21
@@ -37,6 +39,7 @@ function tree(schema, options) {
37
39
}
38
40
} ) ;
39
41
42
+
40
43
/**
41
44
* Pre-save middleware
42
45
* Build or rebuild path when needed
@@ -54,6 +57,7 @@ function tree(schema, options) {
54
57
55
58
var self = this ;
56
59
this . collection . findOne ( { _id : this . parent } , function ( err , doc ) {
60
+
57
61
if ( err ) return next ( err ) ;
58
62
59
63
var previousPath = self . path ;
@@ -62,33 +66,40 @@ function tree(schema, options) {
62
66
if ( isParentChange ) {
63
67
// When the parent is changed we must rewrite all children paths as well
64
68
self . collection . find ( { path : { '$regex' : '^' + previousPath + pathSeparator } } , function ( err , cursor ) {
69
+
65
70
if ( err ) return next ( err ) ;
66
71
67
72
var stream = cursor . stream ( ) ;
68
73
stream . on ( 'data' , function ( doc ) {
69
74
var newPath = self . path + doc . path . substr ( previousPath . length ) ;
70
75
self . collection . update ( { _id : doc . _id } , { $set : { path : newPath } } , function ( err ) {
76
+
71
77
if ( err ) return next ( err ) ;
72
78
} ) ;
73
79
} ) ;
80
+
74
81
stream . on ( 'close' , next ) ;
75
82
stream . on ( 'error' , next ) ;
76
83
} ) ;
77
- } else {
84
+ }
85
+ else {
78
86
next ( ) ;
79
87
}
80
88
} ) ;
81
- } else {
89
+ }
90
+ else {
82
91
next ( ) ;
83
92
}
84
93
} ) ;
85
94
95
+
86
96
/**
87
97
* Pre-remove middleware
88
98
*
89
99
* @param {Function } next
90
100
*/
91
101
schema . pre ( 'remove' , function preRemove ( next ) {
102
+
92
103
if ( ! this . path )
93
104
return next ( ) ;
94
105
@@ -102,21 +113,27 @@ function tree(schema, options) {
102
113
103
114
// Update parent property from children
104
115
this . collection . find ( { parent : previousParent } , function ( err , cursor ) {
116
+
105
117
if ( err ) return next ( err ) ;
106
118
var stream = cursor . stream ( ) ;
107
119
stream . on ( 'data' , function streamOnData ( doc ) {
120
+
108
121
self . collection . update ( { _id : doc . _id } , { $set : { parent : newParent } } , function ( err ) {
122
+
109
123
if ( err ) return next ( err ) ;
110
124
} ) ;
111
125
} ) ;
112
126
stream . on ( 'close' , function streamOnClose ( ) {
127
+
113
128
// Cascade update Path
114
129
self . collection . find ( { path : { $regex : previousParent + pathSeparator } } , function ( err , cursor ) {
115
130
116
131
var subStream = cursor . stream ( ) ;
117
132
subStream . on ( 'data' , function subStreamOnData ( doc ) {
133
+
118
134
var newPath = doc . path . replace ( previousParent + pathSeparator , '' ) ;
119
135
self . collection . update ( { _id : doc . _id } , { $set : { path : newPath } } , function ( err ) {
136
+
120
137
if ( err ) return next ( err ) ;
121
138
} ) ;
122
139
} ) ;
@@ -130,80 +147,81 @@ function tree(schema, options) {
130
147
}
131
148
} ) ;
132
149
150
+
133
151
/**
134
152
* @method getChildren
135
153
*
136
- * @param {[type] } recursive
137
- * @param {Function } next
154
+ * @param {Object } args
155
+ * @param {Boolean } recursive
156
+ * @param {Function } next
138
157
* @return {Model }
139
158
*/
140
- schema . methods . getChildren = function getChildren ( recursive , args , next ) {
141
- var queryArgs = null ;
159
+ schema . methods . getChildren = function getChildren ( args , recursive , next ) {
142
160
143
- if ( _ . isFunction ( recursive ) ) {
144
- next = recursive ;
161
+ // normalize the arguments
162
+ if ( "function" === typeof args ) {
163
+ next = args ;
145
164
recursive = false ;
165
+ args = { } ;
146
166
}
147
-
148
- if ( _ . isBoolean ( recursive ) && _ . isFunction ( args ) ) {
149
- next = args ;
167
+ else if ( "function" === typeof recursive ) {
168
+ next = recursive ;
169
+ if ( args instanceof Object ) {
170
+ recursive = false ;
171
+ }
172
+ else {
173
+ recursive = args ;
174
+ args = { } ;
175
+ }
150
176
}
151
177
152
- if ( _ . isObject ( recursive ) ) {
153
- queryArgs = recursive ;
154
- next = args ;
155
- recursive = false ;
178
+ if ( recursive ) {
179
+ args [ 'path' ] = { $regex : '^' + this . path + pathSeparator }
156
180
}
157
-
158
- if ( _ . isBoolean ( recursive ) && _ . isObject ( args ) ) {
159
- queryArgs = args ;
181
+ else {
182
+ args [ 'parent' ] = this . _id
160
183
}
161
184
162
- var filter = recursive ? { path : { $regex : '^' + this . path + pathSeparator } } : { parent : this . _id } ;
163
- if ( queryArgs ) {
164
- filter = _ . extend ( filter , queryArgs ) ;
165
- }
166
- return this . model ( this . constructor . modelName ) . find ( filter , next ) ;
185
+ return this . model ( this . constructor . modelName ) . find ( args , next ) ;
167
186
} ;
168
187
188
+
169
189
/**
170
190
* @method getParent
171
191
*
172
192
* @param {Function } next
173
193
* @return {Model }
174
194
*/
175
195
schema . methods . getParent = function getParent ( next ) {
196
+
176
197
return this . model ( this . constructor . modelName ) . findOne ( { _id : this . parent } , next ) ;
177
198
} ;
178
199
200
+
179
201
/**
180
202
* @method getAncestors
181
203
*
204
+ * @param {Object } args
182
205
* @param {Function } next
183
206
* @return {Model }
184
207
*/
185
208
schema . methods . getAncestors = function getAncestors ( args , next ) {
186
- var queryArgs = null ;
187
209
188
- if ( _ . isFunction ( args ) ) {
210
+ if ( "function" === typeof args ) {
189
211
next = args ;
212
+ args = { } ;
190
213
}
191
214
192
- if ( _ . isObject ( args ) ) {
193
- queryArgs = args ;
194
- }
215
+ var ids = [ ] ;
195
216
196
217
if ( this . path ) {
197
- var ids = this . path . split ( pathSeparator ) ;
218
+ ids = this . path . split ( pathSeparator ) ;
198
219
ids . pop ( ) ;
199
- } else {
200
- var ids = [ ] ;
201
220
}
202
- var filter = { _id : { $in : ids } } ;
203
- if ( queryArgs ) {
204
- filter = _ . extend ( filter , queryArgs ) ;
205
- }
206
- return this . model ( this . constructor . modelName ) . find ( filter , next ) ;
221
+
222
+ args [ '_id' ] = { $in : ids } ;
223
+
224
+ return this . model ( this . constructor . modelName ) . find ( args , next ) ;
207
225
} ;
208
226
209
227
@@ -221,23 +239,23 @@ function tree(schema, options) {
221
239
* @param {Function } next
222
240
* @return {Model }
223
241
*/
224
- schema . statics . getChildrenTree = function getChildrenTree ( root , args , cb ) {
242
+ schema . statics . getChildrenTree = function getChildrenTree ( root , args , next ) {
225
243
226
244
if ( "function" === typeof ( root ) )
227
245
{
228
- cb = root ;
246
+ next = root ;
229
247
root = null ;
230
248
args = { } ;
231
249
}
232
250
else if ( "function" === typeof ( args ) ) {
233
- cb = args
251
+ next = args ;
234
252
235
253
if ( "model" in root ) {
236
254
args = { } ;
237
255
}
238
256
else
239
257
{
240
- args = root
258
+ args = root ;
241
259
root = null
242
260
}
243
261
}
@@ -249,7 +267,7 @@ function tree(schema, options) {
249
267
var recursive = args . recursive != undefined ? args . recursive : true ;
250
268
var allowEmptyChildren = args . allowEmptyChildren != undefined ? args . allowEmptyChildren : true ;
251
269
252
- if ( ! cb )
270
+ if ( ! next )
253
271
throw new Error ( 'no callback defined when calling getChildrenTree' ) ;
254
272
255
273
// filters: Add recursive path filter or not
@@ -284,18 +302,23 @@ function tree(schema, options) {
284
302
}
285
303
286
304
// options:sort , path sort is mandatory
287
- if ( ! options . sort ) options . sort = { } ;
305
+ if ( ! options . sort ) {
306
+ options . sort = { } ;
307
+ }
288
308
options . sort . path = 1 ;
289
309
options . lean = true ;
290
310
291
311
return this . find ( filters , fields , options , function ( err , results ) {
312
+
292
313
if ( err ) throw err ;
293
314
294
315
var getLevel = function ( path ) {
316
+
295
317
return path ? path . split ( pathSeparator ) . length : 0 ;
296
318
} ;
297
319
298
320
var createChildren = function ( arr , node , level ) {
321
+
299
322
if ( level == minLevel ) {
300
323
if ( allowEmptyChildren )
301
324
node . children = [ ] ;
@@ -325,19 +348,23 @@ function tree(schema, options) {
325
348
createChildren ( finalResults , results [ r ] , level ) ;
326
349
}
327
350
328
- cb ( err , finalResults ) ;
351
+ next ( err , finalResults ) ;
329
352
330
353
} ) ;
331
354
} ;
332
355
356
+
333
357
schema . methods . getChildrenTree = function ( args , cb ) {
358
+
334
359
this . constructor . getChildrenTree ( this , args , cb )
335
360
} ;
336
361
362
+
337
363
/**
338
364
* @property {Number } level <virtual>
339
365
*/
340
366
schema . virtual ( 'level' ) . get ( function virtualPropLevel ( ) {
367
+
341
368
return this . path ? this . path . split ( pathSeparator ) . length : 0 ;
342
369
} ) ;
343
370
}
0 commit comments