[datafeed] properly call hooks for inlined relations on entity creation. Closes #2481156
--- 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):