entities/wfobjs.py
author Sandrine Ribeau <sandrine.ribeau@logilab.fr>
Thu, 06 Nov 2008 16:21:57 -0800
changeset 11 db9c539e0b1b
parent 0 b97547f5f1fa
child 1154 9b23a6836c32
permissions -rw-r--r--
Add module wfobjs to enable workflow in gae. Add module vcard to enable usage of cube person in gae. Add init file creation for cubes gae directory.

"""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', {}