entity.py
changeset 9712 6c6cd8c4b256
parent 9635 aaf099172bb9
child 9774 b7b71be569cf
--- a/entity.py	Mon Apr 07 12:03:31 2014 +0200
+++ b/entity.py	Mon Apr 28 18:11:21 2014 +0200
@@ -1074,6 +1074,25 @@
 
     # generic vocabulary methods ##############################################
 
+    def cw_linkable_rql(self, rtype, targettype, role, ordermethod=None,
+                        vocabconstraints=True, lt_infos={}, limit=None):
+        """build a rql to fetch targettype entities either related or unrelated
+        to this entity using (rtype, role) relation.
+
+        Consider relation permissions so that returned entities may be actually
+        linked by `rtype`.
+
+        `lt_infos` are supplementary informations, usually coming from __linkto
+        parameter, that can help further restricting the results in case current
+        entity is not yet created. It is a dict describing entities the current
+        entity will be linked to, which keys are (rtype, role) tuples and values
+        are a list of eids.
+        """
+        return self._cw_compute_linkable_rql(rtype, targettype, role, ordermethod=None,
+                                             vocabconstraints=vocabconstraints,
+                                             lt_infos=lt_infos, limit=limit,
+                                             unrelated_only=False)
+
     def cw_unrelated_rql(self, rtype, targettype, role, ordermethod=None,
                          vocabconstraints=True, lt_infos={}, limit=None):
         """build a rql to fetch `targettype` entities unrelated to this entity
@@ -1088,6 +1107,21 @@
         entity will be linked to, which keys are (rtype, role) tuples and values
         are a list of eids.
         """
+        return self._cw_compute_linkable_rql(rtype, targettype, role, ordermethod=None,
+                                             vocabconstraints=vocabconstraints,
+                                             lt_infos=lt_infos, limit=limit,
+                                             unrelated_only=True)
+
+    def _cw_compute_linkable_rql(self, rtype, targettype, role, ordermethod=None,
+                                 vocabconstraints=True, lt_infos={}, limit=None,
+                                 unrelated_only=False):
+        """build a rql to fetch `targettype` entities that may be related to
+        this entity using the (rtype, role) relation.
+
+        By default (unrelated_only=False), this includes the already linked
+        entities as well as the unrelated ones. If `unrelated_only` is True, the
+        rql filters out the already related entities.
+        """
         ordermethod = ordermethod or 'fetch_unrelated_order'
         rschema = self._cw.vreg.schema.rschema(rtype)
         rdef = rschema.role_rdef(self.e_schema, targettype, role)
@@ -1116,7 +1150,7 @@
             else:
                 rel = make_relation(searchedvar, rtype, (variable,), VariableRef)
             select.add_restriction(Not(rel))
-        elif self.has_eid():
+        elif self.has_eid() and unrelated_only:
             # elif we have an eid, we don't want a target entity which is
             # already linked to ourself through this relation
             rel = make_relation(subjvar, rtype, (objvar,), VariableRef)