16 from cubicweb.server.hookhelper import (check_internal_entity, previous_state, |
16 from cubicweb.server.hookhelper import (check_internal_entity, previous_state, |
17 get_user_sessions, rproperty) |
17 get_user_sessions, rproperty) |
18 from cubicweb.server.repository import FTIndexEntityOp |
18 from cubicweb.server.repository import FTIndexEntityOp |
19 |
19 |
20 def relation_deleted(session, eidfrom, rtype, eidto): |
20 def relation_deleted(session, eidfrom, rtype, eidto): |
21 session.add_query_data('pendingrelations', (eidfrom, rtype, eidto)) |
21 session.transaction_data.setdefault('pendingrelations', []).append( |
|
22 (eidfrom, rtype, eidto)) |
22 |
23 |
23 |
24 |
24 # base meta-data handling ##################################################### |
25 # base meta-data handling ##################################################### |
25 |
26 |
26 def setctime_before_add_entity(session, entity): |
27 def setctime_before_add_entity(session, entity): |
39 entity['modification_date'] = datetime.now() |
40 entity['modification_date'] = datetime.now() |
40 |
41 |
41 class SetCreatorOp(PreCommitOperation): |
42 class SetCreatorOp(PreCommitOperation): |
42 |
43 |
43 def precommit_event(self): |
44 def precommit_event(self): |
44 if self.eid in self.session.query_data('pendingeids', ()): |
45 if self.eid in self.session.transaction_data.get('pendingeids', ()): |
45 # entity have been created and deleted in the same transaction |
46 # entity have been created and deleted in the same transaction |
46 return |
47 return |
47 ueid = self.session.user.eid |
48 ueid = self.session.user.eid |
48 execute = self.session.unsafe_execute |
49 execute = self.session.unsafe_execute |
49 if not execute('Any X WHERE X created_by U, X eid %(x)s', |
50 if not execute('Any X WHERE X created_by U, X eid %(x)s', |
136 has actually been redirected to another composite |
137 has actually been redirected to another composite |
137 """ |
138 """ |
138 |
139 |
139 def precommit_event(self): |
140 def precommit_event(self): |
140 session = self.session |
141 session = self.session |
141 if not self.eid in session.query_data('pendingeids', ()): |
142 if not self.eid in session.transaction_data.get('pendingeids', ()): |
142 etype = session.describe(self.eid)[0] |
143 etype = session.describe(self.eid)[0] |
143 session.unsafe_execute('DELETE %s X WHERE X eid %%(x)s, NOT %s' |
144 session.unsafe_execute('DELETE %s X WHERE X eid %%(x)s, NOT %s' |
144 % (etype, self.relation), |
145 % (etype, self.relation), |
145 {'x': self.eid}, 'x') |
146 {'x': self.eid}, 'x') |
146 |
147 |
164 """ |
165 """ |
165 def precommit_event(self): |
166 def precommit_event(self): |
166 eidfrom, rtype, eidto = self.rdef |
167 eidfrom, rtype, eidto = self.rdef |
167 # first check related entities have not been deleted in the same |
168 # first check related entities have not been deleted in the same |
168 # transaction |
169 # transaction |
169 pending = self.session.query_data('pendingeids', ()) |
170 pending = self.session.transaction_data.get('pendingeids', ()) |
170 if eidfrom in pending: |
171 if eidfrom in pending: |
171 return |
172 return |
172 if eidto in pending: |
173 if eidto in pending: |
173 return |
174 return |
174 for constraint in self.constraints: |
175 for constraint in self.constraints: |
215 """ |
216 """ |
216 eid, rtype = None, None |
217 eid, rtype = None, None |
217 |
218 |
218 def precommit_event(self): |
219 def precommit_event(self): |
219 # recheck pending eids |
220 # recheck pending eids |
220 if self.eid in self.session.query_data('pendingeids', ()): |
221 if self.eid in self.session.transaction_data.get('pendingeids', ()): |
221 return |
222 return |
222 if self.session.unsafe_execute(*self._rql()).rowcount < 1: |
223 if self.session.unsafe_execute(*self._rql()).rowcount < 1: |
223 etype = self.session.describe(self.eid)[0] |
224 etype = self.session.describe(self.eid)[0] |
224 msg = self.session._('at least one relation %(rtype)s is required on %(etype)s (%(eid)s)') |
225 msg = self.session._('at least one relation %(rtype)s is required on %(etype)s (%(eid)s)') |
225 raise ValidationError(self.eid, {self.rtype: msg % {'rtype': self.rtype, |
226 raise ValidationError(self.eid, {self.rtype: msg % {'rtype': self.rtype, |
272 checkrel_if_necessary(session, opcls, rschema.type, eid) |
273 checkrel_if_necessary(session, opcls, rschema.type, eid) |
273 |
274 |
274 def cardinalitycheck_before_del_relation(session, eidfrom, rtype, eidto): |
275 def cardinalitycheck_before_del_relation(session, eidfrom, rtype, eidto): |
275 """check cardinalities are satisfied""" |
276 """check cardinalities are satisfied""" |
276 card = rproperty(session, rtype, eidfrom, eidto, 'cardinality') |
277 card = rproperty(session, rtype, eidfrom, eidto, 'cardinality') |
277 pendingeids = session.query_data('pendingeids', ()) |
278 pendingeids = session.transaction_data.get('pendingeids', ()) |
278 if card[0] in '1+' and not eidfrom in pendingeids: |
279 if card[0] in '1+' and not eidfrom in pendingeids: |
279 checkrel_if_necessary(session, CheckSRelationOp, rtype, eidfrom) |
280 checkrel_if_necessary(session, CheckSRelationOp, rtype, eidfrom) |
280 if card[1] in '1+' and not eidto in pendingeids: |
281 if card[1] in '1+' and not eidto in pendingeids: |
281 checkrel_if_necessary(session, CheckORelationOp, rtype, eidto) |
282 checkrel_if_necessary(session, CheckORelationOp, rtype, eidto) |
282 |
283 |
421 entity = self.entity |
422 entity = self.entity |
422 rset = session.execute('Any S WHERE ET initial_state S, ET name %(name)s', |
423 rset = session.execute('Any S WHERE ET initial_state S, ET name %(name)s', |
423 {'name': str(entity.e_schema)}) |
424 {'name': str(entity.e_schema)}) |
424 # if there is an initial state and the entity's state is not set, |
425 # if there is an initial state and the entity's state is not set, |
425 # use the initial state as a default state |
426 # use the initial state as a default state |
426 pendingeids = session.query_data('pendingeids', ()) |
427 pendingeids = session.transaction_data.get('pendingeids', ()) |
427 if rset and not entity.eid in pendingeids and not entity.in_state: |
428 if rset and not entity.eid in pendingeids and not entity.in_state: |
428 session.unsafe_execute('SET X in_state S WHERE X eid %(x)s, S eid %(s)s', |
429 session.unsafe_execute('SET X in_state S WHERE X eid %(x)s, S eid %(s)s', |
429 {'x' : entity.eid, 's' : rset[0][0]}, 'x') |
430 {'x' : entity.eid, 's' : rset[0][0]}, 'x') |
430 |
431 |
431 |
432 |
503 # site wide properties |
504 # site wide properties |
504 ChangeCWPropertyOp(session, epropdict=session.vreg.eprop_values, |
505 ChangeCWPropertyOp(session, epropdict=session.vreg.eprop_values, |
505 key=key, value=value) |
506 key=key, value=value) |
506 |
507 |
507 def before_del_eproperty(session, eid): |
508 def before_del_eproperty(session, eid): |
508 for eidfrom, rtype, eidto in session.query_data('pendingrelations', ()): |
509 for eidfrom, rtype, eidto in session.transaction_data.get('pendingrelations', ()): |
509 if rtype == 'for_user' and eidfrom == eid: |
510 if rtype == 'for_user' and eidfrom == eid: |
510 # if for_user was set, delete has already been handled |
511 # if for_user was set, delete has already been handled |
511 break |
512 break |
512 else: |
513 else: |
513 key = session.execute('Any K WHERE P eid %(x)s, P pkey K', |
514 key = session.execute('Any K WHERE P eid %(x)s, P pkey K', |