Commits

Anonymous committed cc1f5dd

add original 0.2 code

Comments (0)

Files changed (40)

+recursive-include ilrt *
+global-exclude *pyc
+Metadata-Version: 1.0
+Name: ilrt.formalworkflow
+Version: 0.2
+Summary: Formal workflow for Plone prevents editing, deletion or reversion of published content from skipping review
+Home-page: https://svn.ilrt.bris.ac.uk/repos/ecu/trunk/src/ilrt.formalworkflow
+Author: Internet Development, ILRT, University of Bristol
+Author-email: internet-development@bris.ac.uk
+License: GPL
+Description: ILRT Formal Workflow
+        ====================
+        
+        Overview
+        --------
+        
+        Ed Crewe, `ILRT
+        <http://www.ilrt.bris.ac.uk/>`_ at University of Bristol, January 2009
+        
+        Formal workflow is designed for sites where there may be many editors
+        for whom unmoderated access to change live published content on the
+        web site is not desired. A typical scenario may be an organistaions
+        public website which has to comply with certain legal restrictions or
+        editorial style for example. To ensure this compliance only a limited
+        subset of editors are trusted to review and publish content.
+        
+        This package applies a workflow definition based on simple publication
+        workflow ... but it ensures that editors cannot modify public content.
+        Instead it enables `plone.app.iterate`_  with which users can check out a
+        working copy of a published item to work on and resubmit for review.
+        
+        .. _`plone.app.iterate`: http://pypi.python.org/pypi/plone.app.iterate
+        
+        Editors and owners are also restricted from deleting items or reverting
+        them to past versions ... essentially anything that could change published
+        content ... without review.
+        
+        Hence only new items can be published, instead working copies are checked in
+        by users with the reviewer or manager role.
+        
+        The package installs a skin layer in order to allow for modifying the iterate
+        interfaces security declaration. If used in conjunction with a theme egg just
+        copy the contents of browser/configuration.xml to the one in your theme.
+        
+        Workflow
+        --------
+        
+        A diagram of the workflow is available in /docs folder
+        
+        .. image:: http://mail.ilrt.bris.ac.uk/~cmetc/images/formalworkflow.png
+        
+        The following walks through a user story::
+        
+        Editor
+        - An editor creates a document
+        - They edit and then submit it for review
+        - It is now in the pending state
+        
+        Reviewer
+        - The document appears for review in their review list so they click on it
+        - They make a few minor ammendments and publish it
+        
+        Editor
+        - A week later some more information needs to be added to the document
+        - The editor goes to it, but it there is no workflow menu just
+        State:Published so they cannot retract it. The edit and history tabs
+        are also gone. So instead they must click on 'Check out' from the actions menu.
+        - This locks the item and marks it as being edited in a working copy.
+        - The editor does their edits then clicks on submit to bring their changes to the
+        attention of the reviewer
+        
+        Reviewer
+        - The reviewer sees the page pop up in their review list
+        - They click on it and look at the changes the editor has made.
+        They like the changes but decide they want some modifications made to them
+        by the editor. They dont want to 'Cancel check-out' since the editor has done a
+        lot of changes, so they just add a note of the further changes needed and make
+        the working copy private again.
+        
+        Editor
+        - The editor reads the comment and re-edits the working copy, once these final changes
+        are complete is it resubmitted to the pending state.
+        
+        Reviewer
+        - The reviewer notices the item is back again in their review list, so realises
+        it has been re-edited.
+        They click on it ... see that it is ready and so do the 'Check in' to replace
+        the current published version, at which point the working copy is removed.
+        
+        This package hardly deserves to be in pypi since it is really all just
+        xml config data, however since it is a commonly required workflow which
+        does require some time consuming configuration tweaks, It seemed worthwhile to
+        submit it ... at least it has some python in the functional tests.
+        
+        NB: If this workflow is applied to an existing site ... then you may require the
+        ilrt.migrationtool to use its utility for mapping  existing content states from
+        the old workflow to formalworkflow
+        
+        
+        Changelog for ilrt.formalworkflow
+        ---------------------------------
+        
+        (name of developer listed in brackets)
+        
+        ilrt.formalworkflow - 0.2 Released
+        
+        - Released to pypi with some documentation
+        [Ed Crewe, ILRT - University of Bristol]
+        
+        ilrt.formalworkflow - 0.1 Unreleased
+        
+        - Initial package structure.
+        [zopeskel]
+        
+        
+Keywords: web zope plone workflow
+Platform: UNKNOWN
+Classifier: Programming Language :: Python
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Environment :: Web Environment
+Classifier: Framework :: Plone
+Classifier: Framework :: Zope2
+Classifier: Framework :: Zope3
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Other Audience
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
+Classifier: Development Status :: 4 - Beta
+ILRT Formal Workflow
+====================
+
+Overview
+--------
+
+Ed Crewe, `ILRT
+<http://www.ilrt.bris.ac.uk/>`_ at University of Bristol, January 2009
+
+Formal workflow is designed for sites where there may be many editors
+for whom unmoderated access to change live published content on the 
+web site is not desired. A typical scenario may be an organistaions 
+public website which has to comply with certain legal restrictions or
+editorial style for example. To ensure this compliance only a limited
+subset of editors are trusted to review and publish content.
+
+This package applies a workflow definition based on simple publication 
+workflow ... but it ensures that editors cannot modify public content.
+Instead it enables `plone.app.iterate`_  with which users can check out a 
+working copy of a published item to work on and resubmit for review.
+
+.. _`plone.app.iterate`: http://pypi.python.org/pypi/plone.app.iterate
+
+Editors and owners are also restricted from deleting items or reverting 
+them to past versions ... essentially anything that could change published 
+content ... without review.
+
+Hence only new items can be published, instead working copies are checked in 
+by users with the reviewer or manager role.
+
+The package installs a skin layer in order to allow for modifying the iterate 
+interfaces security declaration. If used in conjunction with a theme egg just 
+copy the contents of browser/configuration.xml to the one in your theme.
+
+Workflow
+--------
+
+A diagram of the workflow is available in /docs folder   
+
+.. image:: http://mail.ilrt.bris.ac.uk/~cmetc/images/formalworkflow.png
+
+The following walks through a user story::
+
+  Editor
+  - An editor creates a document
+  - They edit and then submit it for review
+  - It is now in the pending state
+
+  Reviewer
+  - The document appears for review in their review list so they click on it
+  - They make a few minor ammendments and publish it
+
+  Editor
+  - A week later some more information needs to be added to the document
+  - The editor goes to it, but it there is no workflow menu just 
+    State:Published so they cannot retract it. The edit and history tabs
+    are also gone. So instead they must click on 'Check out' from the actions menu.
+  - This locks the item and marks it as being edited in a working copy.
+  - The editor does their edits then clicks on submit to bring their changes to the
+    attention of the reviewer
+
+  Reviewer
+  - The reviewer sees the page pop up in their review list
+  - They click on it and look at the changes the editor has made. 
+    They like the changes but decide they want some modifications made to them
+    by the editor. They dont want to 'Cancel check-out' since the editor has done a
+    lot of changes, so they just add a note of the further changes needed and make
+    the working copy private again.
+
+  Editor
+  - The editor reads the comment and re-edits the working copy, once these final changes
+    are complete is it resubmitted to the pending state. 
+
+  Reviewer
+  - The reviewer notices the item is back again in their review list, so realises 
+    it has been re-edited.
+    They click on it ... see that it is ready and so do the 'Check in' to replace 
+    the current published version, at which point the working copy is removed.
+
+This package hardly deserves to be in pypi since it is really all just
+xml config data, however since it is a commonly required workflow which
+does require some time consuming configuration tweaks, It seemed worthwhile to
+submit it ... at least it has some python in the functional tests. 
+
+NB: If this workflow is applied to an existing site ... then you may require the 
+ilrt.migrationtool to use its utility for mapping  existing content states from 
+the old workflow to formalworkflow
+
+Changelog for ilrt.formalworkflow
+---------------------------------
+
+(name of developer listed in brackets)
+
+ilrt.formalworkflow - 0.2 Released
+
+- Released to pypi with some documentation
+  [Ed Crewe, ILRT - University of Bristol]
+
+ilrt.formalworkflow - 0.1 Unreleased
+
+- Initial package structure.
+  [zopeskel]
+
+ilrt.formalworkflow Installation
+=======================
+
+To install ilrt.formalworkflow into the global Python environment (or a workingenv),
+using a traditional Zope 2 instance, you can do this:
+
+ * When you're reading this you have probably already run 
+   ``easy_install ilrt.formalworkflow``. Find out how to install setuptools
+   (and EasyInstall) here:
+   http://peak.telecommunity.com/DevCenter/EasyInstall
+
+ * If you are using Zope 2.9 (not 2.10), get `pythonproducts`_ and install it 
+   via::
+
+       python setup.py install --home /path/to/instance
+
+   into your Zope instance.
+
+ * Create a file called ``ilrt.formalworkflow-configure.zcml`` in the
+   ``/path/to/instance/etc/package-includes`` directory.  The file
+   should only contain this::
+
+       <include package="ilrt.formalworkflow" />
+
+.. _pythonproducts: http://plone.org/products/pythonproducts
+
+Alternatively, if you are using zc.buildout and the plone.recipe.zope2instance
+recipe to manage your project, you can do this:
+
+ * Add ``ilrt.formalworkflow`` to the list of eggs to install, e.g.:
+ 
+    [buildout]
+    ...
+    eggs =
+        ...
+        ilrt.formalworkflow
+        
+  * Tell the plone.recipe.zope2instance recipe to install a ZCML slug:
+  
+    [instance]
+    recipe = plone.recipe.zope2instance
+    ...
+    zcml =
+        ilrt.formalworkflow
+        
+  * Re-run buildout, e.g. with:
+  
+    $ ./bin/buildout
+        
+You can skip the ZCML slug if you are going to explicitly include the package
+from another package's configure.zcml file.
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+  ilrt.formalworkflow is copyright Internet Development, ILRT, University of Bristol
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+  MA 02111-1307 USA.
Add a comment to this file

docs/formalworkflow.png

Added
New image

ilrt.formalworkflow-configure.zcml

+<include package="ilrt.formalworkflow" />

ilrt.formalworkflow.egg-info/PKG-INFO

+Metadata-Version: 1.0
+Name: ilrt.formalworkflow
+Version: 0.2
+Summary: Formal workflow for Plone prevents editing, deletion or reversion of published content from skipping review
+Home-page: https://svn.ilrt.bris.ac.uk/repos/ecu/trunk/src/ilrt.formalworkflow
+Author: Internet Development, ILRT, University of Bristol
+Author-email: internet-development@bris.ac.uk
+License: GPL
+Description: ILRT Formal Workflow
+        ====================
+        
+        Overview
+        --------
+        
+        Ed Crewe, `ILRT
+        <http://www.ilrt.bris.ac.uk/>`_ at University of Bristol, January 2009
+        
+        Formal workflow is designed for sites where there may be many editors
+        for whom unmoderated access to change live published content on the
+        web site is not desired. A typical scenario may be an organistaions
+        public website which has to comply with certain legal restrictions or
+        editorial style for example. To ensure this compliance only a limited
+        subset of editors are trusted to review and publish content.
+        
+        This package applies a workflow definition based on simple publication
+        workflow ... but it ensures that editors cannot modify public content.
+        Instead it enables `plone.app.iterate`_  with which users can check out a
+        working copy of a published item to work on and resubmit for review.
+        
+        .. _`plone.app.iterate`: http://pypi.python.org/pypi/plone.app.iterate
+        
+        Editors and owners are also restricted from deleting items or reverting
+        them to past versions ... essentially anything that could change published
+        content ... without review.
+        
+        Hence only new items can be published, instead working copies are checked in
+        by users with the reviewer or manager role.
+        
+        The package installs a skin layer in order to allow for modifying the iterate
+        interfaces security declaration. If used in conjunction with a theme egg just
+        copy the contents of browser/configuration.xml to the one in your theme.
+        
+        Workflow
+        --------
+        
+        A diagram of the workflow is available in /docs folder
+        
+        .. image:: http://mail.ilrt.bris.ac.uk/~cmetc/images/formalworkflow.png
+        
+        The following walks through a user story::
+        
+        Editor
+        - An editor creates a document
+        - They edit and then submit it for review
+        - It is now in the pending state
+        
+        Reviewer
+        - The document appears for review in their review list so they click on it
+        - They make a few minor ammendments and publish it
+        
+        Editor
+        - A week later some more information needs to be added to the document
+        - The editor goes to it, but it there is no workflow menu just
+        State:Published so they cannot retract it. The edit and history tabs
+        are also gone. So instead they must click on 'Check out' from the actions menu.
+        - This locks the item and marks it as being edited in a working copy.
+        - The editor does their edits then clicks on submit to bring their changes to the
+        attention of the reviewer
+        
+        Reviewer
+        - The reviewer sees the page pop up in their review list
+        - They click on it and look at the changes the editor has made.
+        They like the changes but decide they want some modifications made to them
+        by the editor. They dont want to 'Cancel check-out' since the editor has done a
+        lot of changes, so they just add a note of the further changes needed and make
+        the working copy private again.
+        
+        Editor
+        - The editor reads the comment and re-edits the working copy, once these final changes
+        are complete is it resubmitted to the pending state.
+        
+        Reviewer
+        - The reviewer notices the item is back again in their review list, so realises
+        it has been re-edited.
+        They click on it ... see that it is ready and so do the 'Check in' to replace
+        the current published version, at which point the working copy is removed.
+        
+        This package hardly deserves to be in pypi since it is really all just
+        xml config data, however since it is a commonly required workflow which
+        does require some time consuming configuration tweaks, It seemed worthwhile to
+        submit it ... at least it has some python in the functional tests.
+        
+        NB: If this workflow is applied to an existing site ... then you may require the
+        ilrt.migrationtool to use its utility for mapping  existing content states from
+        the old workflow to formalworkflow
+        
+        
+        Changelog for ilrt.formalworkflow
+        ---------------------------------
+        
+        (name of developer listed in brackets)
+        
+        ilrt.formalworkflow - 0.2 Released
+        
+        - Released to pypi with some documentation
+        [Ed Crewe, ILRT - University of Bristol]
+        
+        ilrt.formalworkflow - 0.1 Unreleased
+        
+        - Initial package structure.
+        [zopeskel]
+        
+        
+Keywords: web zope plone workflow
+Platform: UNKNOWN
+Classifier: Programming Language :: Python
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Environment :: Web Environment
+Classifier: Framework :: Plone
+Classifier: Framework :: Zope2
+Classifier: Framework :: Zope3
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Other Audience
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
+Classifier: Development Status :: 4 - Beta

ilrt.formalworkflow.egg-info/SOURCES.txt

+MANIFEST.in
+PKG-INFO
+README.txt
+ilrt.formalworkflow-configure.zcml
+setup.cfg
+setup.py
+dist/ilrt.formalworkflow-0.2-py2.4.egg
+dist/ilrt.formalworkflow-0.2.tar.gz
+docs/HISTORY.txt
+docs/INSTALL.txt
+docs/LICENSE.GPL
+docs/LICENSE.txt
+docs/formalworkflow.png
+ilrt/__init__.py
+ilrt.formalworkflow.egg-info/PKG-INFO
+ilrt.formalworkflow.egg-info/SOURCES.txt
+ilrt.formalworkflow.egg-info/dependency_links.txt
+ilrt.formalworkflow.egg-info/entry_points.txt
+ilrt.formalworkflow.egg-info/namespace_packages.txt
+ilrt.formalworkflow.egg-info/not-zip-safe
+ilrt.formalworkflow.egg-info/paster_plugins.txt
+ilrt.formalworkflow.egg-info/requires.txt
+ilrt.formalworkflow.egg-info/top_level.txt
+ilrt/formalworkflow/__init__.py
+ilrt/formalworkflow/configure.zcml
+ilrt/formalworkflow/profiles.zcml
+ilrt/formalworkflow/setuphandlers.py
+ilrt/formalworkflow/version.txt
+ilrt/formalworkflow/browser/README.txt
+ilrt/formalworkflow/browser/__init__.py
+ilrt/formalworkflow/browser/configure.zcml
+ilrt/formalworkflow/browser/interfaces.py
+ilrt/formalworkflow/profiles/default/actions.xml
+ilrt/formalworkflow/profiles/default/ilrt.formalworkflow_various.txt
+ilrt/formalworkflow/profiles/default/import_steps.xml
+ilrt/formalworkflow/profiles/default/skins.xml
+ilrt/formalworkflow/profiles/default/workflows.xml
+ilrt/formalworkflow/profiles/default/workflows/formal_workflow/definition.xml
+ilrt/formalworkflow/tests/__init__.py
+ilrt/formalworkflow/tests/base.py
+ilrt/formalworkflow/tests/functional.txt
+ilrt/formalworkflow/tests/test_functional.py

ilrt.formalworkflow.egg-info/dependency_links.txt

+

ilrt.formalworkflow.egg-info/entry_points.txt

+
+      # -*- Entry points: -*-
+      

ilrt.formalworkflow.egg-info/namespace_packages.txt

+ilrt

ilrt.formalworkflow.egg-info/not-zip-safe

+

ilrt.formalworkflow.egg-info/paster_plugins.txt

+PasteScript

ilrt.formalworkflow.egg-info/requires.txt

+setuptools

ilrt.formalworkflow.egg-info/top_level.txt

+ilrt
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

ilrt/formalworkflow/__init__.py

+
+def initialize(context):
+    """Initializer called when used as a Zope 2 product."""

ilrt/formalworkflow/browser/README.txt

+Iterate security changes via the default edit layer
+===================================================
+
+Please note that if you use formalworkflow with a theme egg 
+or other package that defines its own layer ... you will 
+have to respecify the security changes in configure.zcml
+for the layer it defines ... ie. copy the contents of 
+browser/configure.zcml to the one in your theme egg 
+browser folder.
+
+Without these changes ... the permission to checkout an 
+iteration of an item is the same as being able to modify 
+the original. Hence inappropriate for formal workflow.
+
+NB: plone.app.iterate's own declaration has precidence
+for layer="plone.theme.interfaces.IDefaultPloneLayer"
+
+Ed Crewe

ilrt/formalworkflow/browser/__init__.py

+#

ilrt/formalworkflow/browser/configure.zcml

+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="ilrt.formalworkflow">
+
+    <!-- 'formalworkflow' Zope 3 browser layer 
+	 This layer is purely for modifying the interface permissions on app.iterate
+         So that iterations can be made of content that the user has copy but
+         not modify permissions for - e.g. published content
+    -->
+
+    <interface
+        interface=".interfaces.IThemeSpecific"
+        type="zope.publisher.interfaces.browser.IBrowserSkinType"
+        name="formalworkflow"
+        />
+    
+    <browser:page
+        for="plone.app.iterate.interfaces.IIterateAware"
+        name="content-checkout"
+        class="plone.app.iterate.browser.checkout.Checkout"
+        permission="zope2.CopyOrMove"
+        layer=".interfaces.IThemeSpecific"
+        />
+
+    <browser:page
+        for="plone.app.iterate.interfaces.IIterateAware"
+        name="content-cancel-checkout"
+        class="plone.app.iterate.browser.cancel.Cancel"
+        permission="zope2.CopyOrMove"
+        layer=".interfaces.IThemeSpecific"
+        />
+
+
+</configure>

ilrt/formalworkflow/browser/interfaces.py

+from plone.theme.interfaces import IDefaultPloneLayer
+
+class IThemeSpecific(IDefaultPloneLayer):
+    """Marker interface that defines a Zope 3 browser layer.
+    """

ilrt/formalworkflow/configure.zcml

+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:five="http://namespaces.zope.org/five"
+    xmlns:cmf="http://namespaces.zope.org/cmf"
+    i18n_domain="ilrt.formalworkflow">
+
+   <five:registerPackage package="." initialize=".initialize" />
+   <include package=".browser"/>
+   <include file="profiles.zcml" />
+
+</configure>

ilrt/formalworkflow/profiles.zcml

+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
+    i18n_domain="ilrt.formalworkflow">
+
+  <genericsetup:registerProfile
+      name="formalworkflow"
+      title="Formal Workflow"
+      directory="profiles/default"
+      description='Extension profile for the "formalworkflow" Plone theme.'
+      provides="Products.GenericSetup.interfaces.EXTENSION"
+      />
+
+</configure>

ilrt/formalworkflow/profiles/default/actions.xml

+<?xml version="1.0"?>
+<object name="portal_actions" meta_type="Plone Actions Tool"
+   xmlns:i18n="http://xml.zope.org/namespaces/i18n">
+ <object name="object_buttons" meta_type="CMF Action Category">
+     
+  <object name="iterate_checkout" meta_type="CMF Action" i18n:domain="plone">
+   <property name="title" i18n:translate="">Check out</property>
+   <property name="description" i18n:translate=""></property>
+   <property name="url_expr">string:${object_url}/@@content-checkout</property>
+   <property name="icon_expr"></property>
+   <property name="available_expr">python:path('object/@@iterate_control').checkout_allowed()</property>
+   <property name="permissions">
+    <element value="Copy or Move"/>
+   </property>
+   <property name="visible">True</property>
+  </object>
+  
+  <object name="iterate_checkout_cancel" meta_type="CMF Action" i18n:domain="plone">
+   <property name="title" i18n:translate="">Cancel check-out</property>
+   <property name="description" i18n:translate=""></property>
+   <property name="url_expr">string:${object_url}/@@content-cancel-checkout</property>
+   <property name="icon_expr"></property>
+   <property name="available_expr">python:path('object/@@iterate_control').cancel_allowed()</property>
+   <property name="permissions">
+    <element value="Copy or Move"/>
+   </property>
+   <property name="visible">True</property>
+  </object>
+  
+ </object>
+</object>

ilrt/formalworkflow/profiles/default/ilrt.formalworkflow_various.txt

+This file is used as a marker in setuphandlers.py.

ilrt/formalworkflow/profiles/default/import_steps.xml

+<?xml version="1.0"?>
+<import-steps>
+  <import-step id="ilrt.formalworkflow.various"
+               version="20081209-01"
+               handler="ilrt.formalworkflow.setuphandlers.setupVarious"
+               title="formalworkflow: miscellaneous import steps">
+    <dependency step="setuphandlers" />
+    Various import steps that are not handled by GS import/export
+    handlers.
+  </import-step>
+</import-steps>

ilrt/formalworkflow/profiles/default/skins.xml

+<?xml version="1.0"?>
+<!-- This is just so that the security settings of this layer are applied
+ see browser/README.txt to allow for using your preferred skin  -->
+
+ <object name="portal_skins" allow_any="False" cookie_persistence="False"
+   default_skin="formalworkflow">
+
+ <skin-path name="formalworkflow" based-on="Plone Default">
+ </skin-path>
+
+
+</object>

ilrt/formalworkflow/profiles/default/workflows.xml

+<?xml version="1.0"?>
+<object name="portal_workflow" meta_type="Plone Workflow Tool">
+ <property
+    name="title">Contains workflow definitions for your portal</property>
+ <object name="formal_workflow" meta_type="Workflow"/>
+ <bindings>
+  <default>
+   <bound-workflow workflow_id="formal_workflow"/>
+  </default>
+  <type type_id="ATBooleanCriterion"/>
+  <type type_id="ATCurrentAuthorCriterion"/>
+  <type type_id="ATDateCriteria"/>
+  <type type_id="ATDateRangeCriterion"/>
+  <type type_id="ATListCriterion"/>
+  <type type_id="ATPathCriterion"/>
+  <type type_id="ATPortalTypeCriterion"/>
+  <type type_id="ATReferenceCriterion"/>
+  <type type_id="ATRelativePathCriterion"/>
+  <type type_id="ATSelectionCriterion"/>
+  <type type_id="ATSimpleIntCriterion"/>
+  <type type_id="ATSimpleStringCriterion"/>
+  <type type_id="ATSortCriterion"/>
+  <type type_id="Discussion Item"/>
+  <type type_id="File"/>
+  <type type_id="Image"/>
+  <type type_id="Plone Site"/>
+ </bindings>
+</object>

ilrt/formalworkflow/profiles/default/workflows/formal_workflow/definition.xml

+<?xml version="1.0"?>
+<dc-workflow workflow_id="formal_workflow"
+             title="Formal Workflow"
+             description="Based on Simple Publication Workflow but restricting modification of published content. - Only reviewers or managers may edit or retract content that is published. - Ideally iterate should be used in conjunction with this workflow. - Editors may then submit alternative drafts of published content for review. "
+             state_variable="review_state"
+             initial_state="private">
+ <permission>Access contents information</permission>
+ <permission>Change portal events</permission>
+ <permission>Delete objects</permission>
+ <permission>List folder contents</permission>
+ <permission>Modify portal content</permission>
+ <permission>View</permission>
+ <permission>iterate : Check in content</permission>
+ <permission>iterate : Check out content</permission>
+ <state state_id="pending" title="Pending review">
+  <description>Waiting to be reviewed, not editable by the owner.
+</description>
+  <exit-transition transition_id="make_private"/>
+  <exit-transition transition_id="publish"/>
+  <exit-transition transition_id="reject"/>
+  <permission-map name="Access contents information"
+                  acquired="False">
+   <permission-role>Contributor</permission-role>
+   <permission-role>Editor</permission-role>
+   <permission-role>Manager</permission-role>
+   <permission-role>Owner</permission-role>
+   <permission-role>Reader</permission-role>
+   <permission-role>Reviewer</permission-role>
+  </permission-map>
+  <permission-map name="Change portal events"
+                  acquired="False">
+   <permission-role>Manager</permission-role>
+   <permission-role>Reviewer</permission-role>
+  </permission-map>
+  <permission-map name="Delete objects" acquired="False">
+   <permission-role>Manager</permission-role>
+   <permission-role>Reviewer</permission-role>
+  </permission-map>
+  <permission-map name="List folder contents"
+                  acquired="False">
+   <permission-role>Contributor</permission-role>
+   <permission-role>Editor</permission-role>
+   <permission-role>Manager</permission-role>
+   <permission-role>Owner</permission-role>
+   <permission-role>Reader</permission-role>
+   <permission-role>Reviewer</permission-role>
+  </permission-map>
+  <permission-map name="Modify portal content"
+                  acquired="False">
+   <permission-role>Manager</permission-role>
+   <permission-role>Reviewer</permission-role>
+  </permission-map>
+  <permission-map name="View" acquired="False">
+   <permission-role>Contributor</permission-role>
+   <permission-role>Editor</permission-role>
+   <permission-role>Manager</permission-role>
+   <permission-role>Owner</permission-role>
+   <permission-role>Reader</permission-role>
+   <permission-role>Reviewer</permission-role>
+  </permission-map>
+  <permission-map name="iterate : Check in content"
+                  acquired="False">
+   <permission-role>Manager</permission-role>
+   <permission-role>Reviewer</permission-role>
+  </permission-map>
+  <permission-map name="iterate : Check out content"
+                  acquired="False">
+  </permission-map>
+ </state>
+ <state state_id="private" title="Private">
+  <description>Can only be seen and edited by the owner.
+</description>
+  <exit-transition transition_id="publish"/>
+  <exit-transition transition_id="submit"/>
+  <permission-map name="Access contents information"
+                  acquired="False">
+   <permission-role>Contributor</permission-role>
+   <permission-role>Editor</permission-role>
+   <permission-role>Manager</permission-role>
+   <permission-role>Owner</permission-role>
+   <permission-role>Reader</permission-role>
+  </permission-map>
+  <permission-map name="Change portal events"
+                  acquired="False">
+   <permission-role>Editor</permission-role>
+   <permission-role>Manager</permission-role>
+   <permission-role>Owner</permission-role>
+  </permission-map>
+  <permission-map name="Delete objects" acquired="True">
+  </permission-map>
+  <permission-map name="List folder contents"
+                  acquired="False">
+   <permission-role>Contributor</permission-role>
+   <permission-role>Editor</permission-role>
+   <permission-role>Manager</permission-role>
+   <permission-role>Owner</permission-role>
+   <permission-role>Reader</permission-role>
+  </permission-map>
+  <permission-map name="Modify portal content"
+                  acquired="False">
+   <permission-role>Editor</permission-role>
+   <permission-role>Manager</permission-role>
+   <permission-role>Owner</permission-role>
+  </permission-map>
+  <permission-map name="View" acquired="False">
+   <permission-role>Contributor</permission-role>
+   <permission-role>Editor</permission-role>
+   <permission-role>Manager</permission-role>
+   <permission-role>Owner</permission-role>
+   <permission-role>Reader</permission-role>
+  </permission-map>
+  <permission-map name="iterate : Check in content"
+                  acquired="False">
+   <permission-role>Manager</permission-role>
+  </permission-map>
+  <permission-map name="iterate : Check out content"
+                  acquired="False">
+  </permission-map>
+ </state>
+ <state state_id="published" title="Published">
+  <description>Visible to everyone, editable only by manager or reviewer
+</description>
+  <exit-transition transition_id="retract"/>
+  <permission-map name="Access contents information"
+                  acquired="False">
+   <permission-role>Anonymous</permission-role>
+  </permission-map>
+  <permission-map name="Change portal events"
+                  acquired="False">
+   <permission-role>Editor</permission-role>
+   <permission-role>Manager</permission-role>
+   <permission-role>Reviewer</permission-role>
+  </permission-map>
+  <permission-map name="Delete objects" acquired="False">
+   <permission-role>Manager</permission-role>
+   <permission-role>Reviewer</permission-role>
+  </permission-map>
+  <permission-map name="List folder contents"
+                  acquired="False">
+   <permission-role>Anonymous</permission-role>
+  </permission-map>
+  <permission-map name="Modify portal content"
+                  acquired="False">
+   <permission-role>Manager</permission-role>
+   <permission-role>Reviewer</permission-role>
+  </permission-map>
+  <permission-map name="View" acquired="False">
+   <permission-role>Anonymous</permission-role>
+  </permission-map>
+  <permission-map name="iterate : Check in content"
+                  acquired="False">
+   <permission-role>Manager</permission-role>
+   <permission-role>Reviewer</permission-role>
+  </permission-map>
+  <permission-map name="iterate : Check out content"
+                  acquired="False">
+   <permission-role>Editor</permission-role>
+   <permission-role>Manager</permission-role>
+   <permission-role>Reviewer</permission-role>
+  </permission-map>
+ </state>
+ <transition transition_id="publish"
+             title="Reviewer publishes content"
+             new_state="published" trigger="USER"
+             before_script="" after_script="">
+  <description>Publishing the item makes it visible to users of the site.
+</description>
+  <action url="%(content_url)s/content_status_modify?workflow_action=publish"
+          category="workflow">Publish</action>
+  <guard>
+   <guard-permission>Review portal content</guard-permission>
+   <guard-expression>python:not path('object/@@iterate_control').cancel_allowed()</guard-expression>
+  </guard>
+ </transition>
+ <transition transition_id="reject"
+             title="Content taken, or sent back for re-drafting"
+             new_state="private" trigger="USER"
+             before_script="" after_script="">
+  <description>Sending the item back will return the item to the original author and make it private, instead of publishing it. Reviewers should preferably include a reason for why it was not published.
+</description>
+  <action url="%(content_url)s/content_status_modify?workflow_action=reject"
+          category="workflow">Make private</action>
+  <guard>
+   <guard-permission>Request review</guard-permission>
+  </guard>
+ </transition>
+ <transition transition_id="retract"
+             title="Reviewer retracts submission"
+             new_state="private" trigger="USER"
+             before_script="" after_script="">
+  <description>If you published the item by mistake or want to unpublish it whilst doing additional edits, this will take it back.
+</description>
+  <action url="%(content_url)s/content_status_modify?workflow_action=retract"
+          category="workflow">Retract</action>
+  <guard>
+   <guard-permission>Review portal content</guard-permission>
+  </guard>
+ </transition>
+ <transition transition_id="submit"
+             title="Member submits content for publication"
+             new_state="pending" trigger="USER"
+             before_script="" after_script="">
+  <description>Puts your item in a review queue, so it can be published on the site.
+</description>
+  <action url="%(content_url)s/content_status_modify?workflow_action=submit"
+          category="workflow">Submit for publication</action>
+  <guard>
+   <guard-permission>Request review</guard-permission>
+  </guard>
+ </transition>
+ <worklist worklist_id="reviewer_queue" title="">
+  <description>Reviewer tasks</description>
+  <action url="%(portal_url)s/search?review_state=pending"
+          category="global">Pending (%(count)d)</action>
+  <guard>
+   <guard-permission>Review portal content</guard-permission>
+  </guard>
+  <match name="review_state" values="pending"/>
+ </worklist>
+ <variable variable_id="action" for_catalog="False"
+           for_status="True" update_always="True">
+  <description>Previous transition</description>
+  <default>
+   
+   <expression>transition/getId|nothing</expression>
+  </default>
+  <guard>
+  </guard>
+ </variable>
+ <variable variable_id="actor" for_catalog="False"
+           for_status="True" update_always="True">
+  <description>The ID of the user who performed the previous transition</description>
+  <default>
+   
+   <expression>user/getUserName</expression>
+  </default>
+  <guard>
+  </guard>
+ </variable>
+ <variable variable_id="comments" for_catalog="False"
+           for_status="True" update_always="True">
+  <description>Comment about the last transition</description>
+  <default>
+   
+   <expression>python:state_change.kwargs.get('comment', '')</expression>
+  </default>
+  <guard>
+  </guard>
+ </variable>
+ <variable variable_id="review_history" for_catalog="False"
+           for_status="False" update_always="False">
+  <description>Provides access to workflow history</description>
+  <default>
+   
+   <expression>state_change/getHistory</expression>
+  </default>
+  <guard>
+   <guard-permission>Request review</guard-permission>
+   <guard-permission>Review portal content</guard-permission>
+  </guard>
+ </variable>
+ <variable variable_id="time" for_catalog="False"
+           for_status="True" update_always="True">
+  <description>When the previous transition was performed</description>
+  <default>
+   
+   <expression>state_change/getDateTime</expression>
+  </default>
+  <guard>
+  </guard>
+ </variable>
+</dc-workflow>

ilrt/formalworkflow/setuphandlers.py

+def setupVarious(context):
+    """ Install plone.app.iterate if its not installed already """
+
+    if context.readDataFile('ilrt.formalworkflow_various.txt') is None:
+        return
+
+    from Products.CMFCore.utils import getToolByName
+    qi_tool = getToolByName(context.getSite(), 'portal_quickinstaller')
+    if not qi_tool.isProductInstalled('plone.app.iterate'):
+        qi_tool.installProduct('plone.app.iterate', swallowExceptions=1)
+
+        # Need to reinstall the formalworkflow zcml so that its
+        # browser/configure.zcml overrides iterates one ... 
+        from Products.Five import zcml
+        import ilrt.formalworkflow
+        zcml.load_config('configure.zcml', ilrt.formalworkflow)
+        
+
+
+    
+
Add a comment to this file

ilrt/formalworkflow/tests/__init__.py

Empty file added.

ilrt/formalworkflow/tests/base.py

+from Testing import ZopeTestCase as ztc
+from Products.PloneTestCase import PloneTestCase as ptc
+from Products.PloneTestCase.layer import onsetup
+from Products.Five import zcml
+from Products.Five import fiveconfigure
+
+import ilrt.formalworkflow
+import plone.app.iterate
+
+@onsetup
+def setup_products():
+    fiveconfigure.debug_mode = True
+    zcml.load_config('configure.zcml',
+                     ilrt.formalworkflow)
+    fiveconfigure.debug_mode = False    
+    ztc.installPackage('ilrt.formalworkflow')
+
+
+class BaseTestCase(ptc.PloneTestCase):
+    """Base class for test cases.
+    """
+
+    def setUp(self):
+        super(BaseTestCase, self).setUp()
+
+class BaseFunctionalTestCase(ptc.FunctionalTestCase):
+    """Base class for test cases.
+    """
+
+    def setUp(self):
+        super(BaseFunctionalTestCase, self).setUp()
+
+setup_products()
+ptc.setupPloneSite(policy='ilrt.formalworkflow:default',
+                   products=['ilrt.formalworkflow'])
+
+
+

ilrt/formalworkflow/tests/functional.txt

+===================================================================
+Functional test of editor trying to re-edit their published content
+===================================================================
+
+Functional tests for the workflow to confirm that it prevents
+users or owners who do not have reviewer rights from 
+re-editing public content that they have created.
+
+Instead they must use iterate and resubmit.
+
+by Ed Crewe, ILRT (University of Bristol) 
+January 2009
+
+    >>> from Products.Five.testbrowser import Browser
+    >>> from Products.PloneTestCase.setup import portal_owner, default_password
+    >>> from Products.CMFPlone.utils import getToolByName
+    >>> from mechanize._mechanize import LinkNotFoundError
+
+
+Site layer security setup 
+=========================
+
+Confirm we are in the skin that allows access to the iterate
+checkout for the Copy or Move permission ... rather than 
+modify portal content - so we can take an iteration of content 
+when we are not allowed to modify the (published) original 
+
+    >>> portal.getCurrentSkinName()
+    'formalworkflow'
+
+Toggle off membership area creation to save going via the iterate location page
+
+    >>> membership = getToolByName(portal,'portal_membership')
+    >>> if membership.getMemberareaCreationFlag():
+    ...    membership.setMemberareaCreationFlag()
+
+Set up the editor and a folder
+==============================
+
+Make the implicit test user (portal_owner) a manager
+
+    >>> self.setRoles(['Manager'])
+    >>> portal_url = portal.absolute_url()
+
+Register a new demo editor user
+
+    >>> editor = "demoeditor"
+    >>> roles = ['Member','Editor','Contributor']
+    >>> uf = portal.acl_users
+    >>> if uf.getUserById(editor) is None:
+    ...     uf.userFolderAddUser(editor, default_password,roles,[]) 
+
+Check we have created the user
+
+    >>> user = uf.getUserById(editor)
+    >>> user.getId()
+    'demoeditor'
+
+Add a folder for the editor to work in ...
+
+    >>> folderid = 'test_folder'
+    >>> doc = portal.invokeFactory("Folder", folderid)
+    >>> folder = getattr(portal, folderid)
+
+Publish it
+
+    >>> wftool = getToolByName(portal, "portal_workflow")
+    >>> wftool.doActionFor(folder,'publish')
+
+Start functional test for editor
+================================
+
+The following is useful when writing and debugging testbrowser tests. It lets
+us see all error messages in the error_log.
+
+    >>> browser = Browser()
+    >>> browser.handleErrors = False
+    >>> self.portal.error_log._ignored_exceptions = ()
+
+Login as the demo editor user
+=============================
+
+We have the login portlet, so let's use that:
+
+    >>> browser.open(portal_url)
+    >>> browser.getControl(name='__ac_name').value = editor
+    >>> browser.getControl(name='__ac_password').value = default_password
+    >>> browser.getControl(name='submit').click()
+
+We check that we get the logged-in message:
+
+    >>> "You are now logged in" in browser.contents
+    True
+
+Switch to textarea for editor 
+=============================
+
+Go to the users dashboard to check their preferences are set OK
+
+   >>> browser.open(portal_url + '/dashboard')
+
+Check we have disabled editors and just use the text box
+
+    >>> browser.getLink('Personal Preferences').click()
+    >>> browser.getControl(name='wysiwyg_editor').value = ['None']
+    >>> browser.getControl(name='fullname').value = 'Demo Editor'
+    >>> browser.getControl(name='email').value = 'nobody@plone.org'
+    >>> browser.getControl(name='form.button.Save').click()
+    >>> "Your personal settings have been saved." in browser.contents
+    True
+    >>> browser.getControl(name='wysiwyg_editor').value
+    ['None']
+
+
+Add a page as an editor
+=======================
+
+Now go to the folder listing page
+
+    >>> folder_url = folder.absolute_url()
+    >>> browser.open(folder_url)
+    >>> 'Contents' in browser.contents
+    True
+
+
+Lets try to create a new document as the editor
+===============================================
+
+    >>> new_title = "Test New Item"
+    >>> new_id = "test-new-item"
+
+Click on the 'Add New ...' > 'Document' link via url to be language safe 
+
+    >>> browser.getLink(url=folder_url + '/createObject?type_name=Document').click()
+    >>> "/portal_factory/Document/document." in browser.contents
+    True
+
+Fill in the form with dummy content for the test page
+
+    >>> browser.getControl(name="title").value = new_title
+    >>> descrip = "A dummy page created by the test handler"
+    >>> browser.getControl(name='description').value = descrip
+    >>> browser.getControl(name='text').value = "<h1>Test new page</h1>\n\n"
+    >>> browser.getControl(name='form_submit').click()
+    >>> "Changes saved." in browser.contents
+    True
+    >>> new_title in browser.contents
+    True
+
+We shouldnt be able to publish as an editor)
+
+    >>> '/content_status_modify?workflow_action=publish' in browser.contents
+    False
+
+So lets just submit this item for publication ... 
+
+    >>> doc_url = folder_url + '/' + new_id
+    >>> submit_url =  doc_url + '/content_status_modify?workflow_action=submit'
+    >>> browser.getLink(url=submit_url).click()
+
+Finally we can check that we shouldnt be spinning out iterations of 
+content that isnt published ...
+
+    >>> checkout_url =  doc_url + '/@@content-checkout'
+    >>> try:
+    ...    checkoutlink = browser.getLink(url=checkout_url)
+    ... except LinkNotFoundError:
+    ...    checkoutlink = None
+   >>> checkoutlink == None
+   True
+
+OK we are done as the editor for the moment
+
+    >>> browser.getLink('Log out').click()
+
+Log in as the manager and publish the editors document
+======================================================
+
+Login as the manager
+
+    >>> browser.getControl(name='__ac_name').value = portal_owner
+    >>> browser.getControl(name='__ac_password').value = default_password
+    >>> browser.getControl(name='submit').click()
+    >>> "You are now logged in" in browser.contents
+    True
+
+Publish the document
+
+    >>> browser.open(doc_url)
+    >>> submit_url =  doc_url + '/content_status_modify?workflow_action=publish'
+    >>> browser.getLink(url=submit_url).click()
+    >>> browser.getLink(url=doc_url + '/content_status_history').click()
+    >>> browser.getControl(name='workflow_action').value
+    ['published']
+    >>> browser.getLink('Log out').click()
+
+Log in as the editor and try to change public content without a review process 
+==============================================================================
+
+Login as the editor
+
+    >>> browser.getControl(name='__ac_name').value = editor
+    >>> browser.getControl(name='__ac_password').value = default_password
+    >>> browser.getControl(name='submit').click()
+    >>> "You are now logged in" in browser.contents
+    True
+
+    >>> browser.open(doc_url)
+    >>> try:
+    ...    editlink = browser.getLink(url=doc_url + '/edit')
+    ... except LinkNotFoundError:
+    ...    editlink = None
+
+Check that the editor cannot edit the published content
+
+    >>> editlink == None
+    True
+
+If this test fails then lets insult the manager
+
+    >>> if editlink:
+    ...    editlink.click()
+    ...    text = "<h1>My manager looks like a duck and walks like a duck</h1>\n"
+    ...    browser.getControl(name='text').value = text
+    ...    browser.getControl(name='form_submit').click()
+
+Check to see if the editor has been stopped from publically 
+insulting his manager with formal workflow ...
+
+    >>> 'My manager looks like a duck' in browser.contents
+    False
+
+Check to see that the editor or owner cannot remove published content
+
+    >>> retract_url =  doc_url + '/content_status_modify?workflow_action=retract'
+    >>> try:
+    ...    retractlink = browser.getLink(url=retract_url)
+    ... except LinkNotFoundError:
+    ...    retractlink = None
+    >>> if retractlink: retractlink.click()
+
+Should not have a retract link ...
+
+    >>> retractlink == None
+    True
+
+Confirm that the content is still published not private
+
+    >>> 'class="state-published navTreeCurrentItem navTreeCurrentNode"' in browser.contents
+    True
+
+Check that they can't delete it either
+
+    >>> doc_url + '/delete_confirmation' not in browser.contents
+    True
+
+Now lets spin out an iteration and change that instead
+======================================================
+
+Check to see that the editor or owner can checkout a version
+
+    >>> checkout_url =  doc_url + '/@@content-checkout'
+    >>> try:
+    ...    checkoutlink = browser.getLink(url=checkout_url)
+    ... except LinkNotFoundError:
+    ...    checkoutlink = None
+
+We should have a checkout link from plone.app.iterate
+
+   >>> checkoutlink != None
+   True
+
+We should be able to check out
+
+    >>> checkoutlink.click()
+    >>> iteration_url = folder_url + '/copy_of_' + new_id
+
+Lets check we can open the iteration copy 
+
+    >>> browser.open(iteration_url + '/edit')
+
+Now lets be a bit less rude about our manager
+
+    >>> text = "<h1>My manager looks like a pony</h1>\n"
+    >>> browser.getControl(name='text').value = text
+    >>> browser.getControl(name='form_submit').click()
+    >>> 'like a pony' in browser.contents
+    True
+
+check that we could delete this if we regret it
+
+    >>> iteration_url + '/delete_confirmation' not in browser.contents
+    True
+
+submit that for publication
+
+    >>> submit_url = iteration_url + '/content_status_modify?workflow_action=submit'   
+    >>> browser.getLink(url=submit_url).click()
+
+It should now be pending
+
+    >>> 'class="state-pending navTreeCurrentItem navTreeCurrentNode"' in browser.contents
+    True
+
+we are now blocked from deleting until we make private again
+and we should NOT have check in rights
+
+    >>> iteration_url + '/delete_confirmation' not in browser.contents
+    True
+    >>> iteration_url + '/@@content-checkin' not in browser.contents
+    True
+
+
+Finally log in as manager and checkin the change
+================================================
+
+    >>> browser.getLink('Log out').click()
+    >>> browser.getControl(name='__ac_name').value = portal_owner
+    >>> browser.getControl(name='__ac_password').value = default_password
+    >>> browser.getControl(name='submit').click()
+
+Lets check it in
+
+    >>> browser.open(iteration_url)
+    >>> browser.getLink(url=iteration_url + '/@@content-checkin').click()
+    >>> browser.getControl(name="checkin_message").value = 'Fair commment'
+    >>> browser.getControl(name="form.button.Checkin").click()
+
+Now reopen the original url and see if the change is there
+
+    >>> browser.open(doc_url)
+    >>> 'like a pony' in browser.contents
+    True
+
+   

ilrt/formalworkflow/tests/test_functional.py

+import unittest
+from Testing import ZopeTestCase as ztc
+from ilrt.formalworkflow.tests import base
+
+
+def test_suite():
+    return unittest.TestSuite([
+
+        ztc.ZopeDocFileSuite(
+            'tests/functional.txt', package='ilrt.formalworkflow',
+            test_class=base.BaseFunctionalTestCase),
+
+        ])
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

ilrt/formalworkflow/version.txt

+0.2
+[egg_info]
+tag_build = 
+tag_date = 0
+tag_svn_revision = 0
+
+from setuptools import setup, find_packages
+import os
+
+version = '0.2'
+
+setup(name='ilrt.formalworkflow',
+      version=version,
+      description="Formal workflow for Plone prevents editing, deletion or reversion of published content from skipping review",
+      long_description=open("README.txt").read() + "\n" +
+                       open(os.path.join("docs", "HISTORY.txt")).read(),
+      classifiers=[
+        "Programming Language :: Python",
+        "Topic :: Software Development :: Libraries :: Python Modules",
+        "Environment :: Web Environment",
+        "Framework :: Plone",
+        "Framework :: Zope2",
+        "Framework :: Zope3",
+        "Intended Audience :: Developers",
+        "Intended Audience :: Other Audience",
+        "License :: OSI Approved :: BSD License",
+        "Operating System :: OS Independent",
+        "Development Status :: 4 - Beta"
+        ],
+      keywords='web zope plone workflow',
+      author='Internet Development, ILRT, University of Bristol',
+      author_email='internet-development@bris.ac.uk',
+      url='https://svn.ilrt.bris.ac.uk/repos/ecu/trunk/src/ilrt.formalworkflow',
+      license='GPL',
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['ilrt'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          'setuptools',
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.