hooks/metadata.py
branchstable
changeset 7677 134613d3b353
parent 7543 570522300e22
child 7683 a21e24831ae4
equal deleted inserted replaced
7670:6397a9051f65 7677:134613d3b353
    21 
    21 
    22 from datetime import datetime
    22 from datetime import datetime
    23 
    23 
    24 from cubicweb.selectors import is_instance
    24 from cubicweb.selectors import is_instance
    25 from cubicweb.server import hook
    25 from cubicweb.server import hook
       
    26 from cubicweb.server.edition import EditedEntity
    26 
    27 
    27 
    28 
    28 class MetaDataHook(hook.Hook):
    29 class MetaDataHook(hook.Hook):
    29     __abstract__ = True
    30     __abstract__ = True
    30     category = 'metadata'
    31     category = 'metadata'
    66 class SetCreatorOp(hook.DataOperationMixIn, hook.Operation):
    67 class SetCreatorOp(hook.DataOperationMixIn, hook.Operation):
    67 
    68 
    68     def precommit_event(self):
    69     def precommit_event(self):
    69         session = self.session
    70         session = self.session
    70         relations = [(eid, session.user.eid) for eid in self.get_data()
    71         relations = [(eid, session.user.eid) for eid in self.get_data()
    71                 # don't consider entities that have been created and
    72                 # don't consider entities that have been created and deleted in
    72                 # deleted in the same transaction
    73                 # the same transaction, nor ones where created_by has been
       
    74                 # explicitly set
    73                 if not session.deleted_in_transaction(eid) and \
    75                 if not session.deleted_in_transaction(eid) and \
    74                    not session.entity_from_eid(eid).created_by]
    76                    not session.entity_from_eid(eid).created_by]
    75         session.add_relations([('created_by', relations)])
    77         session.add_relations([('created_by', relations)])
    76 
    78 
    77 
    79 
   139                 session, session.entity_from_eid(self.eidfrom))
   141                 session, session.entity_from_eid(self.eidfrom))
   140         elif ftcontainer == 'object':
   142         elif ftcontainer == 'object':
   141             session.repo.system_source.index_entity(
   143             session.repo.system_source.index_entity(
   142                 session, session.entity_from_eid(self.eidto))
   144                 session, session.entity_from_eid(self.eidto))
   143 
   145 
       
   146 
       
   147 
       
   148 # entity source handling #######################################################
       
   149 
       
   150 class ChangeEntityUpdateCaches(hook.Operation):
       
   151     def postcommit_event(self):
       
   152         self.oldsource.reset_caches()
       
   153         repo = self.session.repo
       
   154         entity = self.entity
       
   155         extid = entity.cw_metainformation()['extid']
       
   156         repo._type_source_cache[entity.eid] = (
       
   157             entity.__regid__, self.newsource.uri, None, self.newsource.uri)
       
   158         if self.oldsource.copy_based_source:
       
   159             uri = 'system'
       
   160         else:
       
   161             uri = self.oldsource.uri
       
   162         repo._extid_cache[(extid, uri)] = -entity.eid
       
   163 
       
   164 class ChangeEntitySourceDeleteHook(MetaDataHook):
       
   165     """support for moving an entity from an external source by watching 'Any
       
   166     cw_source CWSource' relation
       
   167     """
       
   168 
       
   169     __regid__ = 'cw.metadata.source-change'
       
   170     __select__ = MetaDataHook.__select__ & hook.match_rtype('cw_source')
       
   171     events = ('before_delete_relation',)
       
   172 
       
   173     def __call__(self):
       
   174         if (self._cw.deleted_in_transaction(self.eidfrom)
       
   175             or self._cw.deleted_in_transaction(self.eidto)):
       
   176             return
       
   177         schange = self._cw.transaction_data.setdefault('cw_source_change', {})
       
   178         schange[self.eidfrom] = self.eidto
       
   179 
       
   180 
       
   181 class ChangeEntitySourceAddHook(MetaDataHook):
       
   182     __regid__ = 'cw.metadata.source-change'
       
   183     __select__ = MetaDataHook.__select__ & hook.match_rtype('cw_source')
       
   184     events = ('before_add_relation',)
       
   185 
       
   186     def __call__(self):
       
   187         schange = self._cw.transaction_data.get('cw_source_change')
       
   188         if schange is not None and self.eidfrom in schange:
       
   189             newsource = self._cw.entity_from_eid(self.eidto)
       
   190             if newsource.name != 'system':
       
   191                 raise Exception('changing source to something else than the '
       
   192                                 'system source is unsupported')
       
   193             syssource = newsource.repo_source
       
   194             oldsource = self._cw.entity_from_eid(schange[self.eidfrom])
       
   195             entity = self._cw.entity_from_eid(self.eidfrom)
       
   196             # copy entity if necessary
       
   197             if not oldsource.repo_source.copy_based_source:
       
   198                 entity.complete(skip_bytes=False)
       
   199                 entity.cw_edited = EditedEntity(entity, **entity.cw_attr_cache)
       
   200                 syssource.add_entity(self._cw, entity)
       
   201             # we don't want the moved entity to be reimported later.  To
       
   202             # distinguish this state, the trick is to change the associated
       
   203             # record in the 'entities' system table with eid=-eid while leaving
       
   204             # other fields unchanged, and to add a new record with eid=eid,
       
   205             # source='system'. External source will then have consider case
       
   206             # where `extid2eid` return a negative eid as 'this entity was known
       
   207             # but has been moved, ignore it'.
       
   208             self._cw.system_sql('UPDATE entities SET eid=-eid,source=%(source)s '
       
   209                                 'WHERE eid=%(eid)s',
       
   210                                 {'eid': self.eidfrom, 'source': newsource.name})
       
   211             attrs = {'type': entity.__regid__, 'eid': entity.eid, 'extid': None,
       
   212                      'source': 'system', 'asource': 'system',
       
   213                      'mtime': datetime.now()}
       
   214             self._cw.system_sql(syssource.sqlgen.insert('entities', attrs), attrs)
       
   215             # register an operation to update repository/sources caches
       
   216             ChangeEntityUpdateCaches(self._cw, entity=entity,
       
   217                                      oldsource=oldsource.repo_source,
       
   218                                      newsource=syssource)