--- a/src/pyams_workflow/interfaces/__init__.py Wed Jan 09 14:02:56 2019 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,495 +0,0 @@
-#
-# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-
-__docformat__ = 'restructuredtext'
-
-
-# import standard library
-
-# import interfaces
-from pyams_utils.interfaces import VIEW_PERMISSION
-from zope.annotation.interfaces import IAttributeAnnotatable
-from zope.interface.interfaces import IObjectEvent, ObjectEvent
-from zope.lifecycleevent.interfaces import IObjectCreatedEvent
-
-# import packages
-from pyams_security.schema import Principal
-from zope.interface import implementer, invariant, Interface, Attribute, Invalid
-from zope.lifecycleevent import ObjectCreatedEvent
-from zope.schema import Choice, Datetime, Set, TextLine, Text, List, Object, Int, Bool
-from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
-
-from pyams_workflow import _
-
-
-MANUAL = 0
-AUTOMATIC = 1
-SYSTEM = 2
-
-
-class InvalidTransitionError(Exception):
- """Base transition error"""
-
- def __init__(self, source):
- self.source = source
-
- def __str__(self):
- return 'source: "%s"' % self.source
-
-
-class NoTransitionAvailableError(InvalidTransitionError):
- """Exception raised when there is not available transition"""
-
- def __init__(self, source, destination):
- super(NoTransitionAvailableError, self).__init__(source)
- self.destination = destination
-
- def __str__(self):
- return 'source: "%s" destination: "%s"' % (self.source, self.destination)
-
-
-class AmbiguousTransitionError(InvalidTransitionError):
- """Exception raised when required transition is ambiguous"""
-
- def __init__(self, source, destination):
- super(AmbiguousTransitionError, self).__init__(source)
- self.destination = destination
-
- def __str__(self):
- return 'source: "%s" destination: "%s"' % (self.source, self.destination)
-
-
-class VersionError(Exception):
- """Versions management error"""
-
-
-class ConditionFailedError(Exception):
- """Exception raised when transition condition failed"""
-
-
-class IWorkflowTransitionEvent(IObjectEvent):
- """Workflow transition event interface"""
-
- wokflow = Attribute("Workflow utility")
-
- principal = Attribute("Event principal")
-
- source = Attribute('Original state or None if initial state')
-
- destination = Attribute('New state')
-
- transition = Attribute('Transition that was fired or None if initial state')
-
- comment = Attribute('Comment that went with state transition')
-
-
-@implementer(IWorkflowTransitionEvent)
-class WorkflowTransitionEvent(ObjectEvent):
- """Workflow transition event"""
-
- def __init__(self, object, workflow, principal, source, destination, transition, comment):
- super(WorkflowTransitionEvent, self).__init__(object)
- self.workflow = workflow
- self.principal = principal
- self.source = source
- self.destination = destination
- self.transition = transition
- self.comment = comment
-
-
-class IWorkflowVersionTransitionEvent(IWorkflowTransitionEvent):
- """Workflow version transition event interface"""
-
- old_object = Attribute('Old version of object')
-
-
-@implementer(IWorkflowVersionTransitionEvent)
-class WorkflowVersionTransitionEvent(WorkflowTransitionEvent):
- """Workflow version transition event"""
-
- def __init__(self, object, workflow, principal, old_object, source, destination, transition, comment):
- super(WorkflowVersionTransitionEvent, self).__init__(object, workflow, principal, source,
- destination, transition, comment)
- self.old_object = old_object
-
-
-class IObjectClonedEvent(IObjectCreatedEvent):
- """Object cloned event interface"""
-
- source = Attribute("Cloned object source")
-
-
-@implementer(IObjectClonedEvent)
-class ObjectClonedEvent(ObjectCreatedEvent):
- """Object cloned event"""
-
- def __init__(self, object, source):
- super(ObjectClonedEvent, self).__init__(object)
- self.source = source
-
-
-class IWorkflow(Interface):
- """Defines workflow in the form of transition objects.
-
- Defined as a utility.
- """
-
- initial_state = Attribute("Initial state")
-
- update_states = Set(title="Updatable states",
- description="States of contents which are updatable by standard contributors")
-
- readonly_states = Set(title="Read-only states",
- description="States of contents which can't be modified by anybody")
-
- protected_states = Set(title="Protected states",
- description="States of contents which can only be modified by site administrators")
-
- manager_states = Set(title="Manager states",
- description="States of contents which can be modified by site administrators and content "
- "managers")
-
- published_states = Set(title="Published states",
- description="States of contents which are published and visible")
-
- waiting_states = Set(title="Waiting states",
- description="States of contents waiting for action")
-
- retired_states = Set(title="Retired states",
- description="States of contents which are retired but not yet archived")
-
- auto_retired_state = Attribute("Auto-retired state")
-
- def initialize(self):
- """Do any needed initialization.
-
- Such as initialization with the workflow versions system.
- """
-
- def refresh(self, transitions):
- """Refresh workflow completely with new transitions."""
-
- def get_state_label(self, state):
- """Get given state label"""
-
- def get_transitions(self, source):
- """Get all transitions from source"""
-
- def get_transition(self, source, transition_id):
- """Get transition with transition_id given source state.
-
- If the transition is invalid from this source state,
- an InvalidTransitionError is raised.
- """
-
- def get_transition_by_id(self, transition_id):
- """Get transition with transition_id"""
-
-
-class IWorkflowInfo(Interface):
- """Get workflow info about workflowed object, and drive workflow.
-
- Defined as an adapter.
- """
-
- def set_initial_state(self, state, comment=None):
- """Set initial state for the context object.
-
- Fires a transition event.
- """
-
- def fire_transition(self, transition_id, comment=None, side_effect=None, check_security=True, principal=None):
- """Fire a transition for the context object.
-
- There's an optional comment parameter that contains some
- opaque object that offers a comment about the transition.
- This is useful for manual transitions where users can motivate
- their actions.
-
- There's also an optional side effect parameter which should
- be a callable which receives the object undergoing the transition
- as the parameter. This could do an editing action of the newly
- transitioned workflow object before an actual transition event is
- fired.
-
- If check_security is set to False, security is not checked
- and an application can fire a transition no matter what the
- user's permission is.
- """
-
- def fire_transition_toward(self, state, comment=None, side_effect=None, check_security=True, principal=None):
- """Fire transition toward state.
-
- Looks up a manual transition that will get to the indicated
- state.
-
- If no such transition is possible, NoTransitionAvailableError will
- be raised.
-
- If more than one manual transitions are possible,
- AmbiguousTransitionError will be raised.
- """
-
- def fire_transition_for_versions(self, state, transition_id, comment=None, principal=None):
- """Fire a transition for all versions in a state"""
-
- def fire_automatic(self):
- """Fire automatic transitions if possible by condition"""
-
- def has_version(self, state):
- """Return true if a version exists in given state"""
-
- def get_manual_transition_ids(self):
- """Returns list of valid manual transitions.
-
- These transitions have to have a condition that's True.
- """
-
- def get_manual_transition_ids_toward(self, state):
- """Returns list of manual transitions towards state"""
-
- def get_automatic_transition_ids(self):
- """Returns list of possible automatic transitions.
-
- Condition is not checked.
- """
-
- def has_automatic_transitions(self):
- """Return true if there are possible automatic outgoing transitions.
-
- Condition is not checked.
- """
-
-
-class IWorkflowStateHistoryItem(Interface):
- """Workflow state history item"""
-
- date = Datetime(title="State change datetime",
- required=True)
-
- source_version = Int(title="Source version ID",
- required=False)
-
- source_state = TextLine(title="Transition source state",
- required=False)
-
- target_state = TextLine(title="Transition target state",
- required=True)
-
- transition_id = TextLine(title="Transition ID",
- required=True)
-
- transition = TextLine(title="Transition name",
- required=True)
-
- principal = Principal(title="Transition principal",
- required=False)
-
- comment = Text(title="Transition comment",
- required=False)
-
-
-class IWorkflowState(Interface):
- """Store state on workflowed objects.
-
- Defined as an adapter.
- """
-
- version_id = Int(title=_("Version ID"))
-
- state = TextLine(title=_("Version state"))
-
- state_date = Datetime(title=_("State date"),
- description=_("Date at which the current state was applied"))
-
- state_principal = Principal(title=_("State principal"),
- description=_("ID of the principal which defined current state"))
-
- state_urgency = Bool(title=_("Urgent request?"),
- required=True,
- default=False)
-
- history = List(title="Workflow states history",
- value_type=Object(schema=IWorkflowStateHistoryItem))
-
- def get_first_state_date(self, states):
- """Get first date at which given state was set"""
-
-
-class IWorkflowVersions(Interface):
- """Interface to get information about versions of content in workflow"""
-
- last_version_id = Attribute("Last version ID")
-
- def get_version(self, version_id):
- """Get version matching given id"""
-
- def get_versions(self, states=None, sort=False, reverse=False):
- """Get all versions of object known for this (optional) state"""
-
- def get_last_versions(self, count=1):
- """Get last versions of this object. Set count=0 to get all versions."""
-
- def add_version(self, content, state, principal=None):
- """Return new unique version id"""
-
- def set_state(self, version_id, state, principal=None):
- """Set new state for given version"""
-
- def has_version(self, state):
- """Return true if a version exists with the specific workflow state"""
-
- def remove_version(self, version_id, state='deleted', comment=None, principal=None):
- """Remove version with given ID"""
-
-
-class IWorkflowStateLabel(Interface):
- """Workflow state label adapter interface"""
-
- def get_label(self, content, request=None, format=True):
- """Get state label for given content"""
-
-
-class IWorkflowManagedContent(IAttributeAnnotatable):
- """Workflow managed content"""
-
- content_class = Attribute("Content class")
-
- workflow_name = Choice(title=_("Workflow name"),
- description=_("Name of workflow utility managing this content"),
- required=True,
- vocabulary='PyAMS workflows')
-
- view_permission = Choice(title=_("View permission"),
- description=_("This permission will be required to display content"),
- vocabulary='PyAMS permissions',
- default=VIEW_PERMISSION,
- required=False)
-
-
-class IWorkflowPublicationSupport(IAttributeAnnotatable):
- """Workflow publication support"""
-
-
-class IWorkflowVersion(IWorkflowPublicationSupport):
- """Workflow content version marker interface"""
-
-
-class IWorkflowTransitionInfo(Interface):
- """Workflow transition info"""
-
- transition_id = TextLine(title=_("Transition ID"),
- required=True)
-
-
-DISPLAY_FIRST_VERSION = 'first'
-DISPLAY_CURRENT_VERSION = 'current'
-
-VERSION_DISPLAY = {DISPLAY_FIRST_VERSION: _("Display first version date"),
- DISPLAY_CURRENT_VERSION: _("Display current version date")}
-
-VERSION_DISPLAY_VOCABULARY = SimpleVocabulary([SimpleTerm(v, title=t)
- for v, t in VERSION_DISPLAY.items()])
-
-
-class IWorkflowPublicationInfo(Interface):
- """Workflow content publication info"""
-
- publication_date = Datetime(title=_("Publication date"),
- description=_("Last date at which content was accepted for publication"),
- required=False)
-
- publisher = Principal(title=_("Publisher"),
- description=_("Name of the manager who published the document"),
- required=False)
-
- publication = TextLine(title=_("Publication"),
- description=_("Last publication date and actor"),
- required=False,
- readonly=True)
-
- first_publication_date = Datetime(title=_("First publication date"),
- description=_("First date at which content was accepted for publication"),
- required=False)
-
- publication_effective_date = Datetime(title=_("Publication start date"),
- description=_("Date from which content will be visible"),
- required=False)
-
- push_end_date = Datetime(title=_("Push end date"),
- description=_("Some contents can be pushed by components to front-office pages; if you "
- "set a date here, this content will not be pushed anymore passed this "
- "date, but will still be available via search engine or direct links"),
- required=False)
-
- push_end_date_index = Attribute("Push end date value used by catalog indexes")
-
- @invariant
- def check_push_end_date(self):
- if self.push_end_date is not None:
- if self.publication_effective_date is None:
- raise Invalid(_("Can't define push end date without publication start date!"))
- if self.publication_effective_date >= self.push_end_date:
- raise Invalid(_("Push end date must be defined after publication start date!"))
- if self.publication_expiration_date is not None:
- if self.publication_expiration_date < self.push_end_date:
- raise Invalid(_("Push end date must be null or defined before publication end date!"))
-
- publication_expiration_date = Datetime(title=_("Publication end date"),
- description=_("Date past which content will not be visible"),
- required=False)
-
- @invariant
- def check_expiration_date(self):
- if self.publication_expiration_date is not None:
- if self.publication_effective_date is None:
- raise Invalid(_("Can't define publication end date without publication start date!"))
- if self.publication_effective_date >= self.publication_expiration_date:
- raise Invalid(_("Publication end date must be defined after publication start date!"))
-
- displayed_publication_date = Choice(title=_("Displayed publication date"),
- description=_("The matching date will be displayed in front-office"),
- vocabulary='PyAMS content publication date',
- default=DISPLAY_FIRST_VERSION,
- required=True)
-
- visible_publication_date = Attribute("Visible publication date")
-
- def reset(self, complete=True):
- """Reset all publication info (used by clone features)
-
- If 'complete' argument is True, all date fields are reset; otherwise, push and publication end dates are
- preserved in new versions.
- """
-
- def is_published(self, check_parent=True):
- """Is the content published?"""
-
- def is_visible(self, request=None, check_parent=True):
- """Is the content visible?"""
-
-
-class IWorkflowRequestUrgencyInfo(Interface):
- """Workflow request urgency info"""
-
- urgent_request = Bool(title=_("Urgent request?"),
- description=_("Please use this option only when really needed..."),
- required=True,
- default=False)
-
-
-class IWorkflowCommentInfo(Interface):
- """Workflow comment info"""
-
- comment = Text(title=_("Comment"),
- description=_("Comment associated with this operation"),
- required=False)