hooks/metadata.py
brancholdstable
changeset 7074 e4580e5f0703
parent 6955 a6c32edabc8d
child 7237 9f619715665b
equal deleted inserted replaced
6749:48f468f33704 7074:e4580e5f0703
     1 # copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
     3 #
     3 #
     4 # This file is part of CubicWeb.
     4 # This file is part of CubicWeb.
     5 #
     5 #
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
    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.utils import eschema_eid
       
    27 
    26 
    28 
    27 
    29 class MetaDataHook(hook.Hook):
    28 class MetaDataHook(hook.Hook):
    30     __abstract__ = True
    29     __abstract__ = True
    31     category = 'metadata'
    30     category = 'metadata'
    39     __regid__ = 'metaattrsinit'
    38     __regid__ = 'metaattrsinit'
    40     events = ('before_add_entity',)
    39     events = ('before_add_entity',)
    41 
    40 
    42     def __call__(self):
    41     def __call__(self):
    43         timestamp = datetime.now()
    42         timestamp = datetime.now()
    44         self.entity.setdefault('creation_date', timestamp)
    43         edited = self.entity.cw_edited
    45         self.entity.setdefault('modification_date', timestamp)
    44         edited.setdefault('creation_date', timestamp)
       
    45         edited.setdefault('modification_date', timestamp)
    46         if not self._cw.get_shared_data('do-not-insert-cwuri'):
    46         if not self._cw.get_shared_data('do-not-insert-cwuri'):
    47             cwuri = u'%seid/%s' % (self._cw.base_url(), self.entity.eid)
    47             cwuri = u'%s%s' % (self._cw.base_url(), self.entity.eid)
    48             self.entity.setdefault('cwuri', cwuri)
    48             edited.setdefault('cwuri', cwuri)
    49 
    49 
    50 
    50 
    51 class UpdateMetaAttrsHook(MetaDataHook):
    51 class UpdateMetaAttrsHook(MetaDataHook):
    52     """update an entity -> set modification date"""
    52     """update an entity -> set modification date"""
    53     __regid__ = 'metaattrsupdate'
    53     __regid__ = 'metaattrsupdate'
    58         # usually don't want to update modification date in such cases.
    58         # usually don't want to update modification date in such cases.
    59         #
    59         #
    60         # XXX to be really clean, we should turn off modification_date update
    60         # XXX to be really clean, we should turn off modification_date update
    61         # explicitly on each command where we do not want that behaviour.
    61         # explicitly on each command where we do not want that behaviour.
    62         if not self._cw.vreg.config.repairing:
    62         if not self._cw.vreg.config.repairing:
    63             self.entity.setdefault('modification_date', datetime.now())
    63             self.entity.cw_edited.setdefault('modification_date', datetime.now())
    64 
    64 
    65 
    65 
    66 class _SetCreatorOp(hook.Operation):
    66 class SetCreatorOp(hook.DataOperationMixIn, hook.Operation):
    67 
    67 
    68     def precommit_event(self):
    68     def precommit_event(self):
    69         session = self.session
    69         session = self.session
    70         for eid in session.transaction_data.pop('set_creator_op'):
    70         for eid in self.get_data():
    71             if session.deleted_in_transaction(eid):
    71             if session.deleted_in_transaction(eid):
    72                 # entity have been created and deleted in the same transaction
    72                 # entity have been created and deleted in the same transaction
    73                 continue
    73                 continue
    74             entity = session.entity_from_eid(eid)
    74             entity = session.entity_from_eid(eid)
    75             if not entity.created_by:
    75             if not entity.created_by:
    76                 session.add_relation(eid, 'created_by', session.user.eid)
    76                 session.add_relation(eid, 'created_by', session.user.eid)
    77 
       
    78 
       
    79 class SetIsHook(MetaDataHook):
       
    80     """create a new entity -> set is and is_instance_of relations
       
    81 
       
    82     those relations are inserted using sql so they are not hookable.
       
    83     """
       
    84     __regid__ = 'setis'
       
    85     events = ('after_add_entity',)
       
    86 
       
    87     def __call__(self):
       
    88         if hasattr(self.entity, '_cw_recreating'):
       
    89             return
       
    90         session = self._cw
       
    91         entity = self.entity
       
    92         try:
       
    93             session.system_sql('INSERT INTO is_relation(eid_from,eid_to) VALUES (%s,%s)'
       
    94                            % (entity.eid, eschema_eid(session, entity.e_schema)))
       
    95         except IndexError:
       
    96             # during schema serialization, skip
       
    97             return
       
    98         for eschema in entity.e_schema.ancestors() + [entity.e_schema]:
       
    99             session.system_sql('INSERT INTO is_instance_of_relation(eid_from,eid_to) VALUES (%s,%s)'
       
   100                                % (entity.eid, eschema_eid(session, eschema)))
       
   101 
    77 
   102 
    78 
   103 class SetOwnershipHook(MetaDataHook):
    79 class SetOwnershipHook(MetaDataHook):
   104     """create a new entity -> set owner and creator metadata"""
    80     """create a new entity -> set owner and creator metadata"""
   105     __regid__ = 'setowner'
    81     __regid__ = 'setowner'
   106     events = ('after_add_entity',)
    82     events = ('after_add_entity',)
   107 
    83 
   108     def __call__(self):
    84     def __call__(self):
   109         if not self._cw.is_internal_session:
    85         if not self._cw.is_internal_session:
   110             self._cw.add_relation(self.entity.eid, 'owned_by', self._cw.user.eid)
    86             self._cw.add_relation(self.entity.eid, 'owned_by', self._cw.user.eid)
   111             hook.set_operation(self._cw, 'set_creator_op', self.entity.eid, _SetCreatorOp)
    87             SetCreatorOp.get_instance(self._cw).add_data(self.entity.eid)
   112 
    88 
   113 class _SyncOwnersOp(hook.Operation):
    89 
       
    90 class SyncOwnersOp(hook.DataOperationMixIn, hook.Operation):
   114     def precommit_event(self):
    91     def precommit_event(self):
   115         for compositeeid, composedeid in self.session.transaction_data.pop('sync_owners_op'):
    92         for compositeeid, composedeid in self.get_data():
   116             self.session.execute('SET X owned_by U WHERE C owned_by U, C eid %(c)s,'
    93             self.session.execute('SET X owned_by U WHERE C owned_by U, C eid %(c)s,'
   117                                  'NOT EXISTS(X owned_by U, X eid %(x)s)',
    94                                  'NOT EXISTS(X owned_by U, X eid %(x)s)',
   118                                  {'c': compositeeid, 'x': composedeid})
    95                                  {'c': compositeeid, 'x': composedeid})
   119 
    96 
   120 
    97 
   130             # skip this special composite relation # XXX (syt) why?
   107             # skip this special composite relation # XXX (syt) why?
   131             return
   108             return
   132         eidfrom, eidto = self.eidfrom, self.eidto
   109         eidfrom, eidto = self.eidfrom, self.eidto
   133         composite = self._cw.schema_rproperty(self.rtype, eidfrom, eidto, 'composite')
   110         composite = self._cw.schema_rproperty(self.rtype, eidfrom, eidto, 'composite')
   134         if composite == 'subject':
   111         if composite == 'subject':
   135             hook.set_operation(self._cw, 'sync_owners_op', (eidfrom, eidto), _SyncOwnersOp)
   112             SyncOwnersOp.get_instance(self._cw).add_data( (eidfrom, eidto) )
   136         elif composite == 'object':
   113         elif composite == 'object':
   137             hook.set_operation(self._cw, 'sync_owners_op', (eidto, eidfrom), _SyncOwnersOp)
   114             SyncOwnersOp.get_instance(self._cw).add_data( (eidto, eidfrom) )
   138 
   115 
   139 
   116 
   140 class FixUserOwnershipHook(MetaDataHook):
   117 class FixUserOwnershipHook(MetaDataHook):
   141     """when a user has been created, add owned_by relation on itself"""
   118     """when a user has been created, add owned_by relation on itself"""
   142     __regid__ = 'fixuserowner'
   119     __regid__ = 'fixuserowner'