entities/wfobjs.py
author Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
Tue, 17 Feb 2009 16:33:52 +0100
changeset 676 270eb87a768a
parent 0 b97547f5f1fa
child 1154 9b23a6836c32
permissions -rw-r--r--
provide a new add_cubes() migration function for cases where the new cubes are linked together by new relations In this case, we need to add all new cubes at once.

"""workflow definition and history related entities

:organization: Logilab
:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"

from cubicweb.entities import AnyEntity, fetch_config


class Transition(AnyEntity):
    """customized class for Transition entities

    provides a specific may_be_passed method to check if the relation may be
    passed by the logged user
    """
    id = 'Transition'
    fetch_attrs, fetch_order = fetch_config(['name'])
    __rtags__ = {('destination_state',  '*', 'subject'):  'create',
                 ('allowed_transition', '*', 'object') :  'create',
                  }
                 
    def may_be_passed(self, eid, stateeid):
        """return true if the logged user may pass this transition

        `eid` is the eid of the object on which we may pass the transition
        `stateeid` is the eid of the current object'state XXX unused
        """
        user = self.req.user
        # check user is at least in one of the required groups if any
        groups = frozenset(g.name for g in self.require_group)
        if groups:
            matches = user.matching_groups(groups)
            if matches:
                return matches
            if 'owners' in groups and user.owns(eid):
                return True
        # check one of the rql expression conditions matches if any
        if self.condition:
            for rqlexpr in self.condition:
                if rqlexpr.check_expression(self.req, eid):
                    return True
        if self.condition or groups:
            return False
        return True

    def destination(self):
        return self.destination_state[0]
    
    def after_deletion_path(self):
        """return (path, parameters) which should be used as redirect
        information when this entity is being deleted
        """
        if self.transition_of:
            return self.transition_of[0].rest_path(), {'vid': 'workflow'}
        return super(Transition, self).after_deletion_path()

    
class State(AnyEntity):
    """customized class for State entities

    provides a specific transitions method returning transitions that may be
    passed by the current user for the given entity
    """
    id = 'State'
    fetch_attrs, fetch_order = fetch_config(['name'])
    rest_attr = 'eid'
    
    __rtags__ = {'destination_state' : 'create',
                 'allowed_transition' : 'create'
                 }
    
    def transitions(self, entity, desteid=None):
        rql = ('Any T,N,DS where S allowed_transition T, S eid %(x)s, '
               'T name N, T destination_state DS, '
               'T transition_of ET, ET name %(et)s')
        if desteid is not None:
            rql += ', DS eid %(ds)s'
        rset = self.req.execute(rql, {'x': self.eid, 'et': str(entity.e_schema),
                                         'ds': desteid}, 'x')
        for tr in rset.entities():
            if tr.may_be_passed(entity.eid, self.eid):
                yield tr
                
    def after_deletion_path(self):
        """return (path, parameters) which should be used as redirect
        information when this entity is being deleted
        """
        if self.state_of:
            return self.state_of[0].rest_path(), {'vid': 'workflow'}
        return super(State, self).after_deletion_path()

    
class TrInfo(AnyEntity):
    """customized class for Transition information entities
    """
    id = 'TrInfo'
    fetch_attrs, fetch_order = fetch_config(['creation_date', 'comment'],
                                            pclass=None) # don't want modification_date
    @property
    def for_entity(self):
        return self.wf_info_for and self.wf_info_for[0]
    @property
    def previous_state(self):
        return self.from_state and self.from_state[0]
    
    @property
    def new_state(self):
        return self.to_state[0]

    def after_deletion_path(self):
        """return (path, parameters) which should be used as redirect
        information when this entity is being deleted
        """
        if self.for_entity:
            return self.for_entity.rest_path(), {}
        return 'view', {}