111 TRACED_OIDS = () |
111 TRACED_OIDS = () |
112 return traceback is None |
112 return traceback is None |
113 |
113 |
114 |
114 |
115 # abstract selectors ########################################################## |
115 # abstract selectors ########################################################## |
|
116 class AbstractSelectorMixIn(object): |
|
117 """convenience mix-in for selectors that depends on class attributes |
|
118 cf. `cubicweb.web.action.LinkToEntityAction` for instance |
|
119 """ |
|
120 def __call__(self, cls, *args, **kwargs): |
|
121 self.concretize(cls) |
|
122 super(AbstractSelectorMixIn, self).__call__(cls, *args, **kwargs) |
116 |
123 |
117 class EClassSelector(Selector): |
124 class EClassSelector(Selector): |
118 """abstract class for selectors working on the entity classes of the result |
125 """abstract class for selectors working on the entity classes of the result |
119 set. Its __call__ method has the following behaviour: |
126 set. Its __call__ method has the following behaviour: |
120 |
127 |
307 @lltrace |
314 @lltrace |
308 def one_etype_rset(cls, req, rset, row=None, col=0, *args, **kwargs): |
315 def one_etype_rset(cls, req, rset, row=None, col=0, *args, **kwargs): |
309 """accept result set where entities in the specified column (or 0) are all |
316 """accept result set where entities in the specified column (or 0) are all |
310 of the same type |
317 of the same type |
311 """ |
318 """ |
|
319 if rset is None: |
|
320 return 0 |
312 if len(rset.column_types(col)) != 1: |
321 if len(rset.column_types(col)) != 1: |
313 return 0 |
322 return 0 |
314 return 1 |
323 return 1 |
315 |
324 |
316 @objectify_selector |
325 @objectify_selector |
610 return self.target_etype in rschema.subjects(eschema) |
619 return self.target_etype in rschema.subjects(eschema) |
611 except KeyError, ex: |
620 except KeyError, ex: |
612 return 0 |
621 return 0 |
613 return 1 |
622 return 1 |
614 |
623 |
|
624 class abstract_relation_possible(AbstractSelectorMixIn, relation_possible): |
|
625 def __init__(self, action='read', once_is_enough=False): |
|
626 super(abstract_relation_possible, self).__init__(None, None, None, |
|
627 action, once_is_enough) |
|
628 |
|
629 def concretize(self, cls): |
|
630 self.rtype = cls.rtype |
|
631 self.role = role(cls) |
|
632 self.target_etype = getattr(cls, 'etype', None) |
615 |
633 |
616 class has_editable_relation(EntitySelector): |
634 class has_editable_relation(EntitySelector): |
617 """accept if some relations for an entity found in the result set is |
635 """accept if some relations for an entity found in the result set is |
618 editable by the logged user. |
636 editable by the logged user. |
619 |
637 |
656 return 0 |
674 return 0 |
657 elif not rschema.has_perm(req, 'add', toeid=entity.eid): |
675 elif not rschema.has_perm(req, 'add', toeid=entity.eid): |
658 return 0 |
676 return 0 |
659 return 1 |
677 return 1 |
660 |
678 |
661 |
679 class abstract_may_add_relation(AbstractSelectorMixIn, may_add_relation): |
|
680 def __init__(self, once_is_enough=False): |
|
681 super(abstract_may_add_relation, self).__init__(None, None, once_is_enough) |
|
682 |
|
683 def concretize(self, cls): |
|
684 self.rtype = cls.rtype |
|
685 self.role = role(cls) |
|
686 |
|
687 |
662 class has_related_entities(EntitySelector): |
688 class has_related_entities(EntitySelector): |
663 """accept if entity found in the result set has some linked entities using |
689 """accept if entity found in the result set has some linked entities using |
664 the specified relation (optionaly filtered according to the specified target |
690 the specified relation (optionaly filtered according to the specified target |
665 type). |
691 type). |
666 |
692 |
683 rset = entity.related(self.rtype, self.role) |
709 rset = entity.related(self.rtype, self.role) |
684 if self.target_etype: |
710 if self.target_etype: |
685 return any(x for x, in rset.description if x == self.target_etype) |
711 return any(x for x, in rset.description if x == self.target_etype) |
686 return bool(rset) |
712 return bool(rset) |
687 |
713 |
688 |
714 class abstract_has_related_entities(AbstractSelectorMixIn, has_related_entities): |
|
715 def __init__(self, once_is_enough=False): |
|
716 super(abstract_has_related_entities, self).__init__(None, None, |
|
717 None, once_is_enough) |
|
718 def concretize(self, cls): |
|
719 self.rtype = cls.rtype |
|
720 self.role = role(cls) |
|
721 self.target_etype = getattr(cls, 'etype', None) |
|
722 |
|
723 |
689 class has_permission(EntitySelector): |
724 class has_permission(EntitySelector): |
690 """accept if user has the permission to do the requested action on a result |
725 """accept if user has the permission to do the requested action on a result |
691 set entity. |
726 set entity. |
692 |
727 |
693 * if row is specified, return 1 if user has the permission on the entity |
728 * if row is specified, return 1 if user has the permission on the entity |