use collective.recipe.sphinxbuilder;

svn path=/plone.app.discussion/trunk/; revision=35274
This commit is contained in:
Timo Stollenwerk 2010-03-18 14:06:04 +00:00
parent 8150617081
commit 6135fcf6d4
35 changed files with 1431 additions and 56 deletions

View File

@ -7,6 +7,7 @@ parts =
test
coverage-test
coverage-report
sphinxbuilder
dump-picked-versions-file = versions.cfg
overwrite-picked-versions-file = True
@ -28,6 +29,7 @@ find-links =
# Add additional eggs here
eggs =
Sphinx
plone.app.discussion
plone.formwidget.captcha
plone.formwidget.recaptcha
@ -45,6 +47,7 @@ auto-checkout =
[versions]
zope.schema = 3.6.0
Sphinx = 0.6.4
[instance]
# For more information on this step and configuration options see:
@ -96,6 +99,10 @@ eggs = z3c.coverage
scripts = coverage=coverage-report
arguments = ('coverage', 'report')
[sphinxbuilder]
recipe = collective.recipe.sphinxbuilder
interpreter = ${buildout:directory}/bin/zopepy
[sources]
plone.formwidget.captcha = svn https://svn.plone.org/svn/plone/plone.formwidget.captcha/trunk
plone.formwidget.recaptcha = svn https://svn.plone.org/svn/plone/plone.formwidget.recaptcha/trunk

View File

@ -3,14 +3,14 @@
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXBUILD = /home/timo/workspace/pad/plone.app.discussion/bin/zopepy /home/timo/workspace/pad/plone.app.discussion/bin/sphinx-build
PAPER =
BUILDDIR = build
BUILDDIR = /home/timo/workspace/pad/plone.app.discussion/docs
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) /home/timo/workspace/pad/plone.app.discussion/docs/source
.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
@ -61,9 +61,9 @@ qthelp:
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ploneappdiscussion.qhcp"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/sphinxbuilder.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ploneappdiscussion.qhc"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/sphinxbuilder.qhc"
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex

Binary file not shown.

Binary file not shown.

View File

@ -1,3 +0,0 @@
# Sphinx inventory version 1
# Project: plone.app.discussion
# Version: 1.0b4

View File

@ -1 +0,0 @@
Search.setIndex({desctypes:{},terms:{index:0,search:0,welcom:0,app:0,indic:0,discuss:0,content:0,tabl:0,modul:0,document:0,plone:0,page:0},titles:["Welcome to plone.app.discussion’s documentation!"],modules:{},descrefs:{},filenames:["index"]})

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
docs/doctrees/index.doctree Normal file

Binary file not shown.

View File

@ -0,0 +1,59 @@
========================
Architectural Principles
========================
This document outlines architectural principles used in the design of
plone.app.discussion.
**Discussion items have a portal_type**
This makes it easier to search for them and manage them using existing
CMF and Plone UI constructs.
**Discussion items are cataloged**
It is be possible to search for discussion items like any other type of
content.
**Discussion items are subject to workflow and permission**
Moderation, anonymous commenting, and auto approve/reject should be
handled using workflow states, automatic and manual transitions, and
permissions.
**Discussion items are light weight objects**
Discussion item objects are as light weight as possible.
Ideally, a discussion item should be as lightweight as a catalog brain.
This may mean that we forego convenience base classes and re-implement
certain interfaces. Comments should not provide the full set of dublin
core metadata, though custom indexers can be used to provide values for
standard catalog indexes.
**Optimise for retrival speed**
HTML filtering and other processing should happen on save, not on render,
to make rendering quick.
**Settings are stored using plone.registry**
Any global setting should be stored in plone.registry records
**Forms are constructed using extensible z3c.form forms**
This allows plugins (such as spam protection algorithms) to provide
additional validation
**Discussion items are stored in a BTree container**
This allows faster lookup and manipulation
**Discussion items are accessed using a dict-like interface**
This makes iteration and manipulation more natural. Even if comments are
not stored threaded, the dict interface should act as if they are, i.e.
calling items() on a comment should return the replies to that comment
(in order).
**Discussion items are retrieved in reverse creation date order**
Discussion items do not need to support explicit ordering. They should
always be retrieved in reverse creation date order (most recent for).
They can be stored with keys so that this is always true.
**Discussion items do not need readable ids**
Ids can be based on the creation date.
**Discussion items send events**
The usual zope.lifecycleevent and zope.container events are fired when
discussion items are added, removed, or modified.

View File

@ -0,0 +1,169 @@
============
Design Notes
============
This document contains design notes for plone.app.discussion.
Storage and traversal
---------------------
For each content item, there is a Conversation object stored in annotations.
This can be traversed to via the ++conversation++ namespace, but also fetched
via an adapter lookup to IConversation.
The conversation stores all comments related to a content object. Each
comment has an integer id (also representable as a string, to act as an OFS
id and allow traversal). Hence, traversing to obj/++conversation++/123 retrieves
the comment with id 123.
Comments ids are assigned in order, so a comment with id N was posted before
a comment with id N + 1. However, it is not guaranteed that ids will be
incremental. Ids must be positive integers - 0 or negative numbers are not
allowed.
Threading information is stored in the conversation: we keep track of the
set of children and the parent if any comment. Top-level comments have a
parent id of 0. This information is managed by the conversation class when
comments are manipulated using a dict-like API.
Note that the __parent__/acquisition parent of an IComment is the
IConversation, and the __parent__/acquisition parent of an IConversation is
the content object.
Events
------
Manipulating the IConversation object should fire the usual IObjectAddedEvent
and IObjectRemovedEvent events. The UI may further fire IObjectCreatedEvent
and IObjectModifiedEvent for comments.
Factories
---------
Comments should always be created via the 'Discussion Item' IFactory utility.
Conversations should always be obtained via the IConversation adapter (even
the ++conversation++ namespace should use this). This makes it possible to
replace conversations and comments transparently.
The Comment class
-----------------
The inheritance tree for DiscussionItem is shown below. Classes we want to
mix in and interface we want to implement in the Comment class are marked
with [x].
[ ] DiscussionItem
[ ] Document
[ ] PortalContent = [ ] IContentish
[ ] DynamicType = [ ] IDynamicType
[ ] CMFCatalogAware = [ ] <no interface>
[ ] SimpleItem = [ ] ISimpleItem
[ ] Item [ ]
[?] Base = [ ] <no interface>
[ ] Resource = [ ] <no interface>
[ ] CopySource = [ ] ICopySource
[ ] Tabs = [ ] <no interface>
[x] Traversable = [ ] ITraversable
[ ] Element = [ ] <no interface>
[x] Owned = [ ] IOwned
[ ] UndoSupport = [ ] IUndoSupport
[ ] Persistent [ ]
[ ] Implicit [ ]
[x] RoleManager = [ ] IRoleManager
[ ] RoleManager = [ ] IPermissionMappingSupport
[ ] DefaultDublinCoreImpl = [ ] IDublinCore
[ ] ICatalogableDublinCore
[ ] IMutableDublinCore
[ ] PropertyManager = [ ] IPropertyManager
Thus, we want:
* Traversable, to get absolute_url() and friends
- this requires a good acquisition chain at all times
* Acquisition.Explicit, to support acquisition
- we do not want implicit acquisition
* Owned, to be able to track ownership
* RoleManager, to support permissions and local roles
We also want to use a number of custom indexers for most of the standard
metadata such as creator, effective date etc.
Finally, we'll need event handlers to perform the actual indexing.
Discussion settings
-------------------
Discussion can be enabled per-type and per-instance, via values in the FTI
(allow_discussion) and on the object. These will remain unchanged. The
IConversation object's 'enabled' property should consult these.
Global settings should be managed using plone.registry. A control panel
can be generated from this as well, using the helper class in
plone.app.registry.
Note that some settings, notably those to do with permissions and workflow,
will need to be wired up as custom form fields with custom data mangers
or similar.
Workflow and permissions
------------------------
Where possible, we should use existing permissions:
* View
* Reply to Item
* Modify Portal Content
* Request Review
In addition, we'll need a 'Moderator' role and a moderation permission,
* Moderate comment
* Bypass moderation
To control whether Anonymous can post comments, we manage the 'Reply to Item'
permission. To control whether moderation is required for various roles, we
could manage the 'Bypass moderation' permission.
These could work in a workflow like this:
* --> [posted] -- {publish} --> [published]--> *
| ^
| |
+----- {auto-publish} -----+
| |
+----- {auto-moderate} ----+
The 'posted' state is the initial state. 'published' is the state where the
comment is visible to non-reviewers.
The 'publish' transition would be protected by the 'Moderate comment'
permission. We could have states and transition for 'rejected', etc, but it
is probably just as good to delete comments that are rejected.
The 'auto-publish' transition would be an automatic transition protected by
the 'Bypass moderation' permission.
The 'auto-moderate' transition would be another automatic transition protected
by an expression (e.g. calling a view) that returns True if the user is on
an auto-moderation 'white-list', e.g. by email address or username.
Forms and UI
------------
The basic commenting display/reply form should be placed in a viewlet.
Ideally, the reply form should be inline, perhaps revealed with JavaScript
if enabled. This allows full contextualisation of replies. The current
solution, with a separate form that shows some context, is brittle and
over-complicated.
If we support quoting of comments in replies, we can load the text to quote
using JavaScript as well.
As a fall-back for non-JavaScript enabled browsers, it is probably OK not to
support quoting and/or viewing of context, e.g. the user is taken to a standalone
'comment reply' form.
All actual forms should be handled using z3c.form and plone.z3cform's
ExtensibleForm support. This makes it possible to plug in additional fields
declaratively, e.g. to include spam protection.

View File

@ -6,11 +6,29 @@
Welcome to plone.app.discussion's documentation!
================================================
.. module:`plone.app.discussion`
Contents:
.. toctree::
:maxdepth: 2
architecture.txt
design.txt
API
---
.. automodule:: plone.app.discussion
.. autoclass:: plone.app.discussion.conversation.Conversation
.. automethod:: plone.app.discussion.conversation.Conversation.enabled
.. include:: ../../CHANGES.txt
Indices and tables
==================

View File

@ -166,18 +166,6 @@ div.admonition p.admonition-title + p {
display: inline;
}
div.admonition p {
margin-bottom: 5px;
}
div.admonition pre {
margin-bottom: 5px;
}
div.admonition ul, div.admonition ol {
margin-bottom: 5px;
}
div.note {
background-color: #eee;
border: 1px solid #ccc;

View File

Before

Width:  |  Height:  |  Size: 392 B

After

Width:  |  Height:  |  Size: 392 B

View File

Before

Width:  |  Height:  |  Size: 199 B

After

Width:  |  Height:  |  Size: 199 B

View File

Before

Width:  |  Height:  |  Size: 199 B

After

Width:  |  Height:  |  Size: 199 B

159
docs/html/architecture.html Normal file
View File

@ -0,0 +1,159 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Architectural Principles &mdash; plone.app.discussion v1.0b4 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '#',
VERSION: '1.0b4',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="plone.app.discussion v1.0b4 documentation" href="index.html" />
<link rel="next" title="Design Notes" href="design.html" />
<link rel="prev" title="Welcome to plone.app.discussions documentation!" href="index.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li class="right" >
<a href="design.html" title="Design Notes"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="index.html" title="Welcome to plone.app.discussions documentation!"
accesskey="P">previous</a> |</li>
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="architectural-principles">
<h1>Architectural Principles<a class="headerlink" href="#architectural-principles" title="Permalink to this headline"></a></h1>
<p>This document outlines architectural principles used in the design of
plone.app.discussion.</p>
<blockquote>
<dl class="docutils">
<dt><strong>Discussion items have a portal_type</strong></dt>
<dd>This makes it easier to search for them and manage them using existing
CMF and Plone UI constructs.</dd>
<dt><strong>Discussion items are cataloged</strong></dt>
<dd>It is be possible to search for discussion items like any other type of
content.</dd>
<dt><strong>Discussion items are subject to workflow and permission</strong></dt>
<dd>Moderation, anonymous commenting, and auto approve/reject should be
handled using workflow states, automatic and manual transitions, and
permissions.</dd>
<dt><strong>Discussion items are light weight objects</strong></dt>
<dd>Discussion item objects are as light weight as possible.
Ideally, a discussion item should be as lightweight as a catalog brain.
This may mean that we forego convenience base classes and re-implement
certain interfaces. Comments should not provide the full set of dublin
core metadata, though custom indexers can be used to provide values for
standard catalog indexes.</dd>
<dt><strong>Optimise for retrival speed</strong></dt>
<dd>HTML filtering and other processing should happen on save, not on render,
to make rendering quick.</dd>
<dt><strong>Settings are stored using plone.registry</strong></dt>
<dd>Any global setting should be stored in plone.registry records</dd>
<dt><strong>Forms are constructed using extensible z3c.form forms</strong></dt>
<dd>This allows plugins (such as spam protection algorithms) to provide
additional validation</dd>
<dt><strong>Discussion items are stored in a BTree container</strong></dt>
<dd>This allows faster lookup and manipulation</dd>
<dt><strong>Discussion items are accessed using a dict-like interface</strong></dt>
<dd>This makes iteration and manipulation more natural. Even if comments are
not stored threaded, the dict interface should act as if they are, i.e.
calling items() on a comment should return the replies to that comment
(in order).</dd>
<dt><strong>Discussion items are retrieved in reverse creation date order</strong></dt>
<dd>Discussion items do not need to support explicit ordering. They should
always be retrieved in reverse creation date order (most recent for).
They can be stored with keys so that this is always true.</dd>
<dt><strong>Discussion items do not need readable ids</strong></dt>
<dd>Ids can be based on the creation date.</dd>
<dt><strong>Discussion items send events</strong></dt>
<dd>The usual zope.lifecycleevent and zope.container events are fired when
discussion items are added, removed, or modified.</dd>
</dl>
</blockquote>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h4>Previous topic</h4>
<p class="topless"><a href="index.html"
title="previous chapter">Welcome to plone.app.discussion&#8217;s documentation!</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="design.html"
title="next chapter">Design Notes</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/architecture.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" size="18" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
>modules</a> |</li>
<li class="right" >
<a href="design.html" title="Design Notes"
>next</a> |</li>
<li class="right" >
<a href="index.html" title="Welcome to plone.app.discussions documentation!"
>previous</a> |</li>
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2010, Timo Stollenwerk.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.4.
</div>
</body>
</html>

303
docs/html/design.html Normal file
View File

@ -0,0 +1,303 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Design Notes &mdash; plone.app.discussion v1.0b4 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '#',
VERSION: '1.0b4',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="plone.app.discussion v1.0b4 documentation" href="index.html" />
<link rel="prev" title="Architectural Principles" href="architecture.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li class="right" >
<a href="architecture.html" title="Architectural Principles"
accesskey="P">previous</a> |</li>
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="design-notes">
<h1>Design Notes<a class="headerlink" href="#design-notes" title="Permalink to this headline"></a></h1>
<p>This document contains design notes for plone.app.discussion.</p>
<div class="section" id="storage-and-traversal">
<h2>Storage and traversal<a class="headerlink" href="#storage-and-traversal" title="Permalink to this headline"></a></h2>
<p>For each content item, there is a Conversation object stored in annotations.
This can be traversed to via the ++conversation++ namespace, but also fetched
via an adapter lookup to IConversation.</p>
<p>The conversation stores all comments related to a content object. Each
comment has an integer id (also representable as a string, to act as an OFS
id and allow traversal). Hence, traversing to obj/++conversation++/123 retrieves
the comment with id 123.</p>
<p>Comments ids are assigned in order, so a comment with id N was posted before
a comment with id N + 1. However, it is not guaranteed that ids will be
incremental. Ids must be positive integers - 0 or negative numbers are not
allowed.</p>
<p>Threading information is stored in the conversation: we keep track of the
set of children and the parent if any comment. Top-level comments have a
parent id of 0. This information is managed by the conversation class when
comments are manipulated using a dict-like API.</p>
<p>Note that the __parent__/acquisition parent of an IComment is the
IConversation, and the __parent__/acquisition parent of an IConversation is
the content object.</p>
</div>
<div class="section" id="events">
<h2>Events<a class="headerlink" href="#events" title="Permalink to this headline"></a></h2>
<p>Manipulating the IConversation object should fire the usual IObjectAddedEvent
and IObjectRemovedEvent events. The UI may further fire IObjectCreatedEvent
and IObjectModifiedEvent for comments.</p>
</div>
<div class="section" id="factories">
<h2>Factories<a class="headerlink" href="#factories" title="Permalink to this headline"></a></h2>
<p>Comments should always be created via the &#8216;Discussion Item&#8217; IFactory utility.
Conversations should always be obtained via the IConversation adapter (even
the ++conversation++ namespace should use this). This makes it possible to
replace conversations and comments transparently.</p>
</div>
<div class="section" id="the-comment-class">
<h2>The Comment class<a class="headerlink" href="#the-comment-class" title="Permalink to this headline"></a></h2>
<p>The inheritance tree for DiscussionItem is shown below. Classes we want to
mix in and interface we want to implement in the Comment class are marked
with [x].</p>
<blockquote>
<dl class="docutils">
<dt>[ ] DiscussionItem</dt>
<dd><dl class="first last docutils">
<dt>[ ] Document</dt>
<dd><dl class="first last docutils">
<dt>[ ] PortalContent = [ ] IContentish</dt>
<dd><p class="first">[ ] DynamicType = [ ] IDynamicType
[ ] CMFCatalogAware = [ ] &lt;no interface&gt;
[ ] SimpleItem = [ ] ISimpleItem</p>
<blockquote class="last">
<dl class="docutils">
<dt>[ ] Item [ ]</dt>
<dd>[?] Base = [ ] &lt;no interface&gt;
[ ] Resource = [ ] &lt;no interface&gt;
[ ] CopySource = [ ] ICopySource
[ ] Tabs = [ ] &lt;no interface&gt;
[x] Traversable = [ ] ITraversable
[ ] Element = [ ] &lt;no interface&gt;
[x] Owned = [ ] IOwned
[ ] UndoSupport = [ ] IUndoSupport</dd>
</dl>
<p>[ ] Persistent [ ]
[ ] Implicit [ ]
[x] RoleManager = [ ] IRoleManager</p>
<blockquote>
[ ] RoleManager = [ ] IPermissionMappingSupport</blockquote>
</blockquote>
</dd>
<dt>[ ] DefaultDublinCoreImpl = [ ] IDublinCore</dt>
<dd><blockquote class="first">
[ ] ICatalogableDublinCore
[ ] IMutableDublinCore</blockquote>
<p class="last">[ ] PropertyManager = [ ] IPropertyManager</p>
</dd>
</dl>
</dd>
</dl>
</dd>
</dl>
</blockquote>
<p>Thus, we want:</p>
<blockquote>
<ul>
<li><dl class="first docutils">
<dt>Traversable, to get absolute_url() and friends</dt>
<dd><ul class="first last simple">
<li>this requires a good acquisition chain at all times</li>
</ul>
</dd>
</dl>
</li>
<li><dl class="first docutils">
<dt>Acquisition.Explicit, to support acquisition</dt>
<dd><ul class="first last simple">
<li>we do not want implicit acquisition</li>
</ul>
</dd>
</dl>
</li>
<li><p class="first">Owned, to be able to track ownership</p>
</li>
<li><p class="first">RoleManager, to support permissions and local roles</p>
</li>
</ul>
</blockquote>
<p>We also want to use a number of custom indexers for most of the standard
metadata such as creator, effective date etc.</p>
<p>Finally, we&#8217;ll need event handlers to perform the actual indexing.</p>
</div>
<div class="section" id="discussion-settings">
<h2>Discussion settings<a class="headerlink" href="#discussion-settings" title="Permalink to this headline"></a></h2>
<p>Discussion can be enabled per-type and per-instance, via values in the FTI
(allow_discussion) and on the object. These will remain unchanged. The
IConversation object&#8217;s &#8216;enabled&#8217; property should consult these.</p>
<p>Global settings should be managed using plone.registry. A control panel
can be generated from this as well, using the helper class in
plone.app.registry.</p>
<p>Note that some settings, notably those to do with permissions and workflow,
will need to be wired up as custom form fields with custom data mangers
or similar.</p>
</div>
<div class="section" id="workflow-and-permissions">
<h2>Workflow and permissions<a class="headerlink" href="#workflow-and-permissions" title="Permalink to this headline"></a></h2>
<p>Where possible, we should use existing permissions:</p>
<blockquote>
<ul class="simple">
<li>View</li>
<li>Reply to Item</li>
<li>Modify Portal Content</li>
<li>Request Review</li>
</ul>
</blockquote>
<p>In addition, we&#8217;ll need a &#8216;Moderator&#8217; role and a moderation permission,</p>
<blockquote>
<ul class="simple">
<li>Moderate comment</li>
<li>Bypass moderation</li>
</ul>
</blockquote>
<p>To control whether Anonymous can post comments, we manage the &#8216;Reply to Item&#8217;
permission. To control whether moderation is required for various roles, we
could manage the &#8216;Bypass moderation&#8217; permission.</p>
<p>These could work in a workflow like this:</p>
<blockquote>
<ul>
<li><dl class="first docutils">
<dt>&#8211;&gt; [posted] &#8211; {publish} &#8211;&gt; [published]&#8211;&gt; *</dt>
<dd><div class="first line-block">
<div class="line">^</div>
<div class="line"><a href="#id1"><span class="problematic" id="id2">|</span></a></div>
</div>
<p class="last">+&#8212;&#8211; {auto-publish} &#8212;&#8211;+
| |
+&#8212;&#8211; {auto-moderate} &#8212;-+</p>
</dd>
</dl>
</li>
</ul>
</blockquote>
<p>The &#8216;posted&#8217; state is the initial state. &#8216;published&#8217; is the state where the
comment is visible to non-reviewers.</p>
<p>The &#8216;publish&#8217; transition would be protected by the &#8216;Moderate comment&#8217;
permission. We could have states and transition for &#8216;rejected&#8217;, etc, but it
is probably just as good to delete comments that are rejected.</p>
<p>The &#8216;auto-publish&#8217; transition would be an automatic transition protected by
the &#8216;Bypass moderation&#8217; permission.</p>
<p>The &#8216;auto-moderate&#8217; transition would be another automatic transition protected
by an expression (e.g. calling a view) that returns True if the user is on
an auto-moderation &#8216;white-list&#8217;, e.g. by email address or username.</p>
</div>
<div class="section" id="forms-and-ui">
<h2>Forms and UI<a class="headerlink" href="#forms-and-ui" title="Permalink to this headline"></a></h2>
<p>The basic commenting display/reply form should be placed in a viewlet.</p>
<p>Ideally, the reply form should be inline, perhaps revealed with JavaScript
if enabled. This allows full contextualisation of replies. The current
solution, with a separate form that shows some context, is brittle and
over-complicated.</p>
<p>If we support quoting of comments in replies, we can load the text to quote
using JavaScript as well.</p>
<p>As a fall-back for non-JavaScript enabled browsers, it is probably OK not to
support quoting and/or viewing of context, e.g. the user is taken to a standalone
&#8216;comment reply&#8217; form.</p>
<p>All actual forms should be handled using z3c.form and plone.z3cform&#8217;s
ExtensibleForm support. This makes it possible to plug in additional fields
declaratively, e.g. to include spam protection.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference external" href="#">Design Notes</a><ul>
<li><a class="reference external" href="#storage-and-traversal">Storage and traversal</a></li>
<li><a class="reference external" href="#events">Events</a></li>
<li><a class="reference external" href="#factories">Factories</a></li>
<li><a class="reference external" href="#the-comment-class">The Comment class</a></li>
<li><a class="reference external" href="#discussion-settings">Discussion settings</a></li>
<li><a class="reference external" href="#workflow-and-permissions">Workflow and permissions</a></li>
<li><a class="reference external" href="#forms-and-ui">Forms and UI</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="architecture.html"
title="previous chapter">Architectural Principles</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/design.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" size="18" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
>modules</a> |</li>
<li class="right" >
<a href="architecture.html" title="Architectural Principles"
>previous</a> |</li>
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2010, Timo Stollenwerk.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.4.
</div>
</body>
</html>

View File

@ -28,6 +28,9 @@
<li class="right" style="margin-right: 10px">
<a href="#" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> &raquo;</li>
</ul>
</div>
@ -40,11 +43,32 @@
<h1 id="index">Index</h1>
<a href="#C"><strong>C</strong></a> | <a href="#E"><strong>E</strong></a> | <a href="#P"><strong>P</strong></a>
<hr />
<h2 id="C">C</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="index.html#plone.app.discussion.conversation.Conversation">Conversation (class in plone.app.discussion.conversation)</a></dt></dl></td><td width="33%" valign="top"><dl>
</dl></td></tr></table>
<h2 id="E">E</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="index.html#plone.app.discussion.conversation.Conversation.enabled">enabled() (plone.app.discussion.conversation.Conversation method)</a></dt></dl></td><td width="33%" valign="top"><dl>
</dl></td></tr></table>
<h2 id="P">P</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="index.html#module-plone.app.discussion">plone.app.discussion (module)</a></dt></dl></td><td width="33%" valign="top"><dl>
</dl></td></tr></table>
</div>
@ -78,12 +102,15 @@
<li class="right" style="margin-right: 10px">
<a href="#" title="General Index"
>index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
>modules</a> |</li>
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2010, Timo Stollenwerk.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.5.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.4.
</div>
</body>
</html>

278
docs/html/index.html Normal file
View File

@ -0,0 +1,278 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Welcome to plone.app.discussions documentation! &mdash; plone.app.discussion v1.0b4 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '#',
VERSION: '1.0b4',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="plone.app.discussion v1.0b4 documentation" href="#" />
<link rel="next" title="Architectural Principles" href="architecture.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li class="right" >
<a href="architecture.html" title="Architectural Principles"
accesskey="N">next</a> |</li>
<li><a href="#">plone.app.discussion v1.0b4 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="welcome-to-plone-app-discussion-s-documentation">
<h1>Welcome to plone.app.discussion&#8217;s documentation!<a class="headerlink" href="#welcome-to-plone-app-discussion-s-documentation" title="Permalink to this headline"></a></h1>
<p>Contents:</p>
<ul>
<li class="toctree-l1"><a class="reference external" href="architecture.html">Architectural Principles</a></li>
<li class="toctree-l1"><a class="reference external" href="design.html">Design Notes</a><ul>
<li class="toctree-l2"><a class="reference external" href="design.html#storage-and-traversal">Storage and traversal</a></li>
<li class="toctree-l2"><a class="reference external" href="design.html#events">Events</a></li>
<li class="toctree-l2"><a class="reference external" href="design.html#factories">Factories</a></li>
<li class="toctree-l2"><a class="reference external" href="design.html#the-comment-class">The Comment class</a></li>
<li class="toctree-l2"><a class="reference external" href="design.html#discussion-settings">Discussion settings</a></li>
<li class="toctree-l2"><a class="reference external" href="design.html#workflow-and-permissions">Workflow and permissions</a></li>
<li class="toctree-l2"><a class="reference external" href="design.html#forms-and-ui">Forms and UI</a></li>
</ul>
</li>
</ul>
<div class="section" id="module-plone.app.discussion">
<h2>API<a class="headerlink" href="#module-plone.app.discussion" title="Permalink to this headline"></a></h2>
<dl class="class">
<dt id="plone.app.discussion.conversation.Conversation">
<em class="property">class </em><tt class="descclassname">plone.app.discussion.conversation.</tt><tt class="descname">Conversation</tt><big>(</big><em>id='++conversation++default'</em><big>)</big><a class="headerlink" href="#plone.app.discussion.conversation.Conversation" title="Permalink to this definition"></a></dt>
<dd><p>A conversation is a container for all comments on a content object.</p>
<p>It manages internal data structures for comment threading and efficient
comment lookup.</p>
<dl class="method">
<dt id="plone.app.discussion.conversation.Conversation.enabled">
<tt class="descname">enabled</tt><big>(</big><big>)</big><a class="headerlink" href="#plone.app.discussion.conversation.Conversation.enabled" title="Permalink to this definition"></a></dt>
<dd>hi world</dd></dl>
</dd></dl>
</div>
</div>
<div class="section" id="changelog">
<h1>Changelog<a class="headerlink" href="#changelog" title="Permalink to this headline"></a></h1>
<div class="section" id="b4-unreleased">
<h2>1.0b4 (unreleased)<a class="headerlink" href="#b4-unreleased" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li>Fix #662654: As an administrator, I can configure a Collection to show recent comments.
Comment.Type() now correctly returns the FTI title (&#8216;Comment&#8217;)
[chaoflow]</li>
<li>German translation updated.
[juh]</li>
<li>Fix #2419342: Fix untranslated published/deleted status messages.
[timo]</li>
<li>Remove fixed width of the actions column of the moderation view. The
translated button titles can differ in size from the English titles.
[timo]</li>
<li>Fix #2494228: Remove comments as well when a content object is deleted.
[timo]</li>
<li>Fix unicode error when non-ASCII characters are typed into the name field of a
comment by anonymous users.
[regebro]</li>
<li>New feature: As a moderator, I am notified when new comments require my
attention.
[timo]</li>
<li>Make p.a.d. work with the recent version of plone.z3cform (0.5.10)
[timo]</li>
<li>Make p.a.d. styles less generic. This fixes #10253.
[timo]</li>
<li>Added greek translation.
[ggozad]</li>
</ul>
</div>
<div class="section" id="b3-2010-01-28">
<h2>1.0b3 (2010-01-28)<a class="headerlink" href="#b3-2010-01-28" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li>Added an i18n directory for messages in the plone domain and updated scripts
to rebuild and sync it.
[hannosch]</li>
<li>Added an optional conversationCanonicalAdapterFactory showing how to share
comments across all translations with LinguaPlone, by storing and retrieving
the conversation from the canonical object.
[hannosch]</li>
<li>Play by the Plone 3.3+ rules and use the INavigationRoot as a base for the
moderation view.
[hannosch]</li>
<li>Added a commentTitle CSS class to the comment titles.
[hannosch]</li>
<li>Update message ids to match their real text.
[hannosch]</li>
<li>Set CSS classes for the comment form in the updateActions method.
[timo]</li>
<li>Respect the allow_comments field on an object and avoid calculations if no
comments should be shown.
[hannosch]</li>
<li>Automatically load the ZCML files of the captcha widgets if they are
installed.
[hannosch]</li>
<li>Fixed i18n domain in GenericSetup profiles to be <tt class="docutils literal"><span class="pre">plone</span></tt>. Other values
aren&#8217;t supported for GS profiles.
[hannosch]</li>
<li>Provide our own copy of the default one state workflow. Not all Plone sites
have this workflow installed.
[hannosch]</li>
<li>Register the event subscribers for the correct interfaces in Plone 3.
[hannosch]</li>
<li>Factored out subscriber declarations into its own ZCML file.
[hannosch]</li>
<li>Bugfix for #2281226: Moderation View: Comments disappear when hitting the
&#8216;Apply&#8217; button without choosing a bulk action.
[timo]</li>
<li>Allow to show the full text of a comment in the moderation view.
[timo]</li>
<li>German translation added.
[timo]</li>
<li>Italian translation added.
[keul]</li>
</ul>
</div>
<div class="section" id="b2-2010-01-22">
<h2>1.0b2 (2010-01-22)<a class="headerlink" href="#b2-2010-01-22" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li>Bugfix for #2010181: The name of a commenter who commented while not logged in
should not appear as a link.</li>
<li>Bugfix for #2010078: Comments that await moderation are visually distinguished
from published comments.</li>
<li>Bugfix for #2010085: Use object_provides instead of portal_type to query the
catalog for comment.</li>
<li>Bugfix for #2010071: p.a.d. works with plone.z3cform 0.5.7 and
plone.app.z3cform 0.4.9 now.</li>
<li>Bugfix for #1513398: Show &#8220;anonymous&#8221; when name field is empty in comment
form.</li>
<li>Migration view: Dry run option added, abort transaction when something goes
wrong during migration, be more verbose about errors.</li>
</ul>
</div>
<div class="section" id="b1-2009-12-08">
<h2>1.0b1 (2009-12-08)<a class="headerlink" href="#b1-2009-12-08" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li>Fix redirect after a adding a comment</li>
<li>Replace yes/no widgets with check boxes in the discussion control panel</li>
<li>Make comments viewlet show up in Plone 4</li>
<li>Apply Plone 4 styles to comment form</li>
<li>Simplify moderation view by removing the filters</li>
</ul>
</div>
<div class="section" id="a2-2009-10-18">
<h2>1.0a2 (2009-10-18)<a class="headerlink" href="#a2-2009-10-18" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li>Plone 4 / Zope 2.12 support</li>
<li>Comment migration script added</li>
<li>Pluggable plone.z3cform comment forms</li>
<li>Captcha and ReCaptcha support added</li>
</ul>
</div>
<div class="section" id="a1-2009-06-07">
<h2>1.0a1 (2009-06-07)<a class="headerlink" href="#a1-2009-06-07" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li>Basic commenting functionality and batch moderation.</li>
</ul>
</div>
</div>
<div class="section" id="indices-and-tables">
<h1>Indices and tables<a class="headerlink" href="#indices-and-tables" title="Permalink to this headline"></a></h1>
<ul class="simple">
<li><a class="reference external" href="genindex.html"><em>Index</em></a></li>
<li><a class="reference external" href="modindex.html"><em>Module Index</em></a></li>
<li><a class="reference external" href="search.html"><em>Search Page</em></a></li>
</ul>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="#">Table Of Contents</a></h3>
<ul>
<li><a class="reference external" href="#">Welcome to plone.app.discussion&#8217;s documentation!</a><ul>
<li><a class="reference external" href="#module-plone.app.discussion">API</a></li>
</ul>
</li>
<li><a class="reference external" href="#changelog">Changelog</a><ul>
<li><a class="reference external" href="#b4-unreleased">1.0b4 (unreleased)</a></li>
<li><a class="reference external" href="#b3-2010-01-28">1.0b3 (2010-01-28)</a></li>
<li><a class="reference external" href="#b2-2010-01-22">1.0b2 (2010-01-22)</a></li>
<li><a class="reference external" href="#b1-2009-12-08">1.0b1 (2009-12-08)</a></li>
<li><a class="reference external" href="#a2-2009-10-18">1.0a2 (2009-10-18)</a></li>
<li><a class="reference external" href="#a1-2009-06-07">1.0a1 (2009-06-07)</a></li>
</ul>
</li>
<li><a class="reference external" href="#indices-and-tables">Indices and tables</a></li>
</ul>
<h4>Next topic</h4>
<p class="topless"><a href="architecture.html"
title="next chapter">Architectural Principles</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/index.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" size="18" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
>modules</a> |</li>
<li class="right" >
<a href="architecture.html" title="Architectural Principles"
>next</a> |</li>
<li><a href="#">plone.app.discussion v1.0b4 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2010, Timo Stollenwerk.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.4.
</div>
</body>
</html>

View File

@ -5,7 +5,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Welcome to plone.app.discussions documentation! &mdash; plone.app.discussion v1.0b4 documentation</title>
<title>Global Module Index &mdash; plone.app.discussion v1.0b4 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
@ -19,7 +19,10 @@
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="plone.app.discussion v1.0b4 documentation" href="#" />
<link rel="top" title="plone.app.discussion v1.0b4 documentation" href="index.html" />
</head>
<body>
<div class="related">
@ -28,7 +31,10 @@
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li><a href="#">plone.app.discussion v1.0b4 documentation</a> &raquo;</li>
<li class="right" >
<a href="#" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> &raquo;</li>
</ul>
</div>
@ -37,20 +43,23 @@
<div class="bodywrapper">
<div class="body">
<div class="section" id="welcome-to-plone-app-discussion-s-documentation">
<h1>Welcome to plone.app.discussion&#8217;s documentation!<a class="headerlink" href="#welcome-to-plone-app-discussion-s-documentation" title="Permalink to this headline"></a></h1>
<p>Contents:</p>
<ul class="simple">
</ul>
</div>
<div class="section" id="indices-and-tables">
<h1>Indices and tables<a class="headerlink" href="#indices-and-tables" title="Permalink to this headline"></a></h1>
<ul class="simple">
<li><a class="reference external" href="genindex.html"><em>Index</em></a></li>
<li><a class="reference external" href="modindex.html"><em>Module Index</em></a></li>
<li><a class="reference external" href="search.html"><em>Search Page</em></a></li>
</ul>
</div>
<h1 id="global-module-index">Global Module Index</h1>
<a href="#cap-P"><strong>P</strong></a>
<hr/>
<table width="100%" class="indextable" cellspacing="0" cellpadding="2"><tr class="pcap"><td></td><td>&nbsp;</td><td></td></tr>
<tr class="cap"><td></td><td><a name="cap-P"><strong>P</strong></a></td><td></td></tr><tr>
<td><img src="_static/minus.png" id="toggle-1"
class="toggler" style="display: none" alt="-" /></td>
<td>
<tt class="xref">plone</tt></td><td>
<em></em></td></tr><tr class="cg-1">
<td></td>
<td>&nbsp;&nbsp;&nbsp;
<a href="index.html#module-plone.app.discussion"><tt class="xref">plone.app.discussion</tt></a></td><td>
<em></em></td></tr>
</table>
</div>
@ -58,19 +67,6 @@
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="#">Table Of Contents</a></h3>
<ul>
<li><a class="reference external" href="#">Welcome to plone.app.discussion&#8217;s documentation!</a><ul>
</ul>
</li>
<li><a class="reference external" href="#indices-and-tables">Indices and tables</a></li>
</ul>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/index.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
@ -94,12 +90,15 @@
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li><a href="#">plone.app.discussion v1.0b4 documentation</a> &raquo;</li>
<li class="right" >
<a href="#" title="Global Module Index"
>modules</a> |</li>
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2010, Timo Stollenwerk.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.5.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.4.
</div>
</body>
</html>

6
docs/html/objects.inv Normal file
View File

@ -0,0 +1,6 @@
# Sphinx inventory version 1
# Project: plone.app.discussion
# Version: 1.0b4
plone.app.discussion mod index.html
plone.app.discussion.conversation.Conversation class index.html
plone.app.discussion.conversation.Conversation.enabled method index.html

View File

@ -29,6 +29,9 @@
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> &raquo;</li>
</ul>
</div>
@ -77,13 +80,16 @@
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
>modules</a> |</li>
<li><a href="index.html">plone.app.discussion v1.0b4 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2010, Timo Stollenwerk.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.5.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.4.
</div>
<script type="text/javascript" src="searchindex.js"></script>

1
docs/html/searchindex.js Normal file

File diff suppressed because one or more lines are too long

113
docs/make.bat Normal file
View File

@ -0,0 +1,113 @@
@ECHO OFF
REM Command file for Sphinx documentation
set SPHINXBUILD=sphinx-build
set BUILDDIR=/home/timo/workspace/pad/plone.app.discussion/docs
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% /home/timo/workspace/pad/plone.app.discussion/docs/source
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\sphinxbuilder.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\sphinxbuilder.ghc
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end

View File

@ -0,0 +1,59 @@
========================
Architectural Principles
========================
This document outlines architectural principles used in the design of
plone.app.discussion.
**Discussion items have a portal_type**
This makes it easier to search for them and manage them using existing
CMF and Plone UI constructs.
**Discussion items are cataloged**
It is be possible to search for discussion items like any other type of
content.
**Discussion items are subject to workflow and permission**
Moderation, anonymous commenting, and auto approve/reject should be
handled using workflow states, automatic and manual transitions, and
permissions.
**Discussion items are light weight objects**
Discussion item objects are as light weight as possible.
Ideally, a discussion item should be as lightweight as a catalog brain.
This may mean that we forego convenience base classes and re-implement
certain interfaces. Comments should not provide the full set of dublin
core metadata, though custom indexers can be used to provide values for
standard catalog indexes.
**Optimise for retrival speed**
HTML filtering and other processing should happen on save, not on render,
to make rendering quick.
**Settings are stored using plone.registry**
Any global setting should be stored in plone.registry records
**Forms are constructed using extensible z3c.form forms**
This allows plugins (such as spam protection algorithms) to provide
additional validation
**Discussion items are stored in a BTree container**
This allows faster lookup and manipulation
**Discussion items are accessed using a dict-like interface**
This makes iteration and manipulation more natural. Even if comments are
not stored threaded, the dict interface should act as if they are, i.e.
calling items() on a comment should return the replies to that comment
(in order).
**Discussion items are retrieved in reverse creation date order**
Discussion items do not need to support explicit ordering. They should
always be retrieved in reverse creation date order (most recent for).
They can be stored with keys so that this is always true.
**Discussion items do not need readable ids**
Ids can be based on the creation date.
**Discussion items send events**
The usual zope.lifecycleevent and zope.container events are fired when
discussion items are added, removed, or modified.

169
docs/source/design.txt Normal file
View File

@ -0,0 +1,169 @@
============
Design Notes
============
This document contains design notes for plone.app.discussion.
Storage and traversal
---------------------
For each content item, there is a Conversation object stored in annotations.
This can be traversed to via the ++conversation++ namespace, but also fetched
via an adapter lookup to IConversation.
The conversation stores all comments related to a content object. Each
comment has an integer id (also representable as a string, to act as an OFS
id and allow traversal). Hence, traversing to obj/++conversation++/123 retrieves
the comment with id 123.
Comments ids are assigned in order, so a comment with id N was posted before
a comment with id N + 1. However, it is not guaranteed that ids will be
incremental. Ids must be positive integers - 0 or negative numbers are not
allowed.
Threading information is stored in the conversation: we keep track of the
set of children and the parent if any comment. Top-level comments have a
parent id of 0. This information is managed by the conversation class when
comments are manipulated using a dict-like API.
Note that the __parent__/acquisition parent of an IComment is the
IConversation, and the __parent__/acquisition parent of an IConversation is
the content object.
Events
------
Manipulating the IConversation object should fire the usual IObjectAddedEvent
and IObjectRemovedEvent events. The UI may further fire IObjectCreatedEvent
and IObjectModifiedEvent for comments.
Factories
---------
Comments should always be created via the 'Discussion Item' IFactory utility.
Conversations should always be obtained via the IConversation adapter (even
the ++conversation++ namespace should use this). This makes it possible to
replace conversations and comments transparently.
The Comment class
-----------------
The inheritance tree for DiscussionItem is shown below. Classes we want to
mix in and interface we want to implement in the Comment class are marked
with [x].
[ ] DiscussionItem
[ ] Document
[ ] PortalContent = [ ] IContentish
[ ] DynamicType = [ ] IDynamicType
[ ] CMFCatalogAware = [ ] <no interface>
[ ] SimpleItem = [ ] ISimpleItem
[ ] Item [ ]
[?] Base = [ ] <no interface>
[ ] Resource = [ ] <no interface>
[ ] CopySource = [ ] ICopySource
[ ] Tabs = [ ] <no interface>
[x] Traversable = [ ] ITraversable
[ ] Element = [ ] <no interface>
[x] Owned = [ ] IOwned
[ ] UndoSupport = [ ] IUndoSupport
[ ] Persistent [ ]
[ ] Implicit [ ]
[x] RoleManager = [ ] IRoleManager
[ ] RoleManager = [ ] IPermissionMappingSupport
[ ] DefaultDublinCoreImpl = [ ] IDublinCore
[ ] ICatalogableDublinCore
[ ] IMutableDublinCore
[ ] PropertyManager = [ ] IPropertyManager
Thus, we want:
* Traversable, to get absolute_url() and friends
- this requires a good acquisition chain at all times
* Acquisition.Explicit, to support acquisition
- we do not want implicit acquisition
* Owned, to be able to track ownership
* RoleManager, to support permissions and local roles
We also want to use a number of custom indexers for most of the standard
metadata such as creator, effective date etc.
Finally, we'll need event handlers to perform the actual indexing.
Discussion settings
-------------------
Discussion can be enabled per-type and per-instance, via values in the FTI
(allow_discussion) and on the object. These will remain unchanged. The
IConversation object's 'enabled' property should consult these.
Global settings should be managed using plone.registry. A control panel
can be generated from this as well, using the helper class in
plone.app.registry.
Note that some settings, notably those to do with permissions and workflow,
will need to be wired up as custom form fields with custom data mangers
or similar.
Workflow and permissions
------------------------
Where possible, we should use existing permissions:
* View
* Reply to Item
* Modify Portal Content
* Request Review
In addition, we'll need a 'Moderator' role and a moderation permission,
* Moderate comment
* Bypass moderation
To control whether Anonymous can post comments, we manage the 'Reply to Item'
permission. To control whether moderation is required for various roles, we
could manage the 'Bypass moderation' permission.
These could work in a workflow like this:
* --> [posted] -- {publish} --> [published]--> *
| ^
| |
+----- {auto-publish} -----+
| |
+----- {auto-moderate} ----+
The 'posted' state is the initial state. 'published' is the state where the
comment is visible to non-reviewers.
The 'publish' transition would be protected by the 'Moderate comment'
permission. We could have states and transition for 'rejected', etc, but it
is probably just as good to delete comments that are rejected.
The 'auto-publish' transition would be an automatic transition protected by
the 'Bypass moderation' permission.
The 'auto-moderate' transition would be another automatic transition protected
by an expression (e.g. calling a view) that returns True if the user is on
an auto-moderation 'white-list', e.g. by email address or username.
Forms and UI
------------
The basic commenting display/reply form should be placed in a viewlet.
Ideally, the reply form should be inline, perhaps revealed with JavaScript
if enabled. This allows full contextualisation of replies. The current
solution, with a separate form that shows some context, is brittle and
over-complicated.
If we support quoting of comments in replies, we can load the text to quote
using JavaScript as well.
As a fall-back for non-JavaScript enabled browsers, it is probably OK not to
support quoting and/or viewing of context, e.g. the user is taken to a standalone
'comment reply' form.
All actual forms should be handled using z3c.form and plone.z3cform's
ExtensibleForm support. This makes it possible to plug in additional fields
declaratively, e.g. to include spam protection.

View File

@ -6,11 +6,29 @@
Welcome to plone.app.discussion's documentation!
================================================
.. module:`plone.app.discussion`
Contents:
.. toctree::
:maxdepth: 2
architecture.txt
design.txt
API
---
.. automodule:: plone.app.discussion
.. autoclass:: plone.app.discussion.conversation.Conversation
.. automethod:: plone.app.discussion.conversation.Conversation.enabled
.. include:: ../../CHANGES.txt
Indices and tables
==================