# HG changeset patch # User Katia Saurfelt # Date 1398701481 -7200 # Node ID 6c6cd8c4b2567677a53373065832f279197d726d # Parent 59616edc20d7b07c251066803be9e8884c97d6f0 [entity] add a new `cw_linkable_rql` method * the new method returns the entities that are or may be related to the current one by the relation passed as an argument. Closes #3738011. diff -r 59616edc20d7 -r 6c6cd8c4b256 doc/3.19.rst --- a/doc/3.19.rst Mon Apr 07 12:03:31 2014 +0200 +++ b/doc/3.19.rst Mon Apr 28 18:11:21 2014 +0200 @@ -159,6 +159,10 @@ are encouraged to write an actual controller (e.g. using ``ajaxfunc``) instead of storing a closure in the session data. +* A new ``entity.cw_linkable_rql`` method provides the rql to fetch all entities + that are already or may be related to the current entity using the given + relation. + Deprecated Code Drops ---------------------- diff -r 59616edc20d7 -r 6c6cd8c4b256 entity.py --- 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) diff -r 59616edc20d7 -r 6c6cd8c4b256 test/unittest_entity.py --- a/test/unittest_entity.py Mon Apr 07 12:03:31 2014 +0200 +++ b/test/unittest_entity.py Mon Apr 28 18:11:21 2014 +0200 @@ -371,6 +371,13 @@ clear_cache(self.schema['EmailAddress'], 'get_rqlexprs') self.schema['EmailAddress'].permissions['read'] = rperms + def test_cw_linkable_rql(self): + with self.admin_access.web_request() as req: + email = req.execute('INSERT EmailAddress X: X address "hop"').get_entity(0, 0) + rql = email.cw_linkable_rql('use_email', 'CWUser', 'object')[0] + self.assertEqual(rql, 'Any S,AA,AB,AC,AD ORDERBY AA ' + 'WHERE O eid %(x)s, S is_instance_of CWUser, ' + 'S login AA, S firstname AB, S surname AC, S modification_date AD') def test_unrelated_rql_security_nonexistant(self): with self.new_access('anon').web_request() as req: