hooks/metadata.py
changeset 2841 107ba1c45227
parent 2835 04034421b072
child 2847 c2ee28f4d4b1
equal deleted inserted replaced
2840:06daf13195d4 2841:107ba1c45227
     9 
     9 
    10 
    10 
    11 from datetime import datetime
    11 from datetime import datetime
    12 
    12 
    13 from cubicweb.selectors import entity_implements
    13 from cubicweb.selectors import entity_implements
    14 from cubicweb.server.hook import Hook
    14 from cubicweb.server import hook
    15 from cubicweb.server.pool import Operation, LateOperation, PreCommitOperation
       
    16 from cubicweb.server.hookhelper import rproperty
       
    17 from cubicweb.server.repository import FTIndexEntityOp
    15 from cubicweb.server.repository import FTIndexEntityOp
    18 
    16 
    19 
    17 
    20 def eschema_type_eid(session, etype):
    18 def eschema_type_eid(session, etype):
    21     """get eid of the CWEType entity for the given yams type"""
    19     """get eid of the CWEType entity for the given yams type"""
    26         eschema.eid = session.unsafe_execute(
    24         eschema.eid = session.unsafe_execute(
    27             'Any X WHERE X is CWEType, X name %(name)s', {'name': etype})[0][0]
    25             'Any X WHERE X is CWEType, X name %(name)s', {'name': etype})[0][0]
    28     return eschema.eid
    26     return eschema.eid
    29 
    27 
    30 
    28 
    31 class InitMetaAttrsHook(Hook):
    29 class MetaDataHook(hook.Hook):
       
    30     __abstract__ = True
       
    31     category = 'metadata'
       
    32 
       
    33 
       
    34 class InitMetaAttrsHook(MetaDataHook):
    32     """before create a new entity -> set creation and modification date
    35     """before create a new entity -> set creation and modification date
    33 
    36 
    34     this is a conveniency hook, you shouldn't have to disable it
    37     this is a conveniency hook, you shouldn't have to disable it
    35     """
    38     """
    36     id = 'metaattrsinit'
    39     __id__ = 'metaattrsinit'
    37     events = ('before_add_entity',)
    40     events = ('before_add_entity',)
    38     category = 'metadata'
       
    39 
    41 
    40     def __call__(self):
    42     def __call__(self):
    41         timestamp = datetime.now()
    43         timestamp = datetime.now()
    42         self.entity.setdefault('creation_date', timestamp)
    44         self.entity.setdefault('creation_date', timestamp)
    43         self.entity.setdefault('modification_date', timestamp)
    45         self.entity.setdefault('modification_date', timestamp)
    44         if not self.cw_req.get_shared_data('do-not-insert-cwuri'):
    46         if not self.cw_req.get_shared_data('do-not-insert-cwuri'):
    45             cwuri = u'%seid/%s' % (self.cw_req.base_url(), self.entity.eid)
    47             cwuri = u'%seid/%s' % (self.cw_req.base_url(), self.entity.eid)
    46             self.entity.setdefault('cwuri', cwuri)
    48             self.entity.setdefault('cwuri', cwuri)
    47 
    49 
    48 
    50 
    49 class UpdateMetaAttrsHook(Hook):
    51 class UpdateMetaAttrsHook(MetaDataHook):
    50     """update an entity -> set modification date"""
    52     """update an entity -> set modification date"""
    51     id = 'metaattrsupdate'
    53     __id__ = 'metaattrsupdate'
    52     events = ('before_update_entity',)
    54     events = ('before_update_entity',)
    53     category = 'metadata'
    55 
    54     def __call__(self):
    56     def __call__(self):
    55         self.entity.setdefault('modification_date', datetime.now())
    57         self.entity.setdefault('modification_date', datetime.now())
    56 
    58 
    57 
    59 
    58 class _SetCreatorOp(PreCommitOperation):
    60 class _SetCreatorOp(hook.Operation):
    59 
    61 
    60     def precommit_event(self):
    62     def precommit_event(self):
    61         session = self.session
    63         session = self.session
    62         if self.entity.eid in session.transaction_data.get('pendingeids', ()):
    64         if session.deleted_in_transaction(self.entity.eid):
    63             # entity have been created and deleted in the same transaction
    65             # entity have been created and deleted in the same transaction
    64             return
    66             return
    65         if not self.entity.created_by:
    67         if not self.entity.created_by:
    66             session.add_relation(self.entity.eid, 'created_by', session.user.eid)
    68             session.add_relation(self.entity.eid, 'created_by', session.user.eid)
    67 
    69 
    68 
    70 
    69 class SetIsHook(Hook):
    71 class SetIsHook(MetaDataHook):
    70     """create a new entity -> set is relation"""
    72     """create a new entity -> set is relation"""
    71     id = 'setis'
    73     __id__ = 'setis'
    72     events = ('after_add_entity',)
    74     events = ('after_add_entity',)
    73     category = 'metadata'
    75 
    74     def __call__(self):
    76     def __call__(self):
    75         if hasattr(self.entity, '_cw_recreating'):
    77         if hasattr(self.entity, '_cw_recreating'):
    76             return
    78             return
    77         session = self.cw_req
    79         session = self.cw_req
    78         entity = self.entity
    80         entity = self.entity
    85         for etype in entity.e_schema.ancestors() + [entity.e_schema]:
    87         for etype in entity.e_schema.ancestors() + [entity.e_schema]:
    86             session.add_relation(entity.eid, 'is_instance_of',
    88             session.add_relation(entity.eid, 'is_instance_of',
    87                                  eschema_type_eid(session, etype))
    89                                  eschema_type_eid(session, etype))
    88 
    90 
    89 
    91 
    90 class SetOwnershipHook(Hook):
    92 class SetOwnershipHook(MetaDataHook):
    91     """create a new entity -> set owner and creator metadata"""
    93     """create a new entity -> set owner and creator metadata"""
    92     id = 'setowner'
    94     __id__ = 'setowner'
    93     events = ('after_add_entity',)
    95     events = ('after_add_entity',)
    94     category = 'metadata'
    96 
    95     def __call__(self):
    97     def __call__(self):
    96         asession = self.cw_req.actual_session()
    98         asession = self.cw_req.actual_session()
    97         if not asession.is_internal_session:
    99         if not asession.is_internal_session:
    98             self.cw_req.add_relation(self.entity.eid, 'owned_by', asession.user.eid)
   100             self.cw_req.add_relation(self.entity.eid, 'owned_by', asession.user.eid)
    99             _SetCreatorOp(asession, entity=self.entity)
   101             _SetCreatorOp(asession, entity=self.entity)
   100 
   102 
   101 
   103 
   102 class _SyncOwnersOp(PreCommitOperation):
   104 class _SyncOwnersOp(hook.Operation):
   103     def precommit_event(self):
   105     def precommit_event(self):
   104         self.session.unsafe_execute('SET X owned_by U WHERE C owned_by U, C eid %(c)s,'
   106         self.session.unsafe_execute('SET X owned_by U WHERE C owned_by U, C eid %(c)s,'
   105                                     'NOT EXISTS(X owned_by U, X eid %(x)s)',
   107                                     'NOT EXISTS(X owned_by U, X eid %(x)s)',
   106                                     {'c': self.compositeeid, 'x': self.composedeid},
   108                                     {'c': self.compositeeid, 'x': self.composedeid},
   107                                     ('c', 'x'))
   109                                     ('c', 'x'))
   108 
   110 
   109 class SyncCompositeOwner(Hook):
   111 
       
   112 class SyncCompositeOwner(MetaDataHook):
   110     """when adding composite relation, the composed should have the same owners
   113     """when adding composite relation, the composed should have the same owners
   111     has the composite
   114     has the composite
   112     """
   115     """
   113     id = 'synccompositeowner'
   116     __id__ = 'synccompositeowner'
   114     events = ('after_add_relation',)
   117     events = ('after_add_relation',)
   115     category = 'metadata'
   118 
   116     def __call__(self):
   119     def __call__(self):
   117         if self.rtype == 'wf_info_for':
   120         if self.rtype == 'wf_info_for':
   118             # skip this special composite relation # XXX (syt) why?
   121             # skip this special composite relation # XXX (syt) why?
   119             return
   122             return
   120         eidfrom, eidto = self.eidfrom, self.eidto
   123         eidfrom, eidto = self.eidfrom, self.eidto
   121         composite = rproperty(self.cw_req, self.rtype, eidfrom, eidto, 'composite')
   124         composite = self.cw_req.schema_rproperty(self.rtype, eidfrom, eidto, 'composite')
   122         if composite == 'subject':
   125         if composite == 'subject':
   123             _SyncOwnersOp(self.cw_req, compositeeid=eidfrom, composedeid=eidto)
   126             _SyncOwnersOp(self.cw_req, compositeeid=eidfrom, composedeid=eidto)
   124         elif composite == 'object':
   127         elif composite == 'object':
   125             _SyncOwnersOp(self.cw_req, compositeeid=eidto, composedeid=eidfrom)
   128             _SyncOwnersOp(self.cw_req, compositeeid=eidto, composedeid=eidfrom)
   126 
   129 
   127 
   130 
   128 class FixUserOwnershipHook(Hook):
   131 class FixUserOwnershipHook(MetaDataHook):
   129     """when a user has been created, add owned_by relation on itself"""
   132     """when a user has been created, add owned_by relation on itself"""
   130     id = 'fixuserowner'
   133     __id__ = 'fixuserowner'
   131     __select__ = Hook.__select__ & entity_implements('CWUser')
   134     __select__ = MetaDataHook.__select__ & entity_implements('CWUser')
   132     events = ('after_add_entity',)
   135     events = ('after_add_entity',)
   133     category = 'metadata'
   136 
   134     def __call__(self):
   137     def __call__(self):
   135         self.cw_req.add_relation(self.entity.eid, 'owned_by', self.entity.eid)
   138         self.cw_req.add_relation(self.entity.eid, 'owned_by', self.entity.eid)
   136 
   139 
   137 
   140 
   138 class UpdateFTIHook(Hook):
   141 class UpdateFTIHook(MetaDataHook):
   139     """sync fulltext index when relevant relation is added / removed
   142     """sync fulltext index when relevant relation is added / removed
   140     """
   143     """
   141     id = 'updateftirel'
   144     __id__ = 'updateftirel'
   142     events = ('after_add_relation', 'after_delete_relation')
   145     events = ('after_add_relation', 'after_delete_relation')
   143     category = 'metadata'
       
   144 
   146 
   145     def __call__(self):
   147     def __call__(self):
   146         rtype = self.rtype
   148         rtype = self.rtype
   147         session = self.cw_req
   149         session = self.cw_req
   148         if self.event == 'after_add_relation':
   150         if self.event == 'after_add_relation':