Replace the old NOTES.txt and PRINCIPLES.txt with the Sphinx versions. Fix Captcha title.

svn path=/plone.app.discussion/trunk/; revision=36998
This commit is contained in:
Timo Stollenwerk 2010-06-04 11:22:16 +00:00
parent adbe6c7db7
commit af1a8bfacd
6 changed files with 82 additions and 308 deletions

View File

@ -1,59 +1 @@
======================== .. include:: ../../plone/app/discussion/architecture.txt
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 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. It also allows integrators to write add-ons that add
new fields to the comment form.
**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

@ -1,167 +1 @@
============ .. include:: ../../plone/app/discussion/design.txt
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 is placed in a viewlet.
The reply form is dynamically created right under the comment when the user hits
the reply button. To do so, we copy the standard comment form with a jQuery
function. This function sets the form's hidden in_reply_to field to the id of
the comment the user wants to reply to. This also makes is possible to use
z3c.form validation for the reply forms, because we can uniquely identify the
a reply form request and return the reply form with validation errors.
Since we rely on JavaScript for the reply form creation, the reply button is
removed for nonJavaScript enabled browsers.
The comment form uses 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

@ -1,59 +0,0 @@
=============================================
plone.app.discussion 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 should 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
All discussion item objects should be 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 should be
fired when discussion items are added, removed, or modified.

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 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. It also allows integrators to write add-ons that add
new fields to the comment form.
**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

@ -1,5 +1,5 @@
Captcha Design Notes Captcha Plugin Architecture
==================== ===========================
This document contains design notes for the plone.app.discussion Captcha plugin This document contains design notes for the plone.app.discussion Captcha plugin
architecture. architecture.

View File

@ -1,6 +1,6 @@
================================= ============
plone.app.discussion design notes Design Notes
================================= ============
This document contains design notes for plone.app.discussion. This document contains design notes for plone.app.discussion.
@ -8,12 +8,12 @@ Storage and traversal
--------------------- ---------------------
For each content item, there is a Conversation object stored in annotations. For each content item, there is a Conversation object stored in annotations.
This can be traversed to via the ++comments++ namespace, but also fetched This can be traversed to via the ++conversation++ namespace, but also fetched
via an adapter lookup to IConversation. via an adapter lookup to IConversation.
The conversation stores all comments related to a content object. Each 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 comment has an integer id (also representable as a string, to act as an OFS
id and allow traversal). Hence, traversing to obj/++comments++/123 retrieves id and allow traversal). Hence, traversing to obj/++conversation++/123 retrieves
the comment with id 123. the comment with id 123.
Comments ids are assigned in order, so a comment with id N was posted before Comments ids are assigned in order, so a comment with id N was posted before
@ -42,8 +42,8 @@ Factories
Comments should always be created via the 'Discussion Item' IFactory utility. Comments should always be created via the 'Discussion Item' IFactory utility.
Conversations should always be obtained via the IConversation adapter (even Conversations should always be obtained via the IConversation adapter (even
the ++comments++ namespace should use this). This makes it possible to replace the ++conversation++ namespace should use this). This makes it possible to
conversations and comments transparently. replace conversations and comments transparently.
The Comment class The Comment class
----------------- -----------------
@ -150,20 +150,18 @@ an auto-moderation 'white-list', e.g. by email address or username.
Forms and UI Forms and UI
------------ ------------
The basic commenting display/reply form should be placed in a viewlet. The basic commenting display/reply form is placed in a viewlet.
Ideally, the reply form should be inline, perhaps revealed with JavaScript The reply form is dynamically created right under the comment when the user hits
if enabled. This allows full contextualisation of replies. The current the reply button. To do so, we copy the standard comment form with a jQuery
solution, with a separate form that shows some context, is brittle and function. This function sets the form's hidden in_reply_to field to the id of
over-complicated. the comment the user wants to reply to. This also makes is possible to use
z3c.form validation for the reply forms, because we can uniquely identify the
a reply form request and return the reply form with validation errors.
If we support quoting of comments in replies, we can load the text to quote Since we rely on JavaScript for the reply form creation, the reply button is
using JavaScript as well. removed for nonJavaScript enabled browsers.
As a fall-back for non-JavaScript enabled browsers, it is probably OK not to The comment form uses z3c.form and plone.z3cform's ExtensibleForm support. This
support quoting and/or viewing of context, e.g. the user is taken to a standalone makes it possible to plug in additional fields declaratively, e.g. to include
'comment reply' form. SPAM protection.
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.