72 def __call__(self): |
72 def __call__(self): |
73 getattr(self, self.event)() |
73 getattr(self, self.event)() |
74 |
74 |
75 def checkrel_if_necessary(self, opcls, rtype, eid): |
75 def checkrel_if_necessary(self, opcls, rtype, eid): |
76 """check an equivalent operation has not already been added""" |
76 """check an equivalent operation has not already been added""" |
77 for op in self.cw_req.pending_operations: |
77 for op in self._cw.pending_operations: |
78 if isinstance(op, opcls) and op.rtype == rtype and op.eid == eid: |
78 if isinstance(op, opcls) and op.rtype == rtype and op.eid == eid: |
79 break |
79 break |
80 else: |
80 else: |
81 opcls(self.cw_req, rtype=rtype, eid=eid) |
81 opcls(self._cw, rtype=rtype, eid=eid) |
82 |
82 |
83 def after_add_entity(self): |
83 def after_add_entity(self): |
84 eid = self.entity.eid |
84 eid = self.entity.eid |
85 eschema = self.entity.e_schema |
85 eschema = self.entity.e_schema |
86 for rschema, targetschemas, x in eschema.relation_definitions(): |
86 for rschema, targetschemas, x in eschema.relation_definitions(): |
103 |
103 |
104 def before_delete_relation(self): |
104 def before_delete_relation(self): |
105 rtype = self.rtype |
105 rtype = self.rtype |
106 if rtype in DONT_CHECK_RTYPES_ON_DEL: |
106 if rtype in DONT_CHECK_RTYPES_ON_DEL: |
107 return |
107 return |
108 session = self.cw_req |
108 session = self._cw |
109 eidfrom, eidto = self.eidfrom, self.eidto |
109 eidfrom, eidto = self.eidfrom, self.eidto |
110 card = session.schema_rproperty(rtype, eidfrom, eidto, 'cardinality') |
110 card = session.schema_rproperty(rtype, eidfrom, eidto, 'cardinality') |
111 pendingrdefs = session.transaction_data.get('pendingrdefs', ()) |
111 pendingrdefs = session.transaction_data.get('pendingrdefs', ()) |
112 if (session.describe(eidfrom)[0], rtype, session.describe(eidto)[0]) in pendingrdefs: |
112 if (session.describe(eidfrom)[0], rtype, session.describe(eidto)[0]) in pendingrdefs: |
113 return |
113 return |
147 """ |
147 """ |
148 __id__ = 'checkconstraint' |
148 __id__ = 'checkconstraint' |
149 events = ('after_add_relation',) |
149 events = ('after_add_relation',) |
150 |
150 |
151 def __call__(self): |
151 def __call__(self): |
152 constraints = self.cw_req.schema_rproperty(self.rtype, self.eidfrom, self.eidto, |
152 constraints = self._cw.schema_rproperty(self.rtype, self.eidfrom, self.eidto, |
153 'constraints') |
153 'constraints') |
154 if constraints: |
154 if constraints: |
155 _CheckConstraintsOp(self.cw_req, constraints=constraints, |
155 _CheckConstraintsOp(self._cw, constraints=constraints, |
156 rdef=(self.eidfrom, self.rtype, self.eidto)) |
156 rdef=(self.eidfrom, self.rtype, self.eidto)) |
157 |
157 |
158 |
158 |
159 class CheckUniqueHook(IntegrityHook): |
159 class CheckUniqueHook(IntegrityHook): |
160 __id__ = 'checkunique' |
160 __id__ = 'checkunique' |
168 if val is None: |
168 if val is None: |
169 continue |
169 continue |
170 if eschema.subject_relation(attr).is_final() and \ |
170 if eschema.subject_relation(attr).is_final() and \ |
171 eschema.has_unique_values(attr): |
171 eschema.has_unique_values(attr): |
172 rql = '%s X WHERE X %s %%(val)s' % (entity.e_schema, attr) |
172 rql = '%s X WHERE X %s %%(val)s' % (entity.e_schema, attr) |
173 rset = self.cw_req.unsafe_execute(rql, {'val': val}) |
173 rset = self._cw.unsafe_execute(rql, {'val': val}) |
174 if rset and rset[0][0] != entity.eid: |
174 if rset and rset[0][0] != entity.eid: |
175 msg = self.cw_req._('the value "%s" is already used, use another one') |
175 msg = self._cw._('the value "%s" is already used, use another one') |
176 raise ValidationError(entity.eid, {attr: msg % val}) |
176 raise ValidationError(entity.eid, {attr: msg % val}) |
177 |
177 |
178 |
178 |
179 class _DelayedDeleteOp(hook.Operation): |
179 class _DelayedDeleteOp(hook.Operation): |
180 """delete the object of composite relation except if the relation |
180 """delete the object of composite relation except if the relation |
197 """ |
197 """ |
198 __id__ = 'deletecomposite' |
198 __id__ = 'deletecomposite' |
199 events = ('before_delete_relation',) |
199 events = ('before_delete_relation',) |
200 |
200 |
201 def __call__(self): |
201 def __call__(self): |
202 composite = self.cw_req.schema_rproperty(self.rtype, self.eidfrom, self.eidto, |
202 composite = self._cw.schema_rproperty(self.rtype, self.eidfrom, self.eidto, |
203 'composite') |
203 'composite') |
204 if composite == 'subject': |
204 if composite == 'subject': |
205 _DelayedDeleteOp(self.cw_req, eid=self.eidto, |
205 _DelayedDeleteOp(self._cw, eid=self.eidto, |
206 relation='Y %s X' % self.rtype) |
206 relation='Y %s X' % self.rtype) |
207 elif composite == 'object': |
207 elif composite == 'object': |
208 _DelayedDeleteOp(self.cw_req, eid=self.eidfrom, |
208 _DelayedDeleteOp(self._cw, eid=self.eidfrom, |
209 relation='X %s Y' % self.rtype) |
209 relation='X %s Y' % self.rtype) |
210 |
210 |
211 |
211 |
212 class DontRemoveOwnersGroupHook(IntegrityHook): |
212 class DontRemoveOwnersGroupHook(IntegrityHook): |
213 """delete the composed of a composite relation when this relation is deleted |
213 """delete the composed of a composite relation when this relation is deleted |
216 __select__ = IntegrityHook.__select__ & entity_implements('CWGroup') |
216 __select__ = IntegrityHook.__select__ & entity_implements('CWGroup') |
217 events = ('before_delete_entity', 'before_update_entity') |
217 events = ('before_delete_entity', 'before_update_entity') |
218 |
218 |
219 def __call__(self): |
219 def __call__(self): |
220 if self.event == 'before_delete_entity' and self.entity.name == 'owners': |
220 if self.event == 'before_delete_entity' and self.entity.name == 'owners': |
221 raise ValidationError(self.entity.eid, {None: self.cw_req._('can\'t be deleted')}) |
221 raise ValidationError(self.entity.eid, {None: self._cw._('can\'t be deleted')}) |
222 elif self.event == 'before_update_entity' and 'name' in self.entity.edited_attribute: |
222 elif self.event == 'before_update_entity' and 'name' in self.entity.edited_attribute: |
223 newname = self.entity.pop('name') |
223 newname = self.entity.pop('name') |
224 oldname = self.entity.name |
224 oldname = self.entity.name |
225 if oldname == 'owners' and newname != oldname: |
225 if oldname == 'owners' and newname != oldname: |
226 raise ValidationError(self.entity.eid, {'name': self.cw_req._('can\'t be changed')}) |
226 raise ValidationError(self.entity.eid, {'name': self._cw._('can\'t be changed')}) |
227 self.entity['name'] = newname |
227 self.entity['name'] = newname |
228 |
228 |
229 |
229 |
230 class TidyHtmlFields(IntegrityHook): |
230 class TidyHtmlFields(IntegrityHook): |
231 """tidy HTML in rich text strings""" |
231 """tidy HTML in rich text strings""" |
241 value = entity[attr] |
241 value = entity[attr] |
242 except KeyError: |
242 except KeyError: |
243 continue # no text to tidy |
243 continue # no text to tidy |
244 if isinstance(value, unicode): # filter out None and Binary |
244 if isinstance(value, unicode): # filter out None and Binary |
245 if getattr(entity, str(metaattr)) == 'text/html': |
245 if getattr(entity, str(metaattr)) == 'text/html': |
246 entity[attr] = soup2xhtml(value, self.cw_req.encoding) |
246 entity[attr] = soup2xhtml(value, self._cw.encoding) |
247 |
247 |
248 |
248 |
249 class StripCWUserLoginHook(IntegrityHook): |
249 class StripCWUserLoginHook(IntegrityHook): |
250 """ensure user logins are stripped""" |
250 """ensure user logins are stripped""" |
251 __id__ = 'stripuserlogin' |
251 __id__ = 'stripuserlogin' |