73 class RqlQuery(object): |
73 class RqlQuery(object): |
74 def __init__(self): |
74 def __init__(self): |
75 self.edited = [] |
75 self.edited = [] |
76 self.restrictions = [] |
76 self.restrictions = [] |
77 self.kwargs = {} |
77 self.kwargs = {} |
|
78 self.canceled = False |
78 |
79 |
79 def __repr__(self): |
80 def __repr__(self): |
80 return ('Query <edited=%r restrictions=%r kwargs=%r>' % ( |
81 return ('Query <edited=%r restrictions=%r kwargs=%r>' % ( |
81 self.edited, self.restrictions, self.kwargs)) |
82 self.edited, self.restrictions, self.kwargs)) |
82 |
83 |
83 def insert_query(self, etype): |
84 def insert_query(self, etype): |
|
85 assert not self.canceled |
84 if self.edited: |
86 if self.edited: |
85 rql = 'INSERT %s X: %s' % (etype, ','.join(self.edited)) |
87 rql = 'INSERT %s X: %s' % (etype, ','.join(self.edited)) |
86 else: |
88 else: |
87 rql = 'INSERT %s X' % etype |
89 rql = 'INSERT %s X' % etype |
88 if self.restrictions: |
90 if self.restrictions: |
89 rql += ' WHERE %s' % ','.join(self.restrictions) |
91 rql += ' WHERE %s' % ','.join(self.restrictions) |
90 return rql |
92 return rql |
91 |
93 |
92 def update_query(self, eid): |
94 def update_query(self, eid): |
|
95 assert not self.canceled |
93 varmaker = rqlvar_maker() |
96 varmaker = rqlvar_maker() |
94 var = varmaker.next() |
97 var = varmaker.next() |
95 while var in self.kwargs: |
98 while var in self.kwargs: |
96 var = varmaker.next() |
99 var = varmaker.next() |
97 rql = 'SET %s WHERE X eid %%(%s)s' % (','.join(self.edited), var) |
100 rql = 'SET %s WHERE X eid %%(%s)s' % (','.join(self.edited), var) |
266 self.handle_formfield(form, field, rqlquery) |
269 self.handle_formfield(form, field, rqlquery) |
267 # if there are some inlined field which were waiting for this entity's |
270 # if there are some inlined field which were waiting for this entity's |
268 # creation, add relevant data to the rqlquery |
271 # creation, add relevant data to the rqlquery |
269 for form_, field in req.data['pending_inlined'].pop(entity.eid, ()): |
272 for form_, field in req.data['pending_inlined'].pop(entity.eid, ()): |
270 rqlquery.set_inlined(field.name, form_.edited_entity.eid) |
273 rqlquery.set_inlined(field.name, form_.edited_entity.eid) |
271 if self.errors: |
274 if not rqlquery.canceled: |
272 errors = dict((f.role_name(), unicode(ex)) for f, ex in self.errors) |
275 if self.errors: |
273 raise ValidationError(valerror_eid(entity.eid), errors) |
276 errors = dict((f.role_name(), unicode(ex)) for f, ex in self.errors) |
274 if eid is None: # creation or copy |
277 raise ValidationError(valerror_eid(entity.eid), errors) |
275 entity.eid = eid = self._insert_entity(etype, formparams['eid'], rqlquery) |
278 if eid is None: # creation or copy |
276 elif rqlquery.edited: # edition of an existant entity |
279 entity.eid = eid = self._insert_entity(etype, formparams['eid'], rqlquery) |
277 self._update_entity(eid, rqlquery) |
280 elif rqlquery.edited: # edition of an existant entity |
|
281 self._update_entity(eid, rqlquery) |
|
282 else: |
|
283 self.errors = [] |
278 if is_main_entity: |
284 if is_main_entity: |
279 self.notify_edited(entity) |
285 self.notify_edited(entity) |
280 if '__delete' in formparams: |
286 if '__delete' in formparams: |
281 # XXX deprecate? |
287 # XXX deprecate? |
282 todelete = req.list_form_param('__delete', formparams, pop=True) |
288 todelete = req.list_form_param('__delete', formparams, pop=True) |
313 |
319 |
314 unlinked_eids = origvalues - value |
320 unlinked_eids = origvalues - value |
315 if unlinked_eids: |
321 if unlinked_eids: |
316 # Special handling of composite relation removal |
322 # Special handling of composite relation removal |
317 self.handle_composite_removal( |
323 self.handle_composite_removal( |
318 form, field, unlinked_eids) |
324 form, field, unlinked_eids, rqlquery) |
319 |
325 |
320 if rschema.inlined and rqlquery is not None and field.role == 'subject': |
326 if rschema.inlined and rqlquery is not None and field.role == 'subject': |
321 self.handle_inlined_relation(form, field, value, origvalues, rqlquery) |
327 self.handle_inlined_relation(form, field, value, origvalues, rqlquery) |
322 elif form.edited_entity.has_eid(): |
328 elif form.edited_entity.has_eid(): |
323 self.handle_relation(form, field, value, origvalues) |
329 self.handle_relation(form, field, value, origvalues) |
325 form._cw.data['pending_others'].add( (form, field) ) |
331 form._cw.data['pending_others'].add( (form, field) ) |
326 |
332 |
327 except ProcessFormError as exc: |
333 except ProcessFormError as exc: |
328 self.errors.append((field, exc)) |
334 self.errors.append((field, exc)) |
329 |
335 |
330 def handle_composite_removal(self, form, field, removed_values): |
336 def handle_composite_removal(self, form, field, removed_values, rqlquery): |
331 """ |
337 """ |
332 In EditController-handled forms, when the user removes a composite |
338 In EditController-handled forms, when the user removes a composite |
333 relation, it triggers the removal of the related entity in the |
339 relation, it triggers the removal of the related entity in the |
334 composite. This is where this happens. |
340 composite. This is where this happens. |
335 |
341 |
347 targettype = form.edited_entity.e_schema |
353 targettype = form.edited_entity.e_schema |
348 to_be_removed = unlinked_entity |
354 to_be_removed = unlinked_entity |
349 else: |
355 else: |
350 targettype = unlinked_entity.e_schema |
356 targettype = unlinked_entity.e_schema |
351 to_be_removed = form.edited_entity |
357 to_be_removed = form.edited_entity |
|
358 self.info('Edition of %s is cancelled (deletion requested)', |
|
359 to_be_removed) |
|
360 rqlquery.canceled = True |
352 self.info('Scheduling removal of %s as composite relation ' |
361 self.info('Scheduling removal of %s as composite relation ' |
353 '%s was removed', to_be_removed, rdef) |
362 '%s was removed', to_be_removed, rdef) |
354 form._cw.data['pending_composite_delete'].add( |
363 form._cw.data['pending_composite_delete'].add( |
355 (to_be_removed, field.name, |
364 (to_be_removed, field.name, |
356 neg_role(rdef.composite), targettype)) |
365 neg_role(rdef.composite), targettype)) |