]> git.proxmox.com Git - sencha-touch.git/blob - src/src/ux/parse/Proxy.js
import Sencha Touch 2.4.2 source
[sencha-touch.git] / src / src / ux / parse / Proxy.js
1 Ext.define('Ext.ux.parse.Proxy', {
2 extend: 'Ext.data.proxy.Server',
3 alias: 'proxy.parse',
4 requires: ['Ext.data.Request', 'Ext.ux.parse.Reader', 'Ext.ux.parse.Helper'],
5
6 config: {
7 reader: "parse",
8 loadAllPointers: false
9 },
10
11 checkParse: function() {
12 if (window.Parse && window.Parse.applicationId) return true;
13
14 if (window.Parse) {
15 // <debug>
16 Ext.Logger.warn('You must set your Parse ApplicationID prior to calling any Proxy Functions');
17 // </debug>
18 } else {
19 // <debug>
20 Ext.Logger.warn('Parse not found, please include parse in your app.json or via script tag');
21 // </debug>
22 }
23 return false;
24 },
25
26 create: function(operation, callback, scope) {
27 this.write(operation, callback, scope);
28 },
29 read: function(operation, callback, scope) {
30 if (this.checkParse() === false) return;
31 var me = this,
32 model = operation.getModel(),
33 parseClassName = model.getParseClass(),
34 cb = me.createCallback(operation, callback, scope),
35 filters = operation.getFilters(),
36 limit = operation.getLimit(),
37 sorters = operation.getSorters(),
38 params = operation.getParams() || {},
39 page = operation.getPage(),
40 queryModifier = params.queryModifier,
41 queryModifierScope = params.queryModifierScope,
42 query = params.query || ParseHelper.getQuery(parseClassName);
43
44 if (Ext.isFunction(query)) {
45 query = query.call(params.queryScope || this);
46 }
47
48 // Pointers are a type of relational data in parse, this include all associations
49 // that are hasMany or hasOne in the query
50 // Many to Many relationships will not work through this method
51
52 //Applying pointers will automatically apply field restrictions so only data used is returned
53 me.applyPointers(query, model, params.loadAllPointers);
54
55 if (params && params.query) {
56 query.find({
57 success: function(response) {
58 cb.apply(me, [true, response]);
59 },
60 error: function(response, error) {
61 cb.apply(me, false, response, error);
62 }
63 });
64 } else if (params && params.id) {
65 query.get(params.id, {
66 success: function(response) {
67 cb.apply(me, [true, response]);
68 },
69 error: function(response, error) {
70 cb.apply(me, [false, response, error]);
71 }
72 });
73 } else {
74 me.applyFilters(query, filters);
75 me.applyLimit(query, limit);
76 me.applySorters(query, sorters);
77 me.applyQueryModifier(query, queryModifier, queryModifierScope);
78
79 if (limit && page) {
80 me.applySkip(query, (page - 1) * limit);
81 }
82
83 var collection = query.collection();
84 collection.fetch({
85 success: function(response) {
86 cb.apply(me, [true, response]);
87 },
88 error: function(response, error) {
89 cb.apply(me, false, response, error);
90 }
91 });
92 }
93 },
94 update: function(operation, callback, scope) {
95 this.write(operation, callback, scope);
96 },
97 destroy: function(operation, callback, scope) {
98 this.write(operation, callback, scope);
99 },
100
101 write: function(operation, callback, scope) {
102 if (this.checkParse() === false) return;
103 var queue = Ext.Array.clone(operation.getRecords()),
104 me = this,
105 models = [],
106 action = operation.getAction(),
107 fn = action === "destroy" ? Parse.Object.destroyAll : Parse.Object.saveAll,
108 cb = me.createCallback(operation, callback, scope);
109
110 Ext.Array.forEach(queue, function(item) {
111 if (item.isParseModel) {
112 models.push(item.getParseObject());
113 }
114 });
115
116 fn(models, {
117 success: function(response) {
118 if (action == "destroy") {
119 cb.apply(me, [true, models]);
120 } else {
121 cb.apply(me, [true, response]);
122 }
123 },
124 error: function(error) {
125 cb.apply(me, [false, [], error]);
126 }
127 });
128 },
129
130 batch: function(options) {
131 var me = this,
132 operations = options.operations,
133 complete = options.listeners && options.listeners.complete ? options.listeners.complete : null,
134 completeScope = options.listeners && options.listeners.scope ? options.listeners.scope : null,
135 model = me.getModel(),
136 createRecords = operations.create || [],
137 updateRecords = operations.update || [],
138 destroyRecords = operations.destroy || [],
139 createOperation = new Ext.data.Operation({
140 action: "create",
141 records: createRecords,
142 model: model
143 }),
144 updateOperation = new Ext.data.Operation({
145 action: "update",
146 records: updateRecords,
147 model: model
148 }),
149 destroyOperation = new Ext.data.Operation({
150 action: "destroy",
151 records: destroyRecords,
152 model: model
153 }),
154 queue = [createOperation, updateOperation, destroyOperation],
155 batch = {operations:Ext.Array.clone(queue), hasException: false},
156 operation, fn,
157 processQueue = function() {
158 operation = queue.shift();
159 if (operation) {
160 if (operation.getRecords().length > 0) {
161 fn = me[operation.getAction()];
162 fn.call(me, operation, function(operation) {
163 if (operation.hasException()) {
164 batch.hasException = true
165 }
166 processQueue();
167 }, me);
168 } else {
169 processQueue();
170 }
171 } else {
172 if(complete) {
173 complete.apply(completeScope, [batch]);
174 }
175 me.onBatchComplete.apply(me, [options, batch]);
176 }
177 };
178
179 processQueue();
180 },
181
182 createCallback: function(operation, callback, scope) {
183 var me = this;
184 return function(success, response, error) {
185 if (!success) response = error;
186 me.processResponse(success, operation, {}, response, callback, scope);
187 };
188 },
189
190 applyFields: function(query, model) {
191 var name = model.getParseClass(),
192 fields = model.getFields(),
193 include;
194
195 fields.each(function(field) {
196 include = name + "." + field.getName();
197 query.include(include);
198 });
199 },
200
201 applyPointers: function(query, model, force) {
202 var me = this,
203 included = [model.getParseClass()],
204 processedModels = [],
205 associations, aModel, aName, aType, aInclude,
206 loadPointers = (force === true || this.getLoadAllPointers() === true);
207
208 function applyRecursivePointers(model) {
209 if (processedModels.indexOf(model) >= 0) return;
210 processedModels.push(model);
211 me.applyFields(query, model);
212
213 associations = model.getAssociations();
214 associations.each(function(association) {
215 aModel = association.getAssociatedModel();
216 aName = association.getName();
217 aType = association.getType();
218 aInclude = aType === "pointer" ? association.getInclude() : false;
219 if ((aInclude || loadPointers) && (aType === "pointer" && included.indexOf(aName) === -1)) {
220 query.include(aName);
221 included.push(aName);
222 }
223 applyRecursivePointers(aModel);
224 })
225 }
226
227 applyRecursivePointers(model);
228 },
229
230 applyFilters: function(query, filters) {
231 if (filters) {
232 var property, value, anyMatch, caseSensitive;
233 Ext.Array.forEach(filters, function(item) {
234 property = item.getProperty();
235 value = item.getValue();
236 anyMatch = item.getAnyMatch();
237 caseSensitive = item.getCaseSensitive();
238
239 if (Ext.isString(value) && caseSensitive && anyMatch) {
240 if (anyMatch) {
241 query.contains(property, value);
242 } else {
243 query.equalTo(property, value);
244 }
245 } else if (Ext.isString(value)) {
246 value = new RegExp((!anyMatch ? "^" : "") + value);
247 }
248
249 if (value instanceof RegExp) {
250 console.log("RegExp");
251 query.matches(property, value, !caseSensitive ? "i" : "");
252 }
253 });
254 }
255 },
256
257 applyLimit: function(query, limit) {
258 query.limit(limit);
259 },
260
261 applySkip: function(query, skip) {
262 query.skip(skip);
263 },
264
265 applyQueryModifier: function(query, modifier, scope) {
266 if (modifier && Ext.isFunction(modifier)) {
267 modifier.call(scope || this, query);
268 }
269 },
270
271 applySorters: function(query, sorters) {
272 if (sorters) {
273 var property, direction;
274 Ext.Array.forEach(filters, function(item) {
275 property = item.getProperty();
276 direction = item.getDirection();
277 if (direction === "DESC") {
278 query.descending(property);
279 } else {
280 query.ascending(property);
281 }
282 });
283 }
284 },
285
286 setException: function(operation, response) {
287 if (Ext.isObject(response)) {
288 operation.setException({
289 status: response.code,
290 statusText: response.message
291 });
292 }
293 }
294 });