[datafeed] properly call hooks for inlined relations on entity creation. Closes #2481156 stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 13 Sep 2012 17:26:15 +0200
branchstable
changeset 8547 f23ac525ddd1
parent 8546 3d2038d6f20d
child 8548 eeabc752c32e
[datafeed] properly call hooks for inlined relations on entity creation. Closes #2481156
server/repository.py
server/sources/datafeed.py
--- a/server/repository.py	Mon Sep 10 15:17:10 2012 +0200
+++ b/server/repository.py	Thu Sep 13 17:26:15 2012 +0200
@@ -120,6 +120,26 @@
                             {'x': eidfrom, 'y': eidto})
 
 
+def preprocess_inlined_relations(session, entity):
+    """when an entity is added, check if it has some inlined relation which
+    requires to be extrated for proper call hooks
+    """
+    relations = []
+    activeintegrity = session.is_hook_category_activated('activeintegrity')
+    eschema = entity.e_schema
+    for attr in entity.cw_edited.iterkeys():
+        rschema = eschema.subjrels[attr]
+        if not rschema.final: # inlined relation
+            value = entity.cw_edited[attr]
+            relations.append((attr, value))
+            session.update_rel_cache_add(entity.eid, attr, value)
+            rdef = session.rtype_eids_rdef(attr, entity.eid, value)
+            if rdef.cardinality[1] in '1?' and activeintegrity:
+                with security_enabled(session, read=False):
+                    session.execute('DELETE X %s Y WHERE Y eid %%(y)s' % attr,
+                                    {'x': entity.eid, 'y': value})
+    return relations
+
 
 class NullEventBus(object):
     def publish(self, msg):
@@ -1353,7 +1373,6 @@
         entity._cw_is_saved = False # entity has an eid but is not yet saved
         # init edited_attributes before calling before_add_entity hooks
         entity.cw_edited = edited
-        eschema = entity.e_schema
         source = self.locate_etype_source(entity.__regid__)
         # allocate an eid to the entity before calling hooks
         entity.eid = self.system_source.create_eid(session)
@@ -1364,19 +1383,7 @@
         prefill_entity_caches(entity)
         if source.should_call_hooks:
             self.hm.call_hooks('before_add_entity', session, entity=entity)
-        relations = []
-        activeintegrity = session.is_hook_category_activated('activeintegrity')
-        for attr in edited.iterkeys():
-            rschema = eschema.subjrels[attr]
-            if not rschema.final: # inlined relation
-                value = edited[attr]
-                relations.append((attr, value))
-                session.update_rel_cache_add(entity.eid, attr, value)
-                rdef = session.rtype_eids_rdef(attr, entity.eid, value)
-                if rdef.cardinality[1] in '1?' and activeintegrity:
-                    with security_enabled(session, read=False):
-                        session.execute('DELETE X %s Y WHERE Y eid %%(y)s' % attr,
-                                        {'x': entity.eid, 'y': value})
+        relations = preprocess_inlined_relations(session, entity)
         edited.set_defaults()
         if session.is_hook_category_activated('integrity'):
             edited.check(creation=True)
--- a/server/sources/datafeed.py	Mon Sep 10 15:17:10 2012 +0200
+++ b/server/sources/datafeed.py	Thu Sep 13 17:26:15 2012 +0200
@@ -30,6 +30,7 @@
 from lxml import etree
 
 from cubicweb import RegistryNotFound, ObjectNotFound, ValidationError, UnknownEid
+from cubicweb.server.repository import preprocess_inlined_relations
 from cubicweb.server.sources import AbstractSource
 from cubicweb.appobject import AppObject
 
@@ -254,11 +255,20 @@
         """called by the repository after an entity stored here has been
         inserted in the system table.
         """
+        relations = preprocess_inlined_relations(session, entity)
         if session.is_hook_category_activated('integrity'):
             entity.cw_edited.check(creation=True)
         self.repo.system_source.add_entity(session, entity)
         entity.cw_edited.saved = entity._cw_is_saved = True
         sourceparams['parser'].after_entity_copy(entity, sourceparams)
+        # call hooks for inlined relations
+        call_hooks = self.repo.hm.call_hooks
+        if self.should_call_hooks:
+            for attr, value in relations:
+                call_hooks('before_add_relation', session,
+                           eidfrom=entity.eid, rtype=attr, eidto=value)
+                call_hooks('after_add_relation', session,
+                           eidfrom=entity.eid, rtype=attr, eidto=value)
 
     def source_cwuris(self, session):
         sql = ('SELECT extid, eid, type FROM entities, cw_source_relation '
@@ -399,6 +409,7 @@
                 entity.set_attributes(**attrs)
                 self.notify_updated(entity)
 
+
 class DataFeedXMLParser(DataFeedParser):
 
     def process(self, url, raise_on_error=False):