hooks/integrity.py
changeset 5048 bf8a53a11b6d
parent 5030 5238d9a8dfee
child 5060 ee3b856e1406
equal deleted inserted replaced
5047:ed048e317eae 5048:bf8a53a11b6d
     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"""