98 setattr(cls, rschema.type, SubjectRelation(rschema)) |
98 setattr(cls, rschema.type, SubjectRelation(rschema)) |
99 else: |
99 else: |
100 attr = 'reverse_%s' % rschema.type |
100 attr = 'reverse_%s' % rschema.type |
101 setattr(cls, attr, ObjectRelation(rschema)) |
101 setattr(cls, attr, ObjectRelation(rschema)) |
102 if mixins: |
102 if mixins: |
103 cls.__bases__ = tuple(mixins + [p for p in cls.__bases__ if not p is object]) |
103 # see etype class instantation in cwvreg.ETypeRegistry.etype_class method: |
104 cls.debug('plugged %s mixins on %s', mixins, etype) |
104 # due to class dumping, cls is the generated top level class with actual |
|
105 # user class as (only) parent. Since we want to be able to override mixins |
|
106 # method from this user class, we have to take care to insert mixins after that |
|
107 # class |
|
108 # |
|
109 # note that we don't plug mixins as user class parent since it causes pb |
|
110 # with some cases of entity classes inheritance. |
|
111 mixins.insert(0, cls.__bases__[0]) |
|
112 mixins += cls.__bases__[1:] |
|
113 cls.__bases__ = tuple(mixins) |
|
114 cls.info('plugged %s mixins on %s', mixins, cls) |
105 |
115 |
106 @classmethod |
116 @classmethod |
107 def fetch_rql(cls, user, restriction=None, fetchattrs=None, mainvar='X', |
117 def fetch_rql(cls, user, restriction=None, fetchattrs=None, mainvar='X', |
108 settype=True, ordermethod='fetch_order'): |
118 settype=True, ordermethod='fetch_order'): |
109 """return a rql to fetch all entities of the class type""" |
119 """return a rql to fetch all entities of the class type""" |
655 args = {} |
665 args = {} |
656 securitycheck_args = {} |
666 securitycheck_args = {} |
657 rdef = rtype.role_rdef(self.e_schema, targettype, role) |
667 rdef = rtype.role_rdef(self.e_schema, targettype, role) |
658 insertsecurity = (rdef.has_local_role('add') and not |
668 insertsecurity = (rdef.has_local_role('add') and not |
659 rdef.has_perm(self._cw, 'add', **securitycheck_args)) |
669 rdef.has_perm(self._cw, 'add', **securitycheck_args)) |
|
670 # XXX consider constraint.mainvars to check if constraint apply |
660 if vocabconstraints: |
671 if vocabconstraints: |
661 # RQLConstraint is a subclass for RQLVocabularyConstraint, so they |
672 # RQLConstraint is a subclass for RQLVocabularyConstraint, so they |
662 # will be included as well |
673 # will be included as well |
663 restriction += [cstr.restriction for cstr in rdef.constraints |
674 restriction += [cstr.restriction for cstr in rdef.constraints |
664 if isinstance(cstr, RQLVocabularyConstraint)] |
675 if isinstance(cstr, RQLVocabularyConstraint)] |
775 else: |
786 else: |
776 self._cw.execute('SET %s WHERE X eid %%(x)s' % ','.join(relations), |
787 self._cw.execute('SET %s WHERE X eid %%(x)s' % ','.join(relations), |
777 kwargs, 'x') |
788 kwargs, 'x') |
778 |
789 |
779 def set_relations(self, _cw_unsafe=False, **kwargs): |
790 def set_relations(self, _cw_unsafe=False, **kwargs): |
|
791 """add relations to the given object. To set a relation where this entity |
|
792 is the object of the relation, use 'reverse_'<relation> as argument name. |
|
793 |
|
794 Values may be an entity, a list of entity, or None (meaning that all |
|
795 relations of the given type from or to this object should be deleted). |
|
796 """ |
780 if _cw_unsafe: |
797 if _cw_unsafe: |
781 execute = self.req.unsafe_execute |
798 execute = self.req.unsafe_execute |
782 else: |
799 else: |
783 execute = self.req.execute |
800 execute = self.req.execute |
|
801 # XXX update cache |
784 for attr, values in kwargs.iteritems(): |
802 for attr, values in kwargs.iteritems(): |
785 if attr.startswith('reverse_'): |
803 if attr.startswith('reverse_'): |
786 restr = 'Y %s X' % attr[len('reverse_'):] |
804 restr = 'Y %s X' % attr[len('reverse_'):] |
787 else: |
805 else: |
788 restr = 'X %s Y' % attr |
806 restr = 'X %s Y' % attr |
|
807 if values is None: |
|
808 execute('DELETE %s WHERE X eid %%(x)s' % restr, |
|
809 {'x': self.eid}, 'x') |
|
810 continue |
789 if not isinstance(values, (tuple, list, set, frozenset)): |
811 if not isinstance(values, (tuple, list, set, frozenset)): |
790 values = (values,) |
812 values = (values,) |
791 execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % ( |
813 execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % ( |
792 restr, ','.join(str(r.eid) for r in values)), |
814 restr, ','.join(str(r.eid) for r in values)), |
793 {'x': self.eid}, 'x') |
815 {'x': self.eid}, 'x') |