1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
1 # copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
3 # |
3 # |
4 # This file is part of CubicWeb. |
4 # This file is part of CubicWeb. |
5 # |
5 # |
6 # CubicWeb is free software: you can redistribute it and/or modify it under the |
6 # CubicWeb is free software: you can redistribute it and/or modify it under the |
18 """Core hooks: check for data integrity according to the instance'schema |
18 """Core hooks: check for data integrity according to the instance'schema |
19 validity |
19 validity |
20 """ |
20 """ |
21 |
21 |
22 __docformat__ = "restructuredtext en" |
22 __docformat__ = "restructuredtext en" |
|
23 _ = unicode |
23 |
24 |
24 from threading import Lock |
25 from threading import Lock |
25 |
26 |
26 from yams.schema import role_name |
27 from cubicweb import validation_error |
27 |
|
28 from cubicweb import ValidationError |
|
29 from cubicweb.schema import (META_RTYPES, WORKFLOW_RTYPES, |
28 from cubicweb.schema import (META_RTYPES, WORKFLOW_RTYPES, |
30 RQLConstraint, RQLUniqueConstraint) |
29 RQLConstraint, RQLUniqueConstraint) |
31 from cubicweb.predicates import is_instance |
30 from cubicweb.predicates import is_instance |
32 from cubicweb.uilib import soup2xhtml |
31 from cubicweb.uilib import soup2xhtml |
33 from cubicweb.server import hook |
32 from cubicweb.server import hook |
85 continue |
84 continue |
86 if rtype in pendingrtypes: |
85 if rtype in pendingrtypes: |
87 continue |
86 continue |
88 if not session.execute(self.base_rql % rtype, {'x': eid}): |
87 if not session.execute(self.base_rql % rtype, {'x': eid}): |
89 etype = session.describe(eid)[0] |
88 etype = session.describe(eid)[0] |
90 _ = session._ |
|
91 msg = _('at least one relation %(rtype)s is required on ' |
89 msg = _('at least one relation %(rtype)s is required on ' |
92 '%(etype)s (%(eid)s)') |
90 '%(etype)s (%(eid)s)') |
93 msg %= {'rtype': _(rtype), 'etype': _(etype), 'eid': eid} |
91 raise validation_error(eid, {(rtype, self.role): msg}, |
94 raise ValidationError(eid, {role_name(rtype, self.role): msg}) |
92 {'rtype': rtype, 'etype': etype, 'eid': eid}, |
|
93 ['rtype', 'etype']) |
95 |
94 |
96 |
95 |
97 class _CheckSRelationOp(_CheckRequiredRelationOperation): |
96 class _CheckSRelationOp(_CheckRequiredRelationOperation): |
98 """check required subject relation""" |
97 """check required subject relation""" |
99 role = 'subject' |
98 role = 'subject' |
229 if val is None: |
228 if val is None: |
230 continue |
229 continue |
231 rql = '%s X WHERE X %s %%(val)s' % (entity.e_schema, attr) |
230 rql = '%s X WHERE X %s %%(val)s' % (entity.e_schema, attr) |
232 rset = self._cw.execute(rql, {'val': val}) |
231 rset = self._cw.execute(rql, {'val': val}) |
233 if rset and rset[0][0] != entity.eid: |
232 if rset and rset[0][0] != entity.eid: |
234 msg = self._cw._('the value "%s" is already used, use another one') |
233 msg = _('the value "%s" is already used, use another one') |
235 qname = role_name(attr, 'subject') |
234 raise validation_error(entity, {(attr, 'subject'): msg}, |
236 raise ValidationError(entity.eid, {qname: msg % val}) |
235 (val,)) |
237 |
236 |
238 |
237 |
239 class DontRemoveOwnersGroupHook(IntegrityHook): |
238 class DontRemoveOwnersGroupHook(IntegrityHook): |
240 """delete the composed of a composite relation when this relation is deleted |
239 """delete the composed of a composite relation when this relation is deleted |
241 """ |
240 """ |
244 events = ('before_delete_entity', 'before_update_entity') |
243 events = ('before_delete_entity', 'before_update_entity') |
245 |
244 |
246 def __call__(self): |
245 def __call__(self): |
247 entity = self.entity |
246 entity = self.entity |
248 if self.event == 'before_delete_entity' and entity.name == 'owners': |
247 if self.event == 'before_delete_entity' and entity.name == 'owners': |
249 msg = self._cw._('can\'t be deleted') |
248 raise validation_error(entity, {None: _("can't be deleted")}) |
250 raise ValidationError(entity.eid, {None: msg}) |
|
251 elif self.event == 'before_update_entity' \ |
249 elif self.event == 'before_update_entity' \ |
252 and 'name' in entity.cw_edited: |
250 and 'name' in entity.cw_edited: |
253 oldname, newname = entity.cw_edited.oldnewvalue('name') |
251 oldname, newname = entity.cw_edited.oldnewvalue('name') |
254 if oldname == 'owners' and newname != oldname: |
252 if oldname == 'owners' and newname != oldname: |
255 qname = role_name('name', 'subject') |
253 raise validation_error(entity, {('name', 'subject'): _("can't be changed")}) |
256 msg = self._cw._('can\'t be changed') |
|
257 raise ValidationError(entity.eid, {qname: msg}) |
|
258 |
254 |
259 |
255 |
260 class TidyHtmlFields(IntegrityHook): |
256 class TidyHtmlFields(IntegrityHook): |
261 """tidy HTML in rich text strings""" |
257 """tidy HTML in rich text strings""" |
262 __regid__ = 'htmltidy' |
258 __regid__ = 'htmltidy' |