[Checkins] SVN: Grokstar/trunk/ Introduce the use of hurry.workflow to workflow the blog. Right now

Martijn Faassen faassen at infrae.com
Thu Feb 1 17:25:16 EST 2007


Log message for revision 72314:
  Introduce the use of hurry.workflow to workflow the blog. Right now
  we've implemented a very simple, non-versioned workflow from 
  CREATED to PUBLISHED. Entries that have not yet been PUBLISHED do
  not show up on the blog frontpage or the calendar. You need to
  edit them (by remembering their name and adding it behind the blog root URL and
  doing '/edit' :) and click 'publish'.
  

Changed:
  U   Grokstar/trunk/buildout.cfg
  U   Grokstar/trunk/setup.py
  U   Grokstar/trunk/src/grokstar/blog.py
  U   Grokstar/trunk/src/grokstar/calendar.py
  U   Grokstar/trunk/src/grokstar/entry.py
  U   Grokstar/trunk/src/grokstar/interfaces.py
  A   Grokstar/trunk/src/grokstar/workflow.py

-=-
Modified: Grokstar/trunk/buildout.cfg
===================================================================
--- Grokstar/trunk/buildout.cfg	2007-02-01 22:05:59 UTC (rev 72313)
+++ Grokstar/trunk/buildout.cfg	2007-02-01 22:25:15 UTC (rev 72314)
@@ -7,6 +7,15 @@
 extra_options = --with-python=${buildout:executable} --force
 url = http://www.zope.org/Products/Zope3/3.3.0/Zope-3.3.0.tgz
 
+# the above part might not work if you have Python 2.4.4. This version
+# of Python is not compatible with Zope 3.3.0. Instead, you can *remove*
+# the 'zope3' name from the 'parts' listing in the [buildout] section,
+# and uncomment what's below. Check out a version of Zope 3.3 branch 
+# and do 'make inplace', and point to it with 'location' below. Then
+# rerun bin/buildout
+# [zope3]
+# location = /home/faassen/buildout/Zope3.3
+
 [data]
 recipe = zc.recipe.filestorage
 
@@ -42,6 +51,7 @@
        grokstar
        hurry.query
        zc.catalog
+       hurry.workflow
 
 [test]
 recipe = zc.recipe.testrunner

Modified: Grokstar/trunk/setup.py
===================================================================
--- Grokstar/trunk/setup.py	2007-02-01 22:05:59 UTC (rev 72313)
+++ Grokstar/trunk/setup.py	2007-02-01 22:25:15 UTC (rev 72314)
@@ -21,6 +21,7 @@
       install_requires=['setuptools',
                         'grok',
                         'hurry.query',
+                        'hurry.workflow',
                         ],
       entry_points="""
       # -*- Entry points: -*-

Modified: Grokstar/trunk/src/grokstar/blog.py
===================================================================
--- Grokstar/trunk/src/grokstar/blog.py	2007-02-01 22:05:59 UTC (rev 72313)
+++ Grokstar/trunk/src/grokstar/blog.py	2007-02-01 22:25:15 UTC (rev 72314)
@@ -8,11 +8,18 @@
 from zope.app.catalog.interfaces import ICatalog
 from zope.app.catalog.field import FieldIndex
 
+from hurry.query.query import Query
+from hurry import query
+from hurry.workflow.interfaces import IWorkflowState
+
 import grok
-from grokstar.interfaces import IEntry
 
+from grokstar.interfaces import IEntry, PUBLISHED
+
 def setup_catalog(catalog):
     catalog['published'] = FieldIndex('published', IEntry)
+    catalog['workflow_state'] = FieldIndex('getState', IWorkflowState, True)
+    catalog['workflow_id'] = FieldIndex('getId', IWorkflowState, True)
     
 class Blog(grok.Container, grok.Site):
 
@@ -55,7 +62,10 @@
         return "Entries: %s" % ' '.join(self.context.keys())
 
 def lastEntries(amount):
-    entries = grok.getSite()['entries'].values()
+    entries = Query().searchResults(
+        query.Eq(('entry_catalog', 'workflow_state'),
+                  PUBLISHED))
+
     return sorted(
         entries, key=lambda entry: entry.published, reverse=True
         )[:amount]

Modified: Grokstar/trunk/src/grokstar/calendar.py
===================================================================
--- Grokstar/trunk/src/grokstar/calendar.py	2007-02-01 22:05:59 UTC (rev 72313)
+++ Grokstar/trunk/src/grokstar/calendar.py	2007-02-01 22:25:15 UTC (rev 72314)
@@ -5,6 +5,8 @@
 from hurry.query.query import Query
 from hurry import query
 
+from grokstar.interfaces import PUBLISHED
+
 class Year(grok.Model):
     def __init__(self, year):
         self.year = year
@@ -78,7 +80,9 @@
 
 def entriesInDateRange(from_, until):
     entries = Query().searchResults(
-        query.Between(('entry_catalog', 'published'), from_, until))
+        query.And(query.Between(('entry_catalog', 'published'), from_, until),
+                  query.Eq(('entry_catalog', 'workflow_state'), PUBLISHED)))
+    
     return sorted(
         entries, key=lambda entry: entry.published, reverse=True
         )

Modified: Grokstar/trunk/src/grokstar/entry.py
===================================================================
--- Grokstar/trunk/src/grokstar/entry.py	2007-02-01 22:05:59 UTC (rev 72313)
+++ Grokstar/trunk/src/grokstar/entry.py	2007-02-01 22:25:15 UTC (rev 72314)
@@ -2,19 +2,22 @@
 from docutils.core import publish_parts
 
 from zope import schema, interface
+from zope.annotation.interfaces import IAttributeAnnotatable
 
+from hurry.workflow.interfaces import IWorkflowInfo
+
 import grok
 
 from grokstar.blog import Blog
 from grokstar import interfaces
 
 class Entry(grok.Model):
-    interface.implements(interfaces.IEntry)
+    interface.implements(interfaces.IEntry, IAttributeAnnotatable)
 
     def __init__(self, title, summary, rightsinfo):
         self.title = title
         self.updated = datetime.now()
-        self.published = datetime.now()
+        self.published = None
         self.summary = summary
         self.rightsinfo = rightsinfo
         
@@ -37,7 +40,9 @@
 
     @grok.action('Add entry')
     def add(self, id, **data):
-        self.context['entries'][id] = RestructuredTextEntry(**data)
+        new_entry = RestructuredTextEntry(**data)
+        self.context['entries'][id] = new_entry
+        IWorkflowInfo(new_entry).fireTransition('create')
         self.redirect(self.url(self.context))
 
 class Edit(grok.EditForm):
@@ -49,6 +54,13 @@
         self.applyChanges(**data)
         self.redirect(self.url(self.context))
 
+    @grok.action('Publish')
+    def publish(self, **data):
+        self.applyChanges(**data)
+        self.context.published = datetime.now()
+        IWorkflowInfo(self.context).fireTransitionToward(interfaces.PUBLISHED)
+        self.redirect(self.url(self.context))
+
 class RenderedContent(grok.View):
     def render(self):
         return renderRest(self.context.content)

Modified: Grokstar/trunk/src/grokstar/interfaces.py
===================================================================
--- Grokstar/trunk/src/grokstar/interfaces.py	2007-02-01 22:05:59 UTC (rev 72313)
+++ Grokstar/trunk/src/grokstar/interfaces.py	2007-02-01 22:25:15 UTC (rev 72314)
@@ -1,6 +1,9 @@
 from zope.interface import Interface
 from zope import schema, interface
 
+CREATED = 0
+PUBLISHED = 1
+
 class IEntry(Interface):
     """
     This interface is based on the Atom entry definition, from the Atom RFC.

Added: Grokstar/trunk/src/grokstar/workflow.py
===================================================================
--- Grokstar/trunk/src/grokstar/workflow.py	2007-02-01 22:05:59 UTC (rev 72313)
+++ Grokstar/trunk/src/grokstar/workflow.py	2007-02-01 22:25:15 UTC (rev 72314)
@@ -0,0 +1,65 @@
+import grok
+from grokstar.entry import Entry
+from hurry.workflow import workflow
+from hurry.workflow.interfaces import IWorkflow
+from hurry.query.query import Query
+from hurry.query import Eq
+
+from grokstar.interfaces import CREATED, PUBLISHED
+
+def create_workflow():
+    create_transition = workflow.Transition(
+        transition_id='create',
+        title='create',
+        source=None,
+        destination=CREATED)
+
+    publish_transition = workflow.Transition(
+        transition_id='publish',
+        title='publish',
+        source=CREATED,
+        destination=PUBLISHED)
+
+    update_transition = workflow.Transition(
+        transition_id='update',
+        title='update',
+        source=PUBLISHED,
+        destination=PUBLISHED)
+    
+    return [create_transition, publish_transition, update_transition]
+
+class Workflow(grok.GlobalUtility, workflow.Workflow):
+    # grok.name('grokstar_workflow')
+    grok.provides(IWorkflow)
+    
+    def __init__(self):
+        super(Workflow, self).__init__(create_workflow())
+
+class Versions(grok.GlobalUtility, workflow.WorkflowVersions):
+
+    def getVersions(self, state, id):
+        q = Query()
+        return q.searchResults(
+            Eq(('entry_catalog', 'workflow_state'),
+               state) &
+            Eq(('entry_catalog', 'workflow_id'),
+               id))     
+    
+    def getVersionsWithAutomaticTransitions(self):
+        return []
+
+    def hasVersion(self, id, state):
+        return bool(len(self.getVersions(state, id)))
+          
+    def hasVersionId(self, id):
+        q = Query()
+        result = q.searchResults(
+            Eq(('entry_catalog', 'workflow_id'), id))
+        return bool(len(result))
+    
+class WorkflowState(grok.Adapter, workflow.WorkflowState):
+    grok.context(Entry)
+    
+class WorkflowInfo(grok.Adapter, workflow.WorkflowInfo):
+    grok.context(Entry)
+



More information about the Checkins mailing list