在任何公司里工作流都是重要的。因此在许多计算机系统尤其是在">内容管理系统(CMS)中基于软件的工作流成为基本要求也就不足为奇了。本章将为消息栏添加发布工作流。
尽管本章并不处理 zope.app.workflow 包的各个方面 - 例如它并不说明如何创建处理定义 - 它只展示最通用的用法示例,将工作流集成到已存在的内容对象包中。而且实现起来惊人的简单。然而,在简单的背后有着相当复杂的接口以及它们的实现和表现。本章最后一节的目标就是用体系结构的角度来解释这个架构。
步骤 I: 明确你的消息工作流
为了明确内容对象的工作流,你需要简单地告诉系统它能够保存工作流数据。最简单的方式就是将下列接口声明添加到主配置文件的消息内容指令中:
1 <implements interface=
2 "zope.app.workflow.interfaces.IProcessInstanceContainerAdaptable"/>
为保存工作流数据的适配器已经定义为对象同时它也实现了 IAnnotable。我们的消息对象通过实现 IAttributeAnnotable 也已经做到了这一点,就象你在相同的内容指令中所看到的那样。
现在对象可以包含工作流,并且当你重启你的浏览器时,你将发现 Message 实例现在已经有一个内容完全空白的“Workflow” 标签了。
步骤 II: 通过浏览器创建工作流及其支持组件
接下来我们需要创建工作流组件本身。在第一次尝试里,我们打算手工创建全部的组件,因为这样可以对工作流运行机制有着更好的了解。
在你开始 Zope 3 之后,到你想在其中添加(或已经存在)消息栏的目录中。点击“Manage Site”到站点管理器;如果目录不是站点的话,点击“Make a site”。现在点击 “Tools” 标签。
如果你刚刚创建站点,你需要创建一个“Local Utility Service”。这可以通过点击 “Service Tool” 的链接来完成。点击 “Add” 按钮,在接下来的屏幕中选择 “Utility Service”,键入名字(如“utilities”)并按 “Add” 确认。现在你已经有了一个被完全配置和激活的 local utility service 了。现在回到工具屏幕。
接下来就是根据过程,包括状态和转换,定义实际的工作流了。点击 “Workflows” 链接,然后点击 “Add” 按钮添加一个工作流。对该工作流我们选择“Stateful Process Definition”(可能是你唯一的选择)并将其命名为“publish-message”。点击 “Add” 按钮,创建该工作流并激活它。
因为 stateful process defintion 组件支持XML的导入导出过滤,所以最好在XML中定义过程。For later reference, 我们打算将工作流XML保存在文件里并将其作为我们产品的一部分。因此打开消息栏包中的一个名为 workflow.xml 的文件,并添加下列过程定义:
1 <?xml version="1.0"?>
2 <workflow type="StatefulWorkflow" title="Message Publication Review">
3 <schema name=""/>
4 <states>
5 <state name="INITIAL" title="initial" />
6 <state name="private" title="Private" />
7 <state name="pending" title="Pending Publication" />
8 <state name="published" title="Public" />
9 </states>
10 <transitions>
11
12 <transition
13 sourceState="published"
14 destinationState="private"
15 name="published_private"
16 title="Unpublish Message"
17 permission="book.messageboard.PublishContent"
18 triggerMode="Manual" />
19
20 <transition
21 sourceState="private"
22 destinationState="pending"
23 name="private_pending"
24 title="Submit Message"
25 permission="book.messageboard.Edit"
26 triggerMode="Manual" />
27
28 <transition
29 sourceState="INITIAL"
30 destinationState="private"
31 name="initial_private"
32 title="Make Private"
33 triggerMode="Automatic" />
34
35 <transition
36 sourceState="pending"
37 destinationState="published"
38 name="pending_published"
39 title="Publish Message"
40 permission="book.messageboard.PublishContent"
41 triggerMode="Manual" />
42
43 <transition
44 sourceState="pending"
45 destinationState="private"
46 name="pending_private"
47 title="Retract Message"
48 permission="book.messageboard.Edit"
49 triggerMode="Manual" />
50
51 <transition
52 sourceState="pending"
53 destinationState="private"
54 name="pending_private_reject"
55 title="Reject Message"
56 permission="book.messageboard.PublishContent"
57 triggerMode="Manual" />
58
59 </transitions>
60
61 </workflow>
第 2 行: 定义工作流为状态工作流,这是当然唯一能实现的类型。 “title” 是用来标识工作流的。
第 3 行: 我们并没有特定的数据模式,所以我们忽略它。这些模式常用来允许开发者添加额外的与工作流相关的数据(特定对象)到工作流实例中。
第 4-9 行: 定义消息可能进入的状态。标题再一次被用于增强状态介绍的可读性。
第 10-59 行: 这是一个对象可能会经历的转换列表。我想转换指令属性是可以自说明的并不需要任何更多的解释。
一旦你保存了 XML 文件之后,点击最新创建的工作流(在 “Workflows” 工具界面)并点击 “Import/Export” 标签。从文件中将 XML 拷至屏幕的文本框里。然后点击 “Import” 按钮。相同的屏幕将返回并提示 “Import was successfull!”. 你也将在屏幕底部看到 XML (也许格式有所不同)。如果你现在点击 ManageStates,你将看到刚才通过 XML 导入的四种状态。这同样也发生在 ManageTransitions 视图中。
你也许已经注意到工作流要求定义一个名为 “book.messageboard.PublishContent” 的新权限,因此在消息栏的配置文件中添加权限:
1 <permission
2 id="book.messageboard.PublishContent"
3 title="Publish Message"
4 description="Publish Message."/>
在 security.zcml 配置文件中允许 “Editor” 有权发布内容。
1 <grant
2 permission="book.messageboard.PublishContent"
3 role="book.messageboard.Editor"/>
现在重启 Zope 3。That should be everything that’s to it! 现在让我们看看它们是否运行正常。