7 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses |
7 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses |
8 """ |
8 """ |
9 __docformat__ = "restructuredtext en" |
9 __docformat__ = "restructuredtext en" |
10 |
10 |
11 from threading import Lock |
11 from threading import Lock |
|
12 |
|
13 from yams.schema import role_name |
12 |
14 |
13 from cubicweb import ValidationError |
15 from cubicweb import ValidationError |
14 from cubicweb.schema import RQLConstraint, RQLUniqueConstraint |
16 from cubicweb.schema import RQLConstraint, RQLUniqueConstraint |
15 from cubicweb.selectors import implements |
17 from cubicweb.selectors import implements |
16 from cubicweb.uilib import soup2xhtml |
18 from cubicweb.uilib import soup2xhtml |
71 if self.session.execute(*self._rql()).rowcount < 1: |
73 if self.session.execute(*self._rql()).rowcount < 1: |
72 etype = self.session.describe(self.eid)[0] |
74 etype = self.session.describe(self.eid)[0] |
73 _ = self.session._ |
75 _ = self.session._ |
74 msg = _('at least one relation %(rtype)s is required on %(etype)s (%(eid)s)') |
76 msg = _('at least one relation %(rtype)s is required on %(etype)s (%(eid)s)') |
75 msg %= {'rtype': _(self.rtype), 'etype': _(etype), 'eid': self.eid} |
77 msg %= {'rtype': _(self.rtype), 'etype': _(etype), 'eid': self.eid} |
76 raise ValidationError(self.eid, {self.rtype: msg}) |
78 qname = role_name(self.rtype, self.role) |
|
79 raise ValidationError(self.eid, {qname: msg}) |
77 |
80 |
78 def commit_event(self): |
81 def commit_event(self): |
79 pass |
82 pass |
80 |
83 |
81 def _rql(self): |
84 def _rql(self): |
82 raise NotImplementedError() |
85 raise NotImplementedError() |
83 |
86 |
84 |
87 |
85 class _CheckSRelationOp(_CheckRequiredRelationOperation): |
88 class _CheckSRelationOp(_CheckRequiredRelationOperation): |
86 """check required subject relation""" |
89 """check required subject relation""" |
|
90 role = 'subject' |
87 def _rql(self): |
91 def _rql(self): |
88 return 'Any O WHERE S eid %%(x)s, S %s O' % self.rtype, {'x': self.eid}, 'x' |
92 return 'Any O WHERE S eid %%(x)s, S %s O' % self.rtype, {'x': self.eid}, 'x' |
89 |
93 |
90 |
94 |
91 class _CheckORelationOp(_CheckRequiredRelationOperation): |
95 class _CheckORelationOp(_CheckRequiredRelationOperation): |
92 """check required object relation""" |
96 """check required object relation""" |
|
97 role = 'object' |
93 def _rql(self): |
98 def _rql(self): |
94 return 'Any S WHERE O eid %%(x)s, S %s O' % self.rtype, {'x': self.eid}, 'x' |
99 return 'Any S WHERE O eid %%(x)s, S %s O' % self.rtype, {'x': self.eid}, 'x' |
95 |
100 |
96 |
101 |
97 class IntegrityHook(hook.Hook): |
102 class IntegrityHook(hook.Hook): |
223 continue |
228 continue |
224 rql = '%s X WHERE X %s %%(val)s' % (entity.e_schema, attr) |
229 rql = '%s X WHERE X %s %%(val)s' % (entity.e_schema, attr) |
225 rset = self._cw.execute(rql, {'val': val}) |
230 rset = self._cw.execute(rql, {'val': val}) |
226 if rset and rset[0][0] != entity.eid: |
231 if rset and rset[0][0] != entity.eid: |
227 msg = self._cw._('the value "%s" is already used, use another one') |
232 msg = self._cw._('the value "%s" is already used, use another one') |
228 raise ValidationError(entity.eid, {attr: msg % val}) |
233 qname = role_name(attr, 'subject') |
|
234 raise ValidationError(entity.eid, {qname: msg % val}) |
229 |
235 |
230 |
236 |
231 class DontRemoveOwnersGroupHook(IntegrityHook): |
237 class DontRemoveOwnersGroupHook(IntegrityHook): |
232 """delete the composed of a composite relation when this relation is deleted |
238 """delete the composed of a composite relation when this relation is deleted |
233 """ |
239 """ |
235 __select__ = IntegrityHook.__select__ & implements('CWGroup') |
241 __select__ = IntegrityHook.__select__ & implements('CWGroup') |
236 events = ('before_delete_entity', 'before_update_entity') |
242 events = ('before_delete_entity', 'before_update_entity') |
237 |
243 |
238 def __call__(self): |
244 def __call__(self): |
239 if self.event == 'before_delete_entity' and self.entity.name == 'owners': |
245 if self.event == 'before_delete_entity' and self.entity.name == 'owners': |
240 raise ValidationError(self.entity.eid, {None: self._cw._('can\'t be deleted')}) |
246 msg = self._cw._('can\'t be deleted') |
241 elif self.event == 'before_update_entity' and 'name' in self.entity.edited_attributes: |
247 raise ValidationError(self.entity.eid, {None: msg}) |
|
248 elif self.event == 'before_update_entity' and \ |
|
249 'name' in self.entity.edited_attributes: |
242 newname = self.entity.pop('name') |
250 newname = self.entity.pop('name') |
243 oldname = self.entity.name |
251 oldname = self.entity.name |
244 if oldname == 'owners' and newname != oldname: |
252 if oldname == 'owners' and newname != oldname: |
245 raise ValidationError(self.entity.eid, {'name': self._cw._('can\'t be changed')}) |
253 qname = role_name('name', 'subject') |
|
254 msg = self._cw._('can\'t be changed') |
|
255 raise ValidationError(self.entity.eid, {qname: msg}) |
246 self.entity['name'] = newname |
256 self.entity['name'] = newname |
247 |
257 |
248 |
258 |
249 class TidyHtmlFields(IntegrityHook): |
259 class TidyHtmlFields(IntegrityHook): |
250 """tidy HTML in rich text strings""" |
260 """tidy HTML in rich text strings""" |