cloudcms-server 4.0.0-beta.2 → 4.0.0-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -5
- package/cloudcms-server.iml +1 -0
- package/index.js +58 -32
- package/middleware/authentication/authentication.js +40 -12
- package/middleware/authentication/providers/saml.js +8 -4
- package/middleware/awareness/awareness.js +8 -7
- package/middleware/awareness/plugins/api_event.js +105 -0
- package/middleware/awareness/plugins/editorial.js +54 -3
- package/middleware/awareness/plugins/resources.js +13 -5
- package/middleware/config/adapter.js +0 -44
- package/middleware/deployment/deployment.js +22 -24
- package/middleware/driver/driver.js +24 -1
- package/middleware/driver-config/driver-config.js +0 -6
- package/middleware/modules/modules.js +11 -5
- package/middleware/perf/perf.js +3 -2
- package/middleware/registration/registration.js +0 -5
- package/middleware/stores/engines/empty.js +0 -4
- package/middleware/stores/engines/fs-caching-adapter.js +0 -5
- package/middleware/stores/engines/fs.js +0 -9
- package/middleware/stores/engines/s3.js +0 -5
- package/middleware/stores/engines/s3fs.js +0 -5
- package/middleware/stores/multistore.js +0 -29
- package/middleware/stores/store.js +0 -10
- package/middleware/stores/stores.js +2 -2
- package/middleware/virtual-config/virtual-config.js +253 -206
- package/middleware/virtual-files/virtual-files.js +0 -3
- package/middleware/welcome/welcome.js +0 -3
- package/notifications/notifications.js +72 -10
- package/notifications/providers/kafka.js +182 -0
- package/notifications/providers/stomp.js +4 -0
- package/package.json +40 -56
- package/server/index.js +216 -123
- package/server/standalone.js +1 -6
- package/util/auth.js +10 -4
- package/util/cloudcms.js +77 -35
- package/util/loaders.js +113 -0
- package/util/proxy-factory.js +143 -168
- package/util/request.js +6 -2
- package/util/workqueue.js +111 -0
- package/.last_command +0 -7
- package/duster/helpers/core/cloudcms/associations.js +0 -34
- package/duster/helpers/core/cloudcms/beta/markdown.js +0 -46
- package/duster/helpers/core/cloudcms/beta/nodeAttachmentText.js +0 -46
- package/duster/helpers/core/cloudcms/beta/params.js +0 -33
- package/duster/helpers/core/cloudcms/beta/processTemplate.js +0 -82
- package/duster/helpers/core/cloudcms/content.js +0 -34
- package/duster/helpers/core/cloudcms/expand.js +0 -38
- package/duster/helpers/core/cloudcms/form.js +0 -34
- package/duster/helpers/core/cloudcms/query.js +0 -34
- package/duster/helpers/core/cloudcms/queryOne.js +0 -34
- package/duster/helpers/core/cloudcms/relatives.js +0 -34
- package/duster/helpers/core/cloudcms/search.js +0 -34
- package/duster/helpers/core/cloudcms/searchOne.js +0 -34
- package/duster/helpers/core/cloudcms/wcm/dependency.js +0 -83
- package/duster/helpers/core/cloudcms/wcm/fragment.js +0 -34
- package/duster/helpers/core/dev/debug.js +0 -42
- package/duster/helpers/core/dom/block.js +0 -49
- package/duster/helpers/core/dom/include.js +0 -38
- package/duster/helpers/core/dom/layout.js +0 -49
- package/duster/helpers/core/dom/link.js +0 -81
- package/duster/helpers/core/dom/resource.js +0 -77
- package/duster/helpers/core/engine.js +0 -1580
- package/duster/helpers/core/ice/value.js +0 -65
- package/duster/helpers/core/index.js +0 -49
- package/duster/helpers/core/operators/if.js +0 -64
- package/duster/helpers/core/operators/iter.js +0 -45
- package/duster/helpers/core/operators/iterate.js +0 -129
- package/duster/helpers/sample/nyt.js +0 -114
- package/duster/index.js +0 -319
- package/duster/support.js +0 -436
- package/duster/tracker.js +0 -262
- package/middleware/authentication/providers/cas.js +0 -73
- package/middleware/authentication/providers/facebook.js +0 -120
- package/middleware/authentication/providers/github.js +0 -88
- package/middleware/authentication/providers/linkedin.js +0 -112
- package/middleware/authentication/providers/twitter.js +0 -120
- package/middleware/server-tags/server-tags.js +0 -113
- package/middleware/wcm/wcm.js +0 -1437
|
@@ -1,1580 +0,0 @@
|
|
|
1
|
-
var path = require('path');
|
|
2
|
-
var fs = require('fs');
|
|
3
|
-
var http = require('http');
|
|
4
|
-
var async = require("async");
|
|
5
|
-
|
|
6
|
-
var tracker = require("../../tracker");
|
|
7
|
-
var util = require("../../../util/util");
|
|
8
|
-
|
|
9
|
-
var DEFAULT_PAGINATION_LIMIT = 25;
|
|
10
|
-
|
|
11
|
-
module.exports = function(app, dust)
|
|
12
|
-
{
|
|
13
|
-
var support = require("../../support")(dust);
|
|
14
|
-
|
|
15
|
-
var enhanceNode = util.enhanceNode;
|
|
16
|
-
|
|
17
|
-
// helper functions
|
|
18
|
-
var isDefined = support.isDefined;
|
|
19
|
-
//var resolveVariables = support.resolveVariables;
|
|
20
|
-
var map = support.map;
|
|
21
|
-
var end = support.end;
|
|
22
|
-
var _MARK_INSIGHT = support._MARK_INSIGHT;
|
|
23
|
-
|
|
24
|
-
// return value
|
|
25
|
-
var r = {};
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Handles behavior for @expand
|
|
29
|
-
*
|
|
30
|
-
* @param chunk
|
|
31
|
-
* @param context
|
|
32
|
-
* @param bodies
|
|
33
|
-
* @param params
|
|
34
|
-
* @returns {*}
|
|
35
|
-
* @private
|
|
36
|
-
*/
|
|
37
|
-
r.handleExpand = function(chunk, context, bodies, params)
|
|
38
|
-
{
|
|
39
|
-
params = params || {};
|
|
40
|
-
|
|
41
|
-
var key = context.resolve(params.key);
|
|
42
|
-
var list = context.resolve(params.list);
|
|
43
|
-
|
|
44
|
-
list = context.get(list) || [];
|
|
45
|
-
|
|
46
|
-
if (!util.isArray(list)) {
|
|
47
|
-
list = [list];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
var idList = util.pluck(list, key);
|
|
51
|
-
var finalIdList = [];
|
|
52
|
-
for(var i = 0; i < idList.length; i++) {
|
|
53
|
-
if (idList[i] && util.isString(idList[i])) {
|
|
54
|
-
finalIdList.push(idList[i]);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
params._userQuery = {
|
|
59
|
-
"_doc": {
|
|
60
|
-
"$in": finalIdList
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
params._orderResults = finalIdList;
|
|
64
|
-
|
|
65
|
-
return handleQuery(chunk, context, bodies, params);
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Handles behavior for @query and @queryOne.
|
|
70
|
-
*
|
|
71
|
-
* @param chunk
|
|
72
|
-
* @param context
|
|
73
|
-
* @param bodies
|
|
74
|
-
* @param params
|
|
75
|
-
* @param keepOne
|
|
76
|
-
* @returns {*}
|
|
77
|
-
* @private
|
|
78
|
-
*/
|
|
79
|
-
var handleQuery = r.handleQuery = function(chunk, context, bodies, params, keepOne)
|
|
80
|
-
{
|
|
81
|
-
params = params || {};
|
|
82
|
-
|
|
83
|
-
// type
|
|
84
|
-
var type = context.resolve(params.type);
|
|
85
|
-
|
|
86
|
-
// pagination
|
|
87
|
-
var sort = context.resolve(params.sort);
|
|
88
|
-
var sortDirection = context.resolve(params.sortDirection);
|
|
89
|
-
var limit = context.resolve(params.limit);
|
|
90
|
-
var skip = context.resolve(params.skip);
|
|
91
|
-
|
|
92
|
-
// scope
|
|
93
|
-
var scope = context.resolve(params.scope);
|
|
94
|
-
|
|
95
|
-
// as
|
|
96
|
-
var as = context.resolve(params.as);
|
|
97
|
-
|
|
98
|
-
// single field constraints
|
|
99
|
-
var field = context.resolve(params.field);
|
|
100
|
-
var fieldRegex = context.resolve(params.fieldRegex);
|
|
101
|
-
var fieldValue = context.resolve(params.fieldValue);
|
|
102
|
-
|
|
103
|
-
// limit response document fields (MongoDB _fields)
|
|
104
|
-
var fields = context.resolve(params.fields) || null;
|
|
105
|
-
var _fields;
|
|
106
|
-
if (fields) {
|
|
107
|
-
_fields = {};
|
|
108
|
-
fields.split(",").map(f => {
|
|
109
|
-
_fields[f.trim()] = 1;
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// role
|
|
114
|
-
var role = context.resolve(params.role);
|
|
115
|
-
|
|
116
|
-
// geolocation (near)
|
|
117
|
-
var near = context.resolve(params.near);
|
|
118
|
-
|
|
119
|
-
// locale
|
|
120
|
-
var locale = context.resolve(params.locale) || context.get("req").acceptLanguage;
|
|
121
|
-
|
|
122
|
-
var emptyResultCode = context.resolve(params.emptyResultCode);
|
|
123
|
-
|
|
124
|
-
// whether to cache this fragment
|
|
125
|
-
var cache = context.resolve(params.cache);
|
|
126
|
-
if (typeof(cache) === "undefined" || !cache)
|
|
127
|
-
{
|
|
128
|
-
cache = false;
|
|
129
|
-
}
|
|
130
|
-
var fragmentId = null;
|
|
131
|
-
if (cache) {
|
|
132
|
-
fragmentId = context.get("fragmentIdGenerator")();
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// user defined query
|
|
136
|
-
var userQuery = params._userQuery;
|
|
137
|
-
delete params._userQuery;
|
|
138
|
-
if (!userQuery) {
|
|
139
|
-
userQuery = {};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// order the resulting records by _doc using this array of IDs
|
|
143
|
-
var orderResultsByList = params._orderResults;
|
|
144
|
-
delete params._orderResults;
|
|
145
|
-
|
|
146
|
-
// ensure limit and skip are numerical
|
|
147
|
-
if (isDefined(limit))
|
|
148
|
-
{
|
|
149
|
-
limit = parseInt(limit);
|
|
150
|
-
}
|
|
151
|
-
if (isDefined(skip))
|
|
152
|
-
{
|
|
153
|
-
skip = parseInt(skip);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// DEBUG
|
|
157
|
-
var forceError = context.resolve(params["forceError"]);
|
|
158
|
-
|
|
159
|
-
var requirements = support.buildRequirements(context, {
|
|
160
|
-
"type": type,
|
|
161
|
-
"sort": sort,
|
|
162
|
-
"sortDirection": sortDirection,
|
|
163
|
-
"limit": limit,
|
|
164
|
-
"skip": skip,
|
|
165
|
-
"scope": scope,
|
|
166
|
-
"as": as,
|
|
167
|
-
"field": field,
|
|
168
|
-
"fieldRegex": fieldRegex,
|
|
169
|
-
"fieldValue": fieldValue,
|
|
170
|
-
"near": near,
|
|
171
|
-
"locale": locale,
|
|
172
|
-
"role": role,
|
|
173
|
-
"userQuery": JSON.stringify(userQuery),
|
|
174
|
-
"_fields": JSON.stringify(_fields)
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
var finishQueryHandler = function(context)
|
|
178
|
-
{
|
|
179
|
-
tracker.finish(context);
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
return map(chunk, function(chunk2) {
|
|
183
|
-
|
|
184
|
-
// if we can serve this from the fragment cache, we do so
|
|
185
|
-
support.loadFragment(context, fragmentId, requirements, function(err, fragmentText) {
|
|
186
|
-
|
|
187
|
-
// if we found a fragment, stream it back
|
|
188
|
-
if (!err && fragmentText)
|
|
189
|
-
{
|
|
190
|
-
chunk2.write(fragmentText);
|
|
191
|
-
return chunk2.end();
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// not cached, so run this puppy...
|
|
195
|
-
|
|
196
|
-
// TRACKER: START
|
|
197
|
-
tracker.start(context, fragmentId, requirements);
|
|
198
|
-
|
|
199
|
-
var query = userQuery || {};
|
|
200
|
-
if (_fields) {
|
|
201
|
-
query._fields = _fields;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (isDefined(type))
|
|
205
|
-
{
|
|
206
|
-
query._type = type;
|
|
207
|
-
}
|
|
208
|
-
if (isDefined(field))
|
|
209
|
-
{
|
|
210
|
-
if (isDefined(fieldRegex))
|
|
211
|
-
{
|
|
212
|
-
query[field] = {
|
|
213
|
-
$regex: fieldRegex,
|
|
214
|
-
$options: "i"
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
else if (isDefined(fieldValue))
|
|
218
|
-
{
|
|
219
|
-
query[field] = fieldValue;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
if (near)
|
|
224
|
-
{
|
|
225
|
-
var nearArray = near.split(",");
|
|
226
|
-
nearArray[0] = parseFloat(nearArray[0]);
|
|
227
|
-
nearArray[1] = parseFloat(nearArray[1]);
|
|
228
|
-
|
|
229
|
-
query["loc"] = {
|
|
230
|
-
"$near": {
|
|
231
|
-
"lat": nearArray[0],
|
|
232
|
-
"long": nearArray[1]
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// strip out translations
|
|
238
|
-
query["_features.f:translation"] = {
|
|
239
|
-
"$exists": false
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
var pagination = {};
|
|
243
|
-
if (!isDefined(limit))
|
|
244
|
-
{
|
|
245
|
-
limit = DEFAULT_PAGINATION_LIMIT;
|
|
246
|
-
}
|
|
247
|
-
pagination.limit = limit;
|
|
248
|
-
if (isDefined(sort))
|
|
249
|
-
{
|
|
250
|
-
if (typeof(sortDirection) !== "undefined")
|
|
251
|
-
{
|
|
252
|
-
sortDirection = parseInt(sortDirection, 10);
|
|
253
|
-
}
|
|
254
|
-
else
|
|
255
|
-
{
|
|
256
|
-
sortDirection = 1;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
pagination.sort = {};
|
|
260
|
-
pagination.sort[sort] = sortDirection;
|
|
261
|
-
}
|
|
262
|
-
if (isDefined(skip))
|
|
263
|
-
{
|
|
264
|
-
pagination.skip = skip;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (locale)
|
|
268
|
-
{
|
|
269
|
-
var gitana = context.get("gitana");
|
|
270
|
-
gitana.getDriver().setLocale(locale);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
var req = context.get("req");
|
|
274
|
-
req.branch(function (err, branch) {
|
|
275
|
-
|
|
276
|
-
// DEBUG: force error
|
|
277
|
-
if (forceError)
|
|
278
|
-
{
|
|
279
|
-
console.log("FORCE ERROR");
|
|
280
|
-
err = {
|
|
281
|
-
"message": "Force error"
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
if (err)
|
|
286
|
-
{
|
|
287
|
-
return end(chunk2, context, err);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
var handleQueryResults = function (array) {
|
|
291
|
-
if (array.length > 0)
|
|
292
|
-
{
|
|
293
|
-
for (var i = 0; i < array.length; i++)
|
|
294
|
-
{
|
|
295
|
-
array[i]._statistics = array[i].__stats();
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
if (orderResultsByList && util.isArray(orderResultsByList))
|
|
300
|
-
{
|
|
301
|
-
var newArray = [];
|
|
302
|
-
for (var i = 0; i < orderResultsByList.length; i++)
|
|
303
|
-
{
|
|
304
|
-
for (var j = 0; j < array.length; j++)
|
|
305
|
-
{
|
|
306
|
-
if (array[j]._doc == orderResultsByList[i])
|
|
307
|
-
{
|
|
308
|
-
newArray.push(array[j]);
|
|
309
|
-
continue;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
array = newArray;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
if (array.length === 0 && emptyResultCode)
|
|
317
|
-
{
|
|
318
|
-
console.log("Query results were empty and dust tag configured to override HTTP response code to: " + emptyResultCode);
|
|
319
|
-
return end(chunk2, context, {
|
|
320
|
-
"message": "empty query results",
|
|
321
|
-
"status": emptyResultCode
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
if (keepOne)
|
|
326
|
-
{
|
|
327
|
-
var newContext = null;
|
|
328
|
-
if (array.length > 0)
|
|
329
|
-
{
|
|
330
|
-
var result = array[0];
|
|
331
|
-
|
|
332
|
-
var resultObject = null;
|
|
333
|
-
if (as)
|
|
334
|
-
{
|
|
335
|
-
resultObject = {};
|
|
336
|
-
resultObject[as] = util.clone(result, true);
|
|
337
|
-
|
|
338
|
-
_MARK_INSIGHT(result, resultObject[as]);
|
|
339
|
-
}
|
|
340
|
-
else
|
|
341
|
-
{
|
|
342
|
-
resultObject = util.clone(result, true);
|
|
343
|
-
|
|
344
|
-
_MARK_INSIGHT(result, resultObject);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
newContext = context.push(resultObject);
|
|
348
|
-
}
|
|
349
|
-
else
|
|
350
|
-
{
|
|
351
|
-
newContext = context.push({});
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
support.renderFragment(newContext, fragmentId, requirements, chunk2, bodies, function (err) {
|
|
355
|
-
|
|
356
|
-
if (err)
|
|
357
|
-
{
|
|
358
|
-
console.log("Caught error in handleQuery/renderFragment: " + err);
|
|
359
|
-
return end(chunk2, newContext, err);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
finishQueryHandler(newContext);
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
else
|
|
366
|
-
{
|
|
367
|
-
for (var a = 0; a < array.length; a++)
|
|
368
|
-
{
|
|
369
|
-
_MARK_INSIGHT(array[a], array[a]);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
var resultObject = null;
|
|
373
|
-
if (as)
|
|
374
|
-
{
|
|
375
|
-
resultObject = {
|
|
376
|
-
"offset": array._offset,
|
|
377
|
-
"total": array._totalRows
|
|
378
|
-
};
|
|
379
|
-
resultObject[as] = array;
|
|
380
|
-
}
|
|
381
|
-
else
|
|
382
|
-
{
|
|
383
|
-
resultObject = {
|
|
384
|
-
"rows": array,
|
|
385
|
-
"offset": array._offset,
|
|
386
|
-
"total": array._totalRows
|
|
387
|
-
};
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
var newContext = context.push(resultObject);
|
|
391
|
-
|
|
392
|
-
support.renderFragment(newContext, fragmentId, requirements, chunk2, bodies, function (err) {
|
|
393
|
-
|
|
394
|
-
if (err)
|
|
395
|
-
{
|
|
396
|
-
console.log("Caught error in handleQuery/renderFragment: " + err);
|
|
397
|
-
return end(chunk2, newContext, err);
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
finishQueryHandler(newContext);
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
};
|
|
404
|
-
|
|
405
|
-
var doQuery = function (branch, query, pagination) {
|
|
406
|
-
Chain(branch).trap(function (err) {
|
|
407
|
-
console.log("Caught error in handleQuery: " + err);
|
|
408
|
-
end(chunk2, context, err);
|
|
409
|
-
return false;
|
|
410
|
-
}).queryNodes(query, pagination).then(function () {
|
|
411
|
-
|
|
412
|
-
_convertToArray(this, function (array) {
|
|
413
|
-
_filterWithAuthorityChecks(array, context, branch, role, function (array) {
|
|
414
|
-
_enhanceQueryResults(array, function (array) {
|
|
415
|
-
_trackQueryResults(array, context, function (array) {
|
|
416
|
-
handleQueryResults(array);
|
|
417
|
-
});
|
|
418
|
-
});
|
|
419
|
-
});
|
|
420
|
-
});
|
|
421
|
-
|
|
422
|
-
});
|
|
423
|
-
};
|
|
424
|
-
|
|
425
|
-
var doQueryPageHasContents = function (branch, query, pagination) {
|
|
426
|
-
var page = context.get("helpers")["page"];
|
|
427
|
-
|
|
428
|
-
Chain(page).trap(function (err) {
|
|
429
|
-
console.log("Caught error in handleQuery: " + err);
|
|
430
|
-
end(chunk2, context, err);
|
|
431
|
-
return false;
|
|
432
|
-
}).queryRelatives(query, {
|
|
433
|
-
"type": "wcm:page_has_content"
|
|
434
|
-
}, pagination).then(function () {
|
|
435
|
-
|
|
436
|
-
_convertToArray(this, function (array) {
|
|
437
|
-
_filterWithAuthorityChecks(array, context, branch, role, function (array) {
|
|
438
|
-
_enhanceQueryResults(array, function (array) {
|
|
439
|
-
_trackQueryResults(array, context, function (array) {
|
|
440
|
-
handleQueryResults(array);
|
|
441
|
-
});
|
|
442
|
-
});
|
|
443
|
-
});
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
});
|
|
447
|
-
};
|
|
448
|
-
|
|
449
|
-
if (isDefined(scope))
|
|
450
|
-
{
|
|
451
|
-
doQueryPageHasContents(branch, query, pagination);
|
|
452
|
-
}
|
|
453
|
-
else
|
|
454
|
-
{
|
|
455
|
-
doQuery(branch, query, pagination);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
});
|
|
459
|
-
});
|
|
460
|
-
});
|
|
461
|
-
};
|
|
462
|
-
|
|
463
|
-
/**
|
|
464
|
-
* Handles behavior for @search and @searchOne.
|
|
465
|
-
*
|
|
466
|
-
* @param chunk
|
|
467
|
-
* @param context
|
|
468
|
-
* @param bodies
|
|
469
|
-
* @param params
|
|
470
|
-
* @param keepOne
|
|
471
|
-
* @returns {*}
|
|
472
|
-
* @private
|
|
473
|
-
*/
|
|
474
|
-
r.handleSearch = function(chunk, context, bodies, params, keepOne)
|
|
475
|
-
{
|
|
476
|
-
params = params || {};
|
|
477
|
-
|
|
478
|
-
// pagination
|
|
479
|
-
var sort = context.resolve(params.sort);
|
|
480
|
-
var sortDirection = context.resolve(params.sortDirection);
|
|
481
|
-
var limit = context.resolve(params.limit);
|
|
482
|
-
var skip = context.resolve(params.skip);
|
|
483
|
-
|
|
484
|
-
// scope
|
|
485
|
-
//var scope = context.resolve(params.scope);
|
|
486
|
-
|
|
487
|
-
// text
|
|
488
|
-
var text = context.resolve(params.text);
|
|
489
|
-
|
|
490
|
-
// as
|
|
491
|
-
var as = context.resolve(params.as);
|
|
492
|
-
|
|
493
|
-
// locale
|
|
494
|
-
var locale = context.resolve(params.locale) || context.get("req").acceptLanguage;
|
|
495
|
-
|
|
496
|
-
// ensure limit and skip are numerical
|
|
497
|
-
if (isDefined(limit))
|
|
498
|
-
{
|
|
499
|
-
limit = parseInt(limit);
|
|
500
|
-
}
|
|
501
|
-
if (isDefined(skip))
|
|
502
|
-
{
|
|
503
|
-
limit = parseInt(skip);
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
// TRACKER: START
|
|
507
|
-
tracker.start(context);
|
|
508
|
-
|
|
509
|
-
if (locale) {
|
|
510
|
-
tracker.requires(context, "locale", locale);
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
return map(chunk, function(chunk) {
|
|
514
|
-
|
|
515
|
-
if (locale)
|
|
516
|
-
{
|
|
517
|
-
var gitana = context.get("gitana");
|
|
518
|
-
gitana.getDriver().setLocale(locale);
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
var req = context.get("req");
|
|
522
|
-
req.branch(function(err, branch) {
|
|
523
|
-
|
|
524
|
-
if (err) {
|
|
525
|
-
return end(chunk, context, err);
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
// TODO: use a "find" to limit to a range of nodes (for page scope)?
|
|
529
|
-
|
|
530
|
-
var pagination = {};
|
|
531
|
-
if (!isDefined(limit)) {
|
|
532
|
-
limit = DEFAULT_PAGINATION_LIMIT;
|
|
533
|
-
}
|
|
534
|
-
pagination.limit = limit;
|
|
535
|
-
if (sort)
|
|
536
|
-
{
|
|
537
|
-
if (typeof(sortDirection) !== "undefined")
|
|
538
|
-
{
|
|
539
|
-
sortDirection = parseInt(sortDirection, 10);
|
|
540
|
-
}
|
|
541
|
-
else
|
|
542
|
-
{
|
|
543
|
-
sortDirection = 1;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
pagination.sort = {};
|
|
547
|
-
pagination.sort[sort] = sortDirection;
|
|
548
|
-
}
|
|
549
|
-
if (skip)
|
|
550
|
-
{
|
|
551
|
-
pagination.skip = skip;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
Chain(branch).trap(function(err){
|
|
555
|
-
console.log("Caught error in handleSearch: " + err);
|
|
556
|
-
end(chunk, context, err);
|
|
557
|
-
return false;
|
|
558
|
-
}).searchNodes(text, pagination).each(function() {
|
|
559
|
-
|
|
560
|
-
// enhance node information
|
|
561
|
-
enhanceNode(this);
|
|
562
|
-
|
|
563
|
-
// TRACKER - PRODUCES "node"
|
|
564
|
-
tracker.produces(context, "node", this._doc);
|
|
565
|
-
|
|
566
|
-
}).then(function() {
|
|
567
|
-
|
|
568
|
-
var array = this.asArray();
|
|
569
|
-
for (var a = 0; a < array.length; a++)
|
|
570
|
-
{
|
|
571
|
-
_MARK_INSIGHT(array[a], array[a]);
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
var resultObject = null;
|
|
575
|
-
if (as)
|
|
576
|
-
{
|
|
577
|
-
resultObject = {
|
|
578
|
-
"offset": this.offset(),
|
|
579
|
-
"total": this.totalRows()
|
|
580
|
-
};
|
|
581
|
-
resultObject[as] = array;
|
|
582
|
-
}
|
|
583
|
-
else
|
|
584
|
-
{
|
|
585
|
-
resultObject = {
|
|
586
|
-
"rows": array,
|
|
587
|
-
"offset": this.offset(),
|
|
588
|
-
"total": this.totalRows()
|
|
589
|
-
};
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
var newContext = context.push(resultObject);
|
|
593
|
-
|
|
594
|
-
chunk.render(bodies.block, newContext);
|
|
595
|
-
end(chunk, context);
|
|
596
|
-
});
|
|
597
|
-
});
|
|
598
|
-
});
|
|
599
|
-
};
|
|
600
|
-
|
|
601
|
-
r.handleAssociations = function(chunk, context, bodies, params)
|
|
602
|
-
{
|
|
603
|
-
params = params || {};
|
|
604
|
-
|
|
605
|
-
// pagination
|
|
606
|
-
var sort = context.resolve(params.sort);
|
|
607
|
-
var sortDirection = context.resolve(params.sortDirection);
|
|
608
|
-
var limit = context.resolve(params.limit);
|
|
609
|
-
var skip = context.resolve(params.skip);
|
|
610
|
-
var nodeSort = context.resolve(params.nodeSort);
|
|
611
|
-
var nodeSortDirection = context.resolve(params.nodeSortDirection);
|
|
612
|
-
var nodeSkip = context.resolve(params.nodeSkip);
|
|
613
|
-
var nodeLimit = context.resolve(params.nodeLimit);
|
|
614
|
-
|
|
615
|
-
// as
|
|
616
|
-
var as = context.resolve(params.as);
|
|
617
|
-
|
|
618
|
-
// node
|
|
619
|
-
var nodeId = context.resolve(params.node);
|
|
620
|
-
var associationType = context.resolve(params.type);
|
|
621
|
-
var associationDirection = context.resolve(params.direction);
|
|
622
|
-
|
|
623
|
-
// locale
|
|
624
|
-
var locale = context.resolve(params.locale) || context.get("req").acceptLanguage;
|
|
625
|
-
|
|
626
|
-
// ensure limit and skip are numerical
|
|
627
|
-
if (isDefined(limit))
|
|
628
|
-
{
|
|
629
|
-
limit = parseInt(limit);
|
|
630
|
-
}
|
|
631
|
-
if (isDefined(skip))
|
|
632
|
-
{
|
|
633
|
-
skip = parseInt(skip);
|
|
634
|
-
}
|
|
635
|
-
if (isDefined(nodeLimit))
|
|
636
|
-
{
|
|
637
|
-
nodeLimit = parseInt(nodeLimit);
|
|
638
|
-
}
|
|
639
|
-
if (isDefined(nodeSkip))
|
|
640
|
-
{
|
|
641
|
-
nodeSkip = parseInt(nodeSkip);
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
// TRACKER: START
|
|
645
|
-
tracker.start(context);
|
|
646
|
-
if (locale) {
|
|
647
|
-
tracker.requires(context, "locale", locale);
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
return map(chunk, function(chunk) {
|
|
651
|
-
|
|
652
|
-
if (locale)
|
|
653
|
-
{
|
|
654
|
-
var gitana = context.get("gitana");
|
|
655
|
-
gitana.getDriver().setLocale(locale);
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
var req = context.get("req");
|
|
659
|
-
req.branch(function(err, branch) {
|
|
660
|
-
|
|
661
|
-
if (err) {
|
|
662
|
-
return end(chunk, context, err);
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
Chain(branch).trap(function(err) {
|
|
666
|
-
console.log("Caught error in handleAssociations: " + err);
|
|
667
|
-
end(chunk, context, err);
|
|
668
|
-
return false;
|
|
669
|
-
}).readNode(nodeId).then(function() {
|
|
670
|
-
|
|
671
|
-
var pagination = {};
|
|
672
|
-
if (!isDefined(limit)) {
|
|
673
|
-
limit = DEFAULT_PAGINATION_LIMIT;
|
|
674
|
-
}
|
|
675
|
-
pagination.limit = limit;
|
|
676
|
-
if (sort)
|
|
677
|
-
{
|
|
678
|
-
if (typeof(sortDirection) !== "undefined")
|
|
679
|
-
{
|
|
680
|
-
sortDirection = parseInt(sortDirection, 10);
|
|
681
|
-
}
|
|
682
|
-
else
|
|
683
|
-
{
|
|
684
|
-
sortDirection = 1;
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
pagination.sort = {};
|
|
688
|
-
pagination.sort[sort] = sortDirection;
|
|
689
|
-
}
|
|
690
|
-
if (skip)
|
|
691
|
-
{
|
|
692
|
-
pagination.skip = skip;
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
var config = {};
|
|
696
|
-
if (associationType)
|
|
697
|
-
{
|
|
698
|
-
config.type = associationType;
|
|
699
|
-
}
|
|
700
|
-
if (associationDirection)
|
|
701
|
-
{
|
|
702
|
-
config.direction = associationDirection;
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
var node = this;
|
|
706
|
-
|
|
707
|
-
this.associations(config, pagination).each(function() {
|
|
708
|
-
|
|
709
|
-
// TRACKER - PRODUCES "node"
|
|
710
|
-
tracker.produces(context, "node", this._doc);
|
|
711
|
-
|
|
712
|
-
}).then(function() {
|
|
713
|
-
|
|
714
|
-
var array = this.asArray();
|
|
715
|
-
for (var a = 0; a < array.length; a++)
|
|
716
|
-
{
|
|
717
|
-
_MARK_INSIGHT(array[a], array[a]);
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
var resultObject = null;
|
|
721
|
-
if (as)
|
|
722
|
-
{
|
|
723
|
-
resultObject = {
|
|
724
|
-
"offset": this.offset(),
|
|
725
|
-
"total": this.totalRows()
|
|
726
|
-
};
|
|
727
|
-
resultObject[as] = array;
|
|
728
|
-
}
|
|
729
|
-
else
|
|
730
|
-
{
|
|
731
|
-
resultObject = {
|
|
732
|
-
"rows": array,
|
|
733
|
-
"offset": this.offset(),
|
|
734
|
-
"total": this.totalRows()
|
|
735
|
-
};
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
var cf = function(sortedArray)
|
|
739
|
-
{
|
|
740
|
-
if (sortedArray) {
|
|
741
|
-
resultObject[as || "rows"] = sortedArray;
|
|
742
|
-
resultObject.total = sortedArray.length;
|
|
743
|
-
}
|
|
744
|
-
var newContext = context.push(resultObject);
|
|
745
|
-
|
|
746
|
-
chunk.render(bodies.block, newContext);
|
|
747
|
-
end(chunk, context);
|
|
748
|
-
};
|
|
749
|
-
|
|
750
|
-
if (array.length == 0)
|
|
751
|
-
{
|
|
752
|
-
cf();
|
|
753
|
-
return;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
// load target node data for each association
|
|
757
|
-
var otherNodeIdsMap = {};
|
|
758
|
-
var otherNodeIds = [];
|
|
759
|
-
var otherNodeIdToAssociations = {};
|
|
760
|
-
for (var z = 0; z < array.length; z++)
|
|
761
|
-
{
|
|
762
|
-
var otherNodeId = null;
|
|
763
|
-
if (array[z].source == node._doc) {
|
|
764
|
-
otherNodeId = array[z].target;
|
|
765
|
-
} else {
|
|
766
|
-
otherNodeId = array[z].source;
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
if (!otherNodeIdsMap[otherNodeId])
|
|
770
|
-
{
|
|
771
|
-
otherNodeIdsMap[otherNodeId] = true;
|
|
772
|
-
otherNodeIds.push(otherNodeId);
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
if (!otherNodeIdToAssociations[otherNodeId])
|
|
776
|
-
{
|
|
777
|
-
otherNodeIdToAssociations[otherNodeId] = [];
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
otherNodeIdToAssociations[otherNodeId].push(array[z]);
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
pagination = {
|
|
784
|
-
limit: nodeLimit || otherNodeIds.length,
|
|
785
|
-
skip: nodeSkip || 0
|
|
786
|
-
};
|
|
787
|
-
if (nodeSort)
|
|
788
|
-
{
|
|
789
|
-
if (typeof(nodeSortDirection) !== "undefined")
|
|
790
|
-
{
|
|
791
|
-
sortDirection = parseInt(nodeSortDirection, 10);
|
|
792
|
-
}
|
|
793
|
-
else
|
|
794
|
-
{
|
|
795
|
-
sortDirection = 1;
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
pagination.sort = {};
|
|
799
|
-
pagination.sort[nodeSort] = sortDirection;
|
|
800
|
-
}
|
|
801
|
-
var otherNodeIdToAssociationsSorted = [];
|
|
802
|
-
Chain(node.getBranch()).queryNodes({
|
|
803
|
-
"_doc": {
|
|
804
|
-
"$in": otherNodeIds
|
|
805
|
-
}
|
|
806
|
-
}, pagination).each(function() {
|
|
807
|
-
|
|
808
|
-
var associations_array = otherNodeIdToAssociations[this._doc];
|
|
809
|
-
for (var z = 0; z < associations_array.length; z++)
|
|
810
|
-
{
|
|
811
|
-
associations_array[z].other = util.clone(this, true);
|
|
812
|
-
|
|
813
|
-
// sorting by node properties (not association properties)
|
|
814
|
-
otherNodeIdToAssociationsSorted.push(associations_array[z]);
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
// enhance node information
|
|
818
|
-
enhanceNode(this);
|
|
819
|
-
|
|
820
|
-
// TRACKER - PRODUCES "node"
|
|
821
|
-
tracker.produces(context, "node", this._doc);
|
|
822
|
-
|
|
823
|
-
}).then(function() {
|
|
824
|
-
if (pagination.sort) {
|
|
825
|
-
cf(otherNodeIdToAssociationsSorted);
|
|
826
|
-
}
|
|
827
|
-
else{
|
|
828
|
-
cf();
|
|
829
|
-
}
|
|
830
|
-
});
|
|
831
|
-
});
|
|
832
|
-
});
|
|
833
|
-
});
|
|
834
|
-
});
|
|
835
|
-
};
|
|
836
|
-
|
|
837
|
-
r.handleRelatives = function(chunk, context, bodies, params)
|
|
838
|
-
{
|
|
839
|
-
params = params || {};
|
|
840
|
-
|
|
841
|
-
// pagination
|
|
842
|
-
var sort = context.resolve(params.sort);
|
|
843
|
-
var sortDirection = context.resolve(params.sortDirection);
|
|
844
|
-
var limit = context.resolve(params.limit);
|
|
845
|
-
var skip = context.resolve(params.skip);
|
|
846
|
-
|
|
847
|
-
// as
|
|
848
|
-
var as = context.resolve(params.as);
|
|
849
|
-
|
|
850
|
-
// from and type
|
|
851
|
-
var fromNodeId = context.resolve(params.node);
|
|
852
|
-
var associationType = context.resolve(params.associationType);
|
|
853
|
-
var associationDirection = context.resolve(params.direction);
|
|
854
|
-
|
|
855
|
-
var type = context.resolve(params.type);
|
|
856
|
-
|
|
857
|
-
// single field constraints
|
|
858
|
-
var field = context.resolve(params.field);
|
|
859
|
-
var fieldRegex = context.resolve(params.fieldRegex);
|
|
860
|
-
var fieldValue = context.resolve(params.fieldValue);
|
|
861
|
-
|
|
862
|
-
// locale
|
|
863
|
-
var locale = context.resolve(params.locale) || context.get("req").acceptLanguage;
|
|
864
|
-
|
|
865
|
-
// role
|
|
866
|
-
var role = context.resolve(params.role);
|
|
867
|
-
|
|
868
|
-
// ensure limit and skip are numerical
|
|
869
|
-
if (isDefined(limit))
|
|
870
|
-
{
|
|
871
|
-
limit = parseInt(limit);
|
|
872
|
-
}
|
|
873
|
-
if (isDefined(skip))
|
|
874
|
-
{
|
|
875
|
-
limit = parseInt(skip);
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
// TRACKER: START
|
|
879
|
-
tracker.start(context);
|
|
880
|
-
if (locale) {
|
|
881
|
-
tracker.requires(context, "locale", locale);
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
return map(chunk, function(chunk) {
|
|
885
|
-
|
|
886
|
-
var gitana = context.get("gitana");
|
|
887
|
-
|
|
888
|
-
var req = context.get("req");
|
|
889
|
-
req.branch(function(err, branch) {
|
|
890
|
-
|
|
891
|
-
if (err) {
|
|
892
|
-
return end(chunk, context, err);
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
Chain(branch).trap(function(err){
|
|
896
|
-
console.log("Caught error in handleRelatives: " + err);
|
|
897
|
-
end(chunk, context, err);
|
|
898
|
-
return false;
|
|
899
|
-
}).readNode(fromNodeId).then(function() {
|
|
900
|
-
|
|
901
|
-
// first query for relatives
|
|
902
|
-
var query = {};
|
|
903
|
-
if (isDefined(type))
|
|
904
|
-
{
|
|
905
|
-
query._type = type;
|
|
906
|
-
}
|
|
907
|
-
if (isDefined(field))
|
|
908
|
-
{
|
|
909
|
-
if (isDefined(fieldRegex))
|
|
910
|
-
{
|
|
911
|
-
query[field] = {
|
|
912
|
-
$regex: fieldRegex,
|
|
913
|
-
$options: "i"
|
|
914
|
-
};
|
|
915
|
-
}
|
|
916
|
-
else if (isDefined(fieldValue))
|
|
917
|
-
{
|
|
918
|
-
query[field] = fieldValue;
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
// pagination
|
|
923
|
-
var pagination = {};
|
|
924
|
-
if (!isDefined(limit)) {
|
|
925
|
-
limit = DEFAULT_PAGINATION_LIMIT;
|
|
926
|
-
}
|
|
927
|
-
pagination.limit = limit;
|
|
928
|
-
if (sort)
|
|
929
|
-
{
|
|
930
|
-
if (typeof(sortDirection) !== "undefined")
|
|
931
|
-
{
|
|
932
|
-
sortDirection = parseInt(sortDirection, 10);
|
|
933
|
-
}
|
|
934
|
-
else
|
|
935
|
-
{
|
|
936
|
-
sortDirection = 1;
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
pagination.sort = {};
|
|
940
|
-
pagination.sort[sort] = sortDirection;
|
|
941
|
-
}
|
|
942
|
-
if (skip)
|
|
943
|
-
{
|
|
944
|
-
pagination.skip = skip;
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
var config = {};
|
|
948
|
-
if (associationType)
|
|
949
|
-
{
|
|
950
|
-
config.type = associationType;
|
|
951
|
-
}
|
|
952
|
-
if (associationDirection)
|
|
953
|
-
{
|
|
954
|
-
config.direction = associationDirection;
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
var handleResults = function(array) {
|
|
958
|
-
|
|
959
|
-
for (var a = 0; a < array.length; a++)
|
|
960
|
-
{
|
|
961
|
-
_MARK_INSIGHT(array[a], array[a]);
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
var resultObject = null;
|
|
965
|
-
if (as)
|
|
966
|
-
{
|
|
967
|
-
resultObject = {
|
|
968
|
-
"offset": array._offset,
|
|
969
|
-
"total": array._totalRows
|
|
970
|
-
};
|
|
971
|
-
resultObject[as] = array;
|
|
972
|
-
}
|
|
973
|
-
else
|
|
974
|
-
{
|
|
975
|
-
resultObject = {
|
|
976
|
-
"rows": array,
|
|
977
|
-
"offset": array._offset,
|
|
978
|
-
"total": array._totalRows
|
|
979
|
-
};
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
var newContext = context.push(resultObject);
|
|
983
|
-
|
|
984
|
-
chunk.render(bodies.block, newContext);
|
|
985
|
-
end(chunk, context);
|
|
986
|
-
|
|
987
|
-
};
|
|
988
|
-
|
|
989
|
-
Chain(this).trap(function(err) {
|
|
990
|
-
console.log("Caught error in handleRelatives/queryRelatives: " + err);
|
|
991
|
-
end(chunk, context, err);
|
|
992
|
-
return false;
|
|
993
|
-
}).queryRelatives(query, config, pagination).then(function () {
|
|
994
|
-
|
|
995
|
-
_convertToArray(this, function (array) {
|
|
996
|
-
_filterWithAuthorityChecks(array, context, branch, role, function (array) {
|
|
997
|
-
_enhanceQueryResults(array, function (array) {
|
|
998
|
-
_trackQueryResults(array, context, function (array) {
|
|
999
|
-
handleResults(array);
|
|
1000
|
-
});
|
|
1001
|
-
});
|
|
1002
|
-
});
|
|
1003
|
-
});
|
|
1004
|
-
|
|
1005
|
-
});
|
|
1006
|
-
});
|
|
1007
|
-
});
|
|
1008
|
-
});
|
|
1009
|
-
};
|
|
1010
|
-
|
|
1011
|
-
r.handleContent = function(chunk, context, bodies, params)
|
|
1012
|
-
{
|
|
1013
|
-
params = params || {};
|
|
1014
|
-
|
|
1015
|
-
var id = context.resolve(params.id);
|
|
1016
|
-
var contentPath = context.resolve(params.path);
|
|
1017
|
-
|
|
1018
|
-
// as
|
|
1019
|
-
var as = context.resolve(params.as);
|
|
1020
|
-
|
|
1021
|
-
// locale
|
|
1022
|
-
var locale = context.resolve(params.locale) || context.get("req").acceptLanguage;
|
|
1023
|
-
|
|
1024
|
-
var requirements = support.buildRequirements(context, {
|
|
1025
|
-
"as": as,
|
|
1026
|
-
"id": id,
|
|
1027
|
-
"contentPath": contentPath,
|
|
1028
|
-
"locale": locale
|
|
1029
|
-
});
|
|
1030
|
-
|
|
1031
|
-
var finishHandler = function(context, err)
|
|
1032
|
-
{
|
|
1033
|
-
tracker.finish(context);
|
|
1034
|
-
};
|
|
1035
|
-
|
|
1036
|
-
// identifier for this fragment
|
|
1037
|
-
var fragmentId = context.resolve(params.fragment);
|
|
1038
|
-
|
|
1039
|
-
return map(chunk, function(chunk2) {
|
|
1040
|
-
|
|
1041
|
-
// if we can serve this from the fragment cache, we do so
|
|
1042
|
-
support.loadFragment(context, fragmentId, requirements, function(err, fragmentText) {
|
|
1043
|
-
|
|
1044
|
-
// if we found a fragment, stream it back
|
|
1045
|
-
if (!err && fragmentText) {
|
|
1046
|
-
chunk2.write(fragmentText);
|
|
1047
|
-
return chunk2.end();
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
// TRACKER: START
|
|
1051
|
-
tracker.start(context);
|
|
1052
|
-
if (locale) {
|
|
1053
|
-
tracker.requires(context, "locale", locale);
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
if (locale)
|
|
1057
|
-
{
|
|
1058
|
-
var gitana = context.get("gitana");
|
|
1059
|
-
gitana.getDriver().setLocale(locale);
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
var f = function(node)
|
|
1063
|
-
{
|
|
1064
|
-
// enhance node information
|
|
1065
|
-
enhanceNode(node);
|
|
1066
|
-
|
|
1067
|
-
// TRACKER - PRODUCES "node"
|
|
1068
|
-
tracker.produces(context, "node", node._doc);
|
|
1069
|
-
|
|
1070
|
-
var newContextObject = {};
|
|
1071
|
-
if (as)
|
|
1072
|
-
{
|
|
1073
|
-
newContextObject[as] = util.clone(node, true);
|
|
1074
|
-
|
|
1075
|
-
_MARK_INSIGHT(node, newContextObject[as]);
|
|
1076
|
-
}
|
|
1077
|
-
else
|
|
1078
|
-
{
|
|
1079
|
-
newContextObject["content"] = util.clone(node, true);
|
|
1080
|
-
|
|
1081
|
-
_MARK_INSIGHT(node, newContextObject.content);
|
|
1082
|
-
}
|
|
1083
|
-
|
|
1084
|
-
var newContext = context.push(newContextObject);
|
|
1085
|
-
//newContext.get("content").attachments = attachments;
|
|
1086
|
-
|
|
1087
|
-
support.renderFragment(newContext, fragmentId, requirements, chunk2, bodies, function(err) {
|
|
1088
|
-
finishHandler(newContext, err);
|
|
1089
|
-
});
|
|
1090
|
-
|
|
1091
|
-
// chunk.render(bodies.block, newContext);
|
|
1092
|
-
// end(chunk, context);
|
|
1093
|
-
};
|
|
1094
|
-
|
|
1095
|
-
var req = context.get("req");
|
|
1096
|
-
req.branch(function(err, branch) {
|
|
1097
|
-
|
|
1098
|
-
if (err) {
|
|
1099
|
-
return end(chunk2, context, err);
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
// select by ID or select by Path
|
|
1103
|
-
if (id)
|
|
1104
|
-
{
|
|
1105
|
-
Chain(branch).trap(function(err) {
|
|
1106
|
-
console.log("Caught error in handleContent: " + err);
|
|
1107
|
-
end(chunk2, context, err);
|
|
1108
|
-
return false;
|
|
1109
|
-
}).readNode(id).then(function() {
|
|
1110
|
-
f(this);
|
|
1111
|
-
});
|
|
1112
|
-
}
|
|
1113
|
-
else if (contentPath)
|
|
1114
|
-
{
|
|
1115
|
-
Chain(branch).trap(function(err) {
|
|
1116
|
-
console.log("Caught error in handleContent: " + err);
|
|
1117
|
-
end(chunk2, context, err);
|
|
1118
|
-
return false;
|
|
1119
|
-
}).readNode("root", contentPath).then(function() {
|
|
1120
|
-
f(this);
|
|
1121
|
-
});
|
|
1122
|
-
}
|
|
1123
|
-
else
|
|
1124
|
-
{
|
|
1125
|
-
// missing both ID and Path?
|
|
1126
|
-
console.log("Missing ID and PATH! {@content} helper must have either a path or an id");
|
|
1127
|
-
}
|
|
1128
|
-
});
|
|
1129
|
-
});
|
|
1130
|
-
});
|
|
1131
|
-
};
|
|
1132
|
-
|
|
1133
|
-
r.handleForm = function(chunk, context, bodies, params)
|
|
1134
|
-
{
|
|
1135
|
-
params = params || {};
|
|
1136
|
-
|
|
1137
|
-
var definition = context.resolve(params.definition);
|
|
1138
|
-
var form = context.resolve(params.form);
|
|
1139
|
-
var list = context.resolve(params.list);
|
|
1140
|
-
var successUrl = context.resolve(params.success);
|
|
1141
|
-
var errorUrl = context.resolve(params.error);
|
|
1142
|
-
var formId = context.resolve(params.formId);
|
|
1143
|
-
var submitTitle = context.resolve(params.submitTitle);
|
|
1144
|
-
|
|
1145
|
-
return map(chunk, function(chunk) {
|
|
1146
|
-
|
|
1147
|
-
var gitana = context.get("gitana");
|
|
1148
|
-
|
|
1149
|
-
var req = context.get("req");
|
|
1150
|
-
req.branch(function(err, branch) {
|
|
1151
|
-
|
|
1152
|
-
if (err) {
|
|
1153
|
-
return end(chunk, context, err);
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
// read the definition
|
|
1157
|
-
Chain(branch).trap(function(err) {
|
|
1158
|
-
console.log("Caught error in handleForm: " + err);
|
|
1159
|
-
end(chunk, context, err);
|
|
1160
|
-
return false;
|
|
1161
|
-
}).readDefinition(definition).then(function() {
|
|
1162
|
-
var schema = this;
|
|
1163
|
-
|
|
1164
|
-
// if a form is specified, read the form
|
|
1165
|
-
var options = null;
|
|
1166
|
-
this.readForm(form).then(function() {
|
|
1167
|
-
options = this;
|
|
1168
|
-
});
|
|
1169
|
-
|
|
1170
|
-
this.then(function() {
|
|
1171
|
-
|
|
1172
|
-
if (!options)
|
|
1173
|
-
{
|
|
1174
|
-
options = {};
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
var config = {
|
|
1178
|
-
"schema": schema,
|
|
1179
|
-
"options": options
|
|
1180
|
-
};
|
|
1181
|
-
var action = "/_form/submit";
|
|
1182
|
-
/*
|
|
1183
|
-
if (list)
|
|
1184
|
-
{
|
|
1185
|
-
action += "&list=" + list;
|
|
1186
|
-
}
|
|
1187
|
-
if (successUrl)
|
|
1188
|
-
{
|
|
1189
|
-
action += "&successUrl=" + successUrl;
|
|
1190
|
-
}
|
|
1191
|
-
if (errorUrl)
|
|
1192
|
-
{
|
|
1193
|
-
action += "&errorUrl=" + errorUrl;
|
|
1194
|
-
}
|
|
1195
|
-
*/
|
|
1196
|
-
/*
|
|
1197
|
-
options.renderForm = true;
|
|
1198
|
-
options.form = {
|
|
1199
|
-
"attributes": {
|
|
1200
|
-
"method": "POST",
|
|
1201
|
-
"action": action,
|
|
1202
|
-
"enctype": "application/json",
|
|
1203
|
-
"data-ajax": "true"
|
|
1204
|
-
},
|
|
1205
|
-
"buttons": {
|
|
1206
|
-
"submit": {
|
|
1207
|
-
"title": "Submit"
|
|
1208
|
-
}
|
|
1209
|
-
}
|
|
1210
|
-
};
|
|
1211
|
-
*/
|
|
1212
|
-
config.helper = {};
|
|
1213
|
-
config.helper.method = "POST";
|
|
1214
|
-
config.helper.action = action;
|
|
1215
|
-
config.helper.submitTitle = submitTitle;
|
|
1216
|
-
if (list)
|
|
1217
|
-
{
|
|
1218
|
-
config.helper.list = list;
|
|
1219
|
-
}
|
|
1220
|
-
if (successUrl)
|
|
1221
|
-
{
|
|
1222
|
-
config.helper.successUrl = successUrl;
|
|
1223
|
-
}
|
|
1224
|
-
if (errorUrl)
|
|
1225
|
-
{
|
|
1226
|
-
config.helper.errorUrl = errorUrl;
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
|
-
config.connector = {
|
|
1230
|
-
"id": "appserver",
|
|
1231
|
-
"config": {}
|
|
1232
|
-
};
|
|
1233
|
-
|
|
1234
|
-
var divId = formId || "form" + new Date().getTime();
|
|
1235
|
-
|
|
1236
|
-
chunk.write("<div id='" + divId + "'></div>");
|
|
1237
|
-
chunk.write("<script src='/_lib/formhelper/formhelper.js'></script>");
|
|
1238
|
-
|
|
1239
|
-
chunk.write("<script>");
|
|
1240
|
-
chunk.write("var formConfig = GenerateForm(" + JSON.stringify(config) + ");");
|
|
1241
|
-
chunk.write("$('#" + divId + "').alpaca(formConfig);");
|
|
1242
|
-
chunk.write("</script>");
|
|
1243
|
-
|
|
1244
|
-
end(chunk, context);
|
|
1245
|
-
|
|
1246
|
-
});
|
|
1247
|
-
});
|
|
1248
|
-
});
|
|
1249
|
-
});
|
|
1250
|
-
};
|
|
1251
|
-
|
|
1252
|
-
// NOTE: this can also be done like this:
|
|
1253
|
-
// NOTE: as per source dust.js line 521
|
|
1254
|
-
/*
|
|
1255
|
-
Context.prototype.resolve = function(body) {
|
|
1256
|
-
var chunk;
|
|
1257
|
-
|
|
1258
|
-
if(typeof body !== 'function') {
|
|
1259
|
-
return body;
|
|
1260
|
-
}
|
|
1261
|
-
chunk = new Chunk().render(body, this);
|
|
1262
|
-
if(chunk instanceof Chunk) {
|
|
1263
|
-
return chunk.data.join(''); // ie7 perf
|
|
1264
|
-
}
|
|
1265
|
-
return chunk;
|
|
1266
|
-
};
|
|
1267
|
-
*/
|
|
1268
|
-
|
|
1269
|
-
/**
|
|
1270
|
-
* Handles include behavior for @include and @module
|
|
1271
|
-
*
|
|
1272
|
-
* @param chunk
|
|
1273
|
-
* @param context
|
|
1274
|
-
* @param bodies
|
|
1275
|
-
* @param params
|
|
1276
|
-
* @param targetPath
|
|
1277
|
-
* @returns {*}
|
|
1278
|
-
* @private
|
|
1279
|
-
*/
|
|
1280
|
-
r.handleInclude = function(chunk, context, bodies, params, targetPath)
|
|
1281
|
-
{
|
|
1282
|
-
params = params || {};
|
|
1283
|
-
|
|
1284
|
-
var log = context.options.log;
|
|
1285
|
-
|
|
1286
|
-
targetPath = targetPath.replace(/\\/g, '/');
|
|
1287
|
-
|
|
1288
|
-
return map(chunk, function(chunk2) {
|
|
1289
|
-
|
|
1290
|
-
var store = context.options.store;
|
|
1291
|
-
|
|
1292
|
-
// the stack of executing template file paths
|
|
1293
|
-
var currentTemplateFilePaths = context.get("templateFilePaths").reverse();
|
|
1294
|
-
|
|
1295
|
-
var resolveMatchingFilePath = function(callback)
|
|
1296
|
-
{
|
|
1297
|
-
// absolute path
|
|
1298
|
-
if (targetPath.indexOf("/") === 0)
|
|
1299
|
-
{
|
|
1300
|
-
currentTemplateFilePaths = currentTemplateFilePaths.reverse();
|
|
1301
|
-
|
|
1302
|
-
// absolute path, always relative to the first element in the template file paths list
|
|
1303
|
-
var filePath = path.normalize(path.join(currentTemplateFilePaths[0], "..", "." + targetPath));
|
|
1304
|
-
|
|
1305
|
-
// if the file path does not end with ".html", we append
|
|
1306
|
-
if (filePath.indexOf(".html") == -1)
|
|
1307
|
-
{
|
|
1308
|
-
filePath += ".html";
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
store.existsFile(filePath, function(exists) {
|
|
1312
|
-
|
|
1313
|
-
if (exists) {
|
|
1314
|
-
callback(null, filePath);
|
|
1315
|
-
} else {
|
|
1316
|
-
callback();
|
|
1317
|
-
// callback({"message": "file not found in store: " + filePath});
|
|
1318
|
-
}
|
|
1319
|
-
});
|
|
1320
|
-
}
|
|
1321
|
-
else
|
|
1322
|
-
{
|
|
1323
|
-
var fns = [];
|
|
1324
|
-
|
|
1325
|
-
// relative path, walk the template file paths list backwards
|
|
1326
|
-
var filePaths = [];
|
|
1327
|
-
for (var a = 0; a < currentTemplateFilePaths.length; a++)
|
|
1328
|
-
{
|
|
1329
|
-
var fn = function(currentTemplateFilePath) {
|
|
1330
|
-
return function(done) {
|
|
1331
|
-
|
|
1332
|
-
// target template path
|
|
1333
|
-
var filePath = path.normalize(path.join(currentTemplateFilePath, "..", targetPath));
|
|
1334
|
-
|
|
1335
|
-
// if the file path does not end with ".html", we append
|
|
1336
|
-
if (filePath.indexOf(".html") == -1)
|
|
1337
|
-
{
|
|
1338
|
-
filePath += ".html";
|
|
1339
|
-
}
|
|
1340
|
-
|
|
1341
|
-
store.existsFile(filePath, function(exists) {
|
|
1342
|
-
|
|
1343
|
-
if (exists) {
|
|
1344
|
-
filePaths.push(filePath);
|
|
1345
|
-
}
|
|
1346
|
-
|
|
1347
|
-
done();
|
|
1348
|
-
});
|
|
1349
|
-
}
|
|
1350
|
-
};
|
|
1351
|
-
fns.push(fn);
|
|
1352
|
-
}
|
|
1353
|
-
|
|
1354
|
-
async.series(fns, function() {
|
|
1355
|
-
|
|
1356
|
-
for (var i = 0; i < filePaths.length; i++) {
|
|
1357
|
-
if (filePaths[i]) {
|
|
1358
|
-
callback(null, filePaths[i]);
|
|
1359
|
-
break;
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
})
|
|
1363
|
-
|
|
1364
|
-
}
|
|
1365
|
-
};
|
|
1366
|
-
|
|
1367
|
-
resolveMatchingFilePath(function(err, matchingFilePath) {
|
|
1368
|
-
|
|
1369
|
-
// if no match...
|
|
1370
|
-
if (!matchingFilePath) {
|
|
1371
|
-
console.log("Unable to find included file for path: " + targetPath);
|
|
1372
|
-
end(chunk2, context);
|
|
1373
|
-
return;
|
|
1374
|
-
}
|
|
1375
|
-
|
|
1376
|
-
var filePath = matchingFilePath;
|
|
1377
|
-
|
|
1378
|
-
var templatePath = filePath.split(path.sep).join("/");
|
|
1379
|
-
|
|
1380
|
-
var includeContextObject = {};
|
|
1381
|
-
|
|
1382
|
-
// override with any params
|
|
1383
|
-
for (var k in params) {
|
|
1384
|
-
var value = context.resolve(params[k]);
|
|
1385
|
-
if (value) {
|
|
1386
|
-
includeContextObject[k] = value;
|
|
1387
|
-
}
|
|
1388
|
-
}
|
|
1389
|
-
|
|
1390
|
-
// some additional overrides that we enforce
|
|
1391
|
-
var templateFilePaths = context.get("templateFilePaths");
|
|
1392
|
-
var newTemplateFilePaths = [];
|
|
1393
|
-
for (var r = 0; r < templateFilePaths.length; r++) {
|
|
1394
|
-
newTemplateFilePaths.push(templateFilePaths[r]);
|
|
1395
|
-
}
|
|
1396
|
-
newTemplateFilePaths.push(filePath);
|
|
1397
|
-
includeContextObject["templateFilePaths"] = newTemplateFilePaths;
|
|
1398
|
-
|
|
1399
|
-
// include the subcontext
|
|
1400
|
-
var subContext = context.push(includeContextObject);
|
|
1401
|
-
|
|
1402
|
-
dust.render(templatePath, subContext, function (err, out) {
|
|
1403
|
-
|
|
1404
|
-
if (err) {
|
|
1405
|
-
log("Error while rendering include for: " + templatePath + ", err: " + (err && err.message ? err.message : err));
|
|
1406
|
-
return end(chunk2, subContext, err);
|
|
1407
|
-
}
|
|
1408
|
-
|
|
1409
|
-
chunk2.write(out);
|
|
1410
|
-
end(chunk2, subContext);
|
|
1411
|
-
});
|
|
1412
|
-
});
|
|
1413
|
-
});
|
|
1414
|
-
};
|
|
1415
|
-
|
|
1416
|
-
/**
|
|
1417
|
-
* Handles behavior for @fragment.
|
|
1418
|
-
*
|
|
1419
|
-
* @param chunk
|
|
1420
|
-
* @param context
|
|
1421
|
-
* @param bodies
|
|
1422
|
-
* @param params
|
|
1423
|
-
*
|
|
1424
|
-
* @returns {*}
|
|
1425
|
-
* @private
|
|
1426
|
-
*/
|
|
1427
|
-
var handleFragment = r.handleFragment = function(chunk, context, bodies, params)
|
|
1428
|
-
{
|
|
1429
|
-
params = params || {};
|
|
1430
|
-
|
|
1431
|
-
var fragmentId = context.get("fragmentIdGenerator")();
|
|
1432
|
-
|
|
1433
|
-
var requirements = support.buildRequirements(context, {});
|
|
1434
|
-
|
|
1435
|
-
var finishHandler = function(context, err)
|
|
1436
|
-
{
|
|
1437
|
-
tracker.finish(context);
|
|
1438
|
-
};
|
|
1439
|
-
|
|
1440
|
-
return map(chunk, function(chunk2) {
|
|
1441
|
-
|
|
1442
|
-
// if we can serve this from the fragment cache, we do so
|
|
1443
|
-
support.loadFragment(context, fragmentId, requirements, function(err, fragmentText) {
|
|
1444
|
-
|
|
1445
|
-
// if we found a fragment, stream it back
|
|
1446
|
-
if (!err && fragmentText) {
|
|
1447
|
-
chunk2.write(fragmentText);
|
|
1448
|
-
return chunk2.end();
|
|
1449
|
-
}
|
|
1450
|
-
|
|
1451
|
-
// not cached, so run this puppy...
|
|
1452
|
-
|
|
1453
|
-
// TRACKER: START
|
|
1454
|
-
tracker.start(context, fragmentId, requirements);
|
|
1455
|
-
|
|
1456
|
-
var requirements = support.buildRequirements(context, {});
|
|
1457
|
-
|
|
1458
|
-
var newContext = context.push({});
|
|
1459
|
-
|
|
1460
|
-
support.renderFragment(newContext, fragmentId, requirements, chunk2, bodies, function(err) {
|
|
1461
|
-
finishHandler(newContext, err);
|
|
1462
|
-
});
|
|
1463
|
-
|
|
1464
|
-
});
|
|
1465
|
-
});
|
|
1466
|
-
};
|
|
1467
|
-
|
|
1468
|
-
r.util = util;
|
|
1469
|
-
r.map = support.map;
|
|
1470
|
-
r.end = support.end;
|
|
1471
|
-
r.resolveVariables = support.resolveVariables;
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
// pipeline
|
|
1475
|
-
|
|
1476
|
-
var _convertToArray = function(map, _done)
|
|
1477
|
-
{
|
|
1478
|
-
var array = [];
|
|
1479
|
-
|
|
1480
|
-
for (var i = 0; i < map.__keys().length; i++)
|
|
1481
|
-
{
|
|
1482
|
-
array.push(map[map.__keys()[i]]);
|
|
1483
|
-
}
|
|
1484
|
-
|
|
1485
|
-
// additional values
|
|
1486
|
-
array._totalRows = map.totalRows();
|
|
1487
|
-
array._offset = map.offset();
|
|
1488
|
-
|
|
1489
|
-
_done(array);
|
|
1490
|
-
};
|
|
1491
|
-
|
|
1492
|
-
var _filterWithAuthorityChecks = function(array, context, branch, role, _done)
|
|
1493
|
-
{
|
|
1494
|
-
if (!role) {
|
|
1495
|
-
return _done(array);
|
|
1496
|
-
}
|
|
1497
|
-
|
|
1498
|
-
var req = context.get("req");
|
|
1499
|
-
if (!req) {
|
|
1500
|
-
return _done(array);
|
|
1501
|
-
}
|
|
1502
|
-
|
|
1503
|
-
var user = req.user;
|
|
1504
|
-
if (!user) {
|
|
1505
|
-
return _done(array);
|
|
1506
|
-
}
|
|
1507
|
-
if (!user.domainId || !user.id) {
|
|
1508
|
-
return _done(array);
|
|
1509
|
-
}
|
|
1510
|
-
|
|
1511
|
-
var principalId = user.domainId + "/" + user.id;
|
|
1512
|
-
|
|
1513
|
-
// filter via authority checks
|
|
1514
|
-
var checks = [];
|
|
1515
|
-
for (var i = 0; i < array.length; i++)
|
|
1516
|
-
{
|
|
1517
|
-
checks.push({
|
|
1518
|
-
"permissionedId": array[i]._doc,
|
|
1519
|
-
"authorityId": role,
|
|
1520
|
-
"principalId": principalId
|
|
1521
|
-
});
|
|
1522
|
-
}
|
|
1523
|
-
|
|
1524
|
-
Chain(branch).checkNodeAuthorities(checks, function(results) {
|
|
1525
|
-
|
|
1526
|
-
// create a quick lookup map
|
|
1527
|
-
var resultsMap = {};
|
|
1528
|
-
for (var i = 0; i < results.length; i++)
|
|
1529
|
-
{
|
|
1530
|
-
resultsMap[results[i].permissionedId] = results[i].result;
|
|
1531
|
-
}
|
|
1532
|
-
|
|
1533
|
-
// now filter the array
|
|
1534
|
-
var i = 0;
|
|
1535
|
-
do
|
|
1536
|
-
{
|
|
1537
|
-
if (i < array.length)
|
|
1538
|
-
{
|
|
1539
|
-
var permissionedId = array[i]._doc;
|
|
1540
|
-
|
|
1541
|
-
if (resultsMap[permissionedId])
|
|
1542
|
-
{
|
|
1543
|
-
i++;
|
|
1544
|
-
}
|
|
1545
|
-
else
|
|
1546
|
-
{
|
|
1547
|
-
array.splice(i, 1);
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1551
|
-
while (i < array.length);
|
|
1552
|
-
|
|
1553
|
-
_done(array);
|
|
1554
|
-
});
|
|
1555
|
-
};
|
|
1556
|
-
|
|
1557
|
-
var _enhanceQueryResults = function(array, _done)
|
|
1558
|
-
{
|
|
1559
|
-
for (var i = 0; i < array.length; i++)
|
|
1560
|
-
{
|
|
1561
|
-
// enhance node information
|
|
1562
|
-
enhanceNode(array[i]);
|
|
1563
|
-
}
|
|
1564
|
-
|
|
1565
|
-
_done(array);
|
|
1566
|
-
};
|
|
1567
|
-
|
|
1568
|
-
var _trackQueryResults = function(array, context, _done)
|
|
1569
|
-
{
|
|
1570
|
-
for (var i = 0; i < array.length; i++)
|
|
1571
|
-
{
|
|
1572
|
-
// TRACKER - PRODUCES "node"
|
|
1573
|
-
tracker.produces(context, "node", array[i]._doc);
|
|
1574
|
-
}
|
|
1575
|
-
|
|
1576
|
-
_done(array);
|
|
1577
|
-
};
|
|
1578
|
-
|
|
1579
|
-
return r;
|
|
1580
|
-
};
|