[Zope3-checkins] CVS: Zope3/src/zope/app/wiki - INSTALL.txt:1.1
README.txt:1.1 TODO.txt:1.1 VERSION.txt:1.1 __init__.py:1.1
configure.zcml:1.1 diff.py:1.1 index.py:1.1 interfaces.py:1.1
traversal.py:1.1 wiki.py:1.1 wikipage.py:1.1
Philipp von Weitershausen
philikon at philikon.de
Fri Feb 27 06:07:02 EST 2004
Update of /cvs-repository/Zope3/src/zope/app/wiki
In directory cvs.zope.org:/tmp/cvs-serv21004/app/wiki
Added Files:
INSTALL.txt README.txt TODO.txt VERSION.txt __init__.py
configure.zcml diff.py index.py interfaces.py traversal.py
wiki.py wikipage.py
Log Message:
Moved the zwiki product to zope.app.wiki. It currently still needs to be
enabled in products.zcml, since it depends on securitypolicy enabled.
That's to change soon when we move securitypolicy back to zope.app.
=== Added File Zope3/src/zope/app/wiki/INSTALL.txt ===
Installation
============
- Since Wiki is not enabled by default, you need to include the Wiki
package in your products.zcml file::
<include package="zope.app.wiki" />
- You need to define the following role declarations to your user in order
to use the wiki package effectively::
<grant role="zwiki.Admin" principal="user" />
<grant role="zwiki.Editor" principal="user" />
<grant role="zwiki.User" principal="user" />
<grant role="zwiki.User" principal="anybody" />
Usage
=====
1. To see Wikis in action, go into the management interface and add a Wiki
object named 'wiki'. Leave the two preselected options.
2. To enter the end user interface, enter::
http://localhost:8080/++skin++wiki/wiki
=== Added File Zope3/src/zope/app/wiki/README.txt ===
ZWiki for Zope 3
================
This product is a port/rewrite of the famous Zope 2 product Zwiki. At
the current stage only the most basic Wiki functionalities are
implemented and much more work needs to be done.
Features
--------
Rendering
- Plain Text
- reStructured Text (reST)
Wiki
- Table of Contents
- Mail Subscription for entire Wiki
- Full-text Search
Wiki Page
- Proper rendering of Wiki Links
- Edit Wiki Page
- Comment on a Wiki Page
- Declare Wiki Hierarchy (Parents)
- Local, WikiPage-based Mail Subscription
- Jumping to other Wikis
Miscellaneous
- Somewhat sophisticated rendering mechanism. New source types and
their render methods can now be configured (added) via ZCML.
- A fully independent skin called 'wiki'; Note that this skill will
be only useful in the context of a Wiki Page.
=== Added File Zope3/src/zope/app/wiki/TODO.txt ===
TODO
====
Tests
- Write tests for diff module
Rendering/Views
- Create custom HTMLDocument class for rendering the STX and ReST in Wiki
style.
- Make sure WebDAV works.
- Add File Extension recognition.
- Create a Management screen (advancedform) that is accessible for users
without management rights.
Other Features
- Make use of Traverser features; i.e. create links that include
parents...
- Check in Traverser that found subobj has self.context as parent.
- Activating diff support for edited Wiki Pages. The main issue right now
is to get to the old version of the text. so that we can execute the
Differ.
=== Added File Zope3/src/zope/app/wiki/VERSION.txt ===
Zope3 Wiki 0.0.1
=== Added File Zope3/src/zope/app/wiki/__init__.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""ZWiki for Zope 3
$Id: __init__.py,v 1.1 2004/02/27 11:06:58 philikon Exp $
"""
=== Added File Zope3/src/zope/app/wiki/configure.zcml ===
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:event="http://namespaces.zope.org/event"
i18n_domain="zope"
>
<!-- Security definitions -->
<role
id="zwiki.User"
title="Wiki User"
description="Wiki visitors, which can only view and comment on wikis." />
<role
id="zwiki.Editor"
title="Wiki Editor"
description="The Wiki Editor can create and edit wikis." />
<role
id="zwiki.Admin"
title="Wiki Administrator"
description="The Wiki Admin can fully manage wiki pages." />
<permission
id="zope.app.wiki.ViewWikiPage"
title="View Wiki Page"
description="View a Wiki Page." />
<grant
permission="zope.app.wiki.ViewWikiPage"
role="zwiki.User" />
<permission
id="zope.app.wiki.CommentWikiPage"
title="Comment on Wiki Page"
description="Make a comment on Wiki Page." />
<grant
permission="zope.app.wiki.CommentWikiPage"
role="zwiki.User" />
<permission
id="zope.app.wiki.AddWikiPage"
title="Add Wiki Page"
description="Add Wiki Page." />
<grant
permission="zope.app.wiki.AddWikiPage"
role="zwiki.Editor" />
<permission
id="zope.app.wiki.EditWikiPage"
title="Edit Wiki Page"
description="Edit Wiki Page." />
<grant
permission="zope.app.wiki.EditWikiPage"
role="zwiki.Editor" />
<permission
id="zope.app.wiki.DeleteWikiPage"
title="Delete Wiki Page"
description="Delete Wiki Page." />
<grant
permission="zope.app.wiki.DeleteWikiPage"
role="zwiki.Admin" />
<permission
id="zope.app.wiki.ReparentWikiPage"
title="Reparent Wiki Page"
description="Reparent a Wiki Page." />
<grant
permission="zope.app.wiki.ReparentWikiPage"
role="zwiki.Admin"/>
<!-- Content declarations -->
<content class=".wiki.Wiki">
<implements interface="zope.app.interfaces.container.IContentContainer" />
<implements
interface="zope.app.interfaces.annotation.IAttributeAnnotatable" />
<factory
id="Wiki"
permission="zope.ManageContent"
description="Minimal Wiki Page Container implementation " />
<require
permission="zope.View"
interface="zope.app.interfaces.container.IReadContainer"/>
<require
permission="zope.app.wiki.AddWikiPage"
interface="zope.app.interfaces.container.IWriteContainer"/>
</content>
<!-- Mail Subscriptions support -->
<adapter
factory=".wikipage.MailSubscriptions"
provides=".interfaces.IMailSubscriptions"
for=".interfaces.IWiki" />
<content class=".wikipage.WikiPage">
<implements
interface="zope.app.interfaces.annotation.IAttributeAnnotatable" />
<factory
id="WikiPage"
permission="zope.app.wiki.AddWikiPage"
title="Wiki Page"
description="A Wiki Page" />
<!-- XXX: I am not sure whether this is safe. We probably have to split
the interface from the schema. -->
<allow interface=".interfaces.IWikiPage" />
<require
permission="zope.app.wiki.AddWikiPage"
set_schema=".interfaces.IWikiPage" />
</content>
<adapter
factory=".wikipage.WikiPageHierarchyAdapter"
provides=".interfaces.IWikiPageHierarchy"
for=".interfaces.IWikiPage" />
<!-- Mail Subscriptions support -->
<adapter
factory=".wikipage.MailSubscriptions"
provides=".interfaces.IMailSubscriptions"
for=".interfaces.IWikiPage" />
<adapter
factory=".traversal.WikiPageTraversable"
provides="zope.app.interfaces.traversing.ITraversable"
for=".interfaces.IWikiPage" />
<adapter
factory="zope.app.wiki.wikipage.SearchableText"
provides="zope.app.interfaces.index.text.ISearchableText"
for="zope.app.wiki.interfaces.IWikiPage" />
<!-- WikiPage FTP configurations -->
<adapter
for=".interfaces.IWikiPage"
provides="zope.app.interfaces.file.IReadFile"
factory=".wikipage.WikiPageReadFile"
permission="zope.app.wiki.ViewWikiPage"
/>
<adapter
for=".interfaces.IWikiPage"
provides="zope.app.interfaces.file.IWriteFile"
factory=".wikipage.WikiPageWriteFile"
permission="zope.app.wiki.EditWikiPage"
/>
<!-- Wiki Index registration -->
<content class=".index.WikiTextIndex">
<require
permission="zope.ManageServices"
interface="zope.app.interfaces.index.text.IUITextIndex"
attributes="query"
/>
<factory
id="zope.app.wiki.index.WikiTextIndex"
permission="zope.ManageServices"
/>
<implements
interface="zope.app.interfaces.services.query.IQueryProcessable"
/>
</content>
<!-- Register event listener for change mails -->
<event:subscribe
subscriber=".wikipage.mailer"
event_types="zope.app.interfaces.event.IObjectAddedEvent
zope.app.interfaces.event.IObjectModifiedEvent
zope.app.interfaces.event.IObjectRemovedEvent
zope.app.interfaces.event.IObjectMovedEvent" />
<!-- Register various browser related components, including all views -->
<include package=".browser" />
</configure>
=== Added File Zope3/src/zope/app/wiki/diff.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Browser View Components for WikiPages
$Id: diff.py,v 1.1 2004/02/27 11:06:58 philikon Exp $
"""
from difflib import ndiff
MAX_OLD_LINES_DISPLAY = 40
MAX_NEW_LINES_DISPLAY = 40
def textdiff(old_text, new_text, verbose=1):
"""
generate a plain text diff, optimized for human readability,
between two revisions of this page, numbering back from the latest.
Alternately, a and/or b texts can be specified.
"""
old = split(old_text, '\n')
new = split(new_text, '\n')
cruncher=ndiff.SequenceMatcher(
isjunk=lambda x: x in " \\t",
a=old,
b=new)
r = []
for tag, old_lo, old_hi, new_lo, new_hi in cruncher.get_opcodes():
if tag == 'replace':
if verbose: r.append('??changed:')
r = r + _abbreviateDiffLines(old[old_lo:old_hi],'-',
MAX_OLD_LINES_DISPLAY)
r = r + _abbreviateDiffLines(new[new_lo:new_hi],'',
MAX_NEW_LINES_DISPLAY)
r.append('')
elif tag == 'delete':
if verbose: r.append('--removed:')
r = r + _abbreviateDiffLines(old[old_lo:old_hi],'-',
MAX_OLD_LINES_DISPLAY)
r.append('')
elif tag == 'insert':
if verbose: r.append('++added:')
r = r + _abbreviateDiffLines(new[new_lo:new_hi],'',
MAX_NEW_LINES_DISPLAY)
r.append('')
elif tag == 'equal':
pass
else:
raise ValueError, 'unknown tag ' + `tag`
return '\n' + join(r, '\n')
def _abbreviateDiffLines(lines, prefix, maxlines=5):
output = []
if maxlines and len(lines) > maxlines:
extra = len(lines) - maxlines
for i in xrange(maxlines - 1):
output.append(prefix + lines[i])
output.append(prefix + "[%d more line%s...]" %
(extra, ((extra == 1) and '') or 's')) # not working
else:
for line in lines:
output.append(prefix + line)
return output
=== Added File Zope3/src/zope/app/wiki/index.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""A custom Text Index for Wikis
$Id: index.py,v 1.1 2004/02/27 11:06:58 philikon Exp $
"""
from zope.app.index.text.index import TextIndex
from zope.app.wiki.interfaces import IWikiPage
class WikiTextIndex(TextIndex):
def notify(wrapped_self, event):
"""An event occurred. Index or unindex the object in response."""
if IWikiPage.isImplementedBy(event.object):
super(WikiTextIndex, wrapped_self).notify(event)
=== Added File Zope3/src/zope/app/wiki/interfaces.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""ZWiki Interface Declarations
This module defines the ZWiki relevant interfaces.
$Id: interfaces.py,v 1.1 2004/02/27 11:06:58 philikon Exp $
"""
from zope.interface import Interface
from zope.schema import TextLine, List, SourceText
from zope.schema.vocabulary import VocabularyField
#from zope.app.interfaces.container import IContentContainer
from zope.schema import Field
from zope.app.interfaces.container import IContained
from zope.app.container.constraints import ContainerTypesConstraint
from zope.app.container.constraints import ItemTypePrecondition
from zope.app.interfaces.container import IContainer
from zope.app.i18n import ZopeMessageIDFactory as _
class IWikiPage(Interface):
"""A single Wiki Page content object.
The Wiki page is a simple content object that stores the content
(source) and the source type of the wiki page."""
source = SourceText(
title=_(u"Source Text"),
description=_(u"Renderable source text of the Wiki Page."),
default=u"",
required=True)
type = VocabularyField(
title=_(u"Source Type"),
description=_(u"Type of the source text, e.g. structured text"),
default=u"reStructured Text (reST)",
required = True,
vocabulary = "SourceTypes")
def append(source):
"""Append some text to the existing source text."""
def comment(source, user):
"""Comment on the current Wiki; add comment to source."""
def getCommentCounter():
"""Returns the amount of written comments for this wiki page."""
class IWikiPageHierarchy(Interface):
"""This interface supports the virtual hierarchical structure of the Wiki
Pages."""
parents = List(
title = _(u"Wiki Page Parents"),
description = _(u"Parents of a a Wiki"),
value_type = TextLine(title=_(u"Parent Name"),
description=_(u"Name of the parent wiki page.")),
required=False)
def reparent(parents):
"""Reset the parents the Wiki page belongs to.
The parents attribute is a list of unicode strings that contain the
names of the parent wiki pages.
"""
def path():
"""Return the object path of the virtual Wiki Hierarchy.
The return value for this method should be a list of wiki objects
describing the path.
XXX: Wiki Pages can have several parents, so that we should be able to
have multiple paths; but let's not worry about that right now. At some
point this needs to be done though.
"""
def findChildren(recursive=True):
"""Returns a list of children for this wiki page.
If the recursive is True, the method recurses into all children
returning the entire sub-tree of this Wiki Page. Is the recursive
argument set to False, only the first level of children will be
returned.
"""
class IWiki(IContainer):
def __setitem__(name, object):
"""Add a poll"""
__setitem__.precondition = ItemTypePrecondition(IWikiPage)
class IWikiContained(IContained):
__parent__ = Field(
constraint = ContainerTypesConstraint(IWiki))
class IMailSubscriptions(Interface):
"""This interface allows you to retrieve a list of E-mails for
mailings. In our context """
def getSubscriptions():
"""Return a list of E-mails."""
def addSubscriptions(emails):
"""Add a bunch of subscriptions, but one would be okay as well."""
def removeSubscriptions(emails):
"""Remove a set of subscriptions."""
=== Added File Zope3/src/zope/app/wiki/traversal.py ===
##############################################################################
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
##############################################################################
"""Specific HTTP
$Id: traversal.py,v 1.1 2004/02/27 11:06:58 philikon Exp $
"""
from zope.interface import implements
from zope.proxy import removeAllProxies
from zope.component import getDefaultViewName, queryView
from zope.publisher.interfaces import IPublishTraverse
from zope.exceptions import NotFoundError
from zope.app.traversing import getParent
from zope.app.traversing.namespace import UnexpectedParameters
from zope.app.interfaces.traversing import ITraversable
from zope.app.wiki.interfaces import IWikiPage
class WikiPageTraverser:
implements(IPublishTraverse)
__used_for__ = IWikiPage
def __init__(self, page, request):
self.context = page
self.wiki = getParent(page)
self.request = request
def publishTraverse(self, request, name):
subob = self.wiki.get(name, None)
# XXX: Check that subobj has self.context as parent!
if subob is None:
view = queryView(self.context, name, request)
if view is not None:
return view
raise NotFoundError(self.context, name, request)
return removeAllProxies(subob)
def browserDefault(self, request):
c = self.context
view_name = getDefaultViewName(c, request)
view_uri = "@@%s" % view_name
return c, (view_uri,)
_marker = object()
class WikiPageTraversable:
"""Traverses wikipages via wiki itself and getattr.
"""
implements(ITraversable)
__used_for__ = IWikiPage
def __init__(self, page):
self._page = page
self._wiki = getParent(page)
def traverse(self, name, parameters, original_name, furtherPath):
if parameters:
raise UnexpectedParameters(parameters)
subobj = self._wiki.get(name, _marker)
if subobj is _marker:
subobj = getattr(self._page, name, _marker)
if subobj is _marker:
raise NotFoundError, original_name
return subobj
=== Added File Zope3/src/zope/app/wiki/wiki.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Wiki implementation
$Id: wiki.py,v 1.1 2004/02/27 11:06:58 philikon Exp $
"""
from zope.interface import implements
from zope.app.folder import Folder
from zope.app.wiki.interfaces import IWiki
class Wiki(Folder):
__doc__ = IWiki.__doc__
implements(IWiki)
=== Added File Zope3/src/zope/app/wiki/wikipage.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Wiki implementation
$Id: wikipage.py,v 1.1 2004/02/27 11:06:58 philikon Exp $
"""
import smtplib
from persistent import Persistent
from zope.interface import implements
from zope.component import getAdapter
from zope.app.traversing import getParent, getName
from zope.app.interfaces.index.text import ISearchableText
from zope.app.interfaces.file import IReadFile, IWriteFile
from zope.app.interfaces.annotation import IAnnotations
from zope.app.interfaces.event import ISubscriber
from zope.app.interfaces.event import IObjectAddedEvent, IObjectModifiedEvent
from zope.app.interfaces.event import IObjectRemovedEvent, IObjectMovedEvent
from zope.app.wiki.interfaces import IWiki, IWikiPage
from zope.app.wiki.interfaces import IWikiPageHierarchy, IMailSubscriptions
__metaclass__ = type
HierarchyKey = 'http://www.zope.org/zwiki#1.0/PageHierarchy/parents'
SubscriberKey = 'http://www.zope.org/zwiki#1.0/MailSubscriptions/emails'
class WikiPage(Persistent):
__doc__ = IWikiPage.__doc__
implements(IWikiPage)
# See zope.app.wiki.interfaces.IWikiPage
source = u''
# See zope.app.wiki.interfaces.IWikiPage
type = u'reStructured Text (reST)'
def __init__(self):
self.__comments = 1
def append(self, source):
"See zope.app.wiki.interfaces.IWikiPage"
self.source += source
def comment(self, comment):
"See zope.app.wiki.interfaces.IWikiPage"
self.__comments += 1
self.append(comment)
def getCommentCounter(self):
"See zope.app.wiki.interfaces.IWikiPage"
return self.__comments
class WikiPageHierarchyAdapter:
__doc__ = IWikiPageHierarchy.__doc__
implements(IWikiPageHierarchy)
__used_for__ = IWikiPage
def __init__(self, context):
self.context = context
self._annotations = getAdapter(context, IAnnotations)
if not self._annotations.get(HierarchyKey):
self._annotations[HierarchyKey] = ()
def reparent(self, parents):
"See zope.app.wiki.interfaces.IWikiPageHierarchy"
self.setParents(parents)
def setParents(self, parents):
self._annotations[HierarchyKey] = tuple(parents)
def getParents(self):
return self._annotations[HierarchyKey]
parents = property(getParents, setParents)
def path(self):
"See zope.app.wiki.interfaces.IWikiPageHierarchy"
# XXX: Allow for multpile parents
if not self.getParents():
return [self.context]
wiki = getParent(self.context)
name = self.getParents()[0]
hier = getAdapter(wiki[name], IWikiPageHierarchy)
return hier.path() + [self.context]
def findChildren(self, recursive=True):
"See zope.app.wiki.interfaces.IWikiPageHierarchy"
wiki = getParent(self.context)
contextName = getName(self.context)
children = []
for pageName in wiki:
hier = getAdapter(wiki[pageName], IWikiPageHierarchy)
if contextName in hier.getParents():
if recursive:
subs = hier.findChildren()
else:
subs = ()
children.append((wiki[pageName], subs))
return tuple(children)
# Adapters for file-system style access
class WikiPageReadFile:
"""Adapter for letting a Wiki Page look like a regular readable file."""
implements(IReadFile)
__used_for__ = IWikiPage
def __init__(self, context):
self.context = context
def read(self):
"""See zope.app.interfaces.file.IReadFile"""
return self.context.source
def size(self):
"""See zope.app.interfaces.file.IReadFile"""
return len(self.context.source)
class WikiPageWriteFile:
"""Adapter for letting a Wiki Page look like a regular writable file."""
implements(IWriteFile)
__used_for__ = IWikiPage
def __init__(self, context):
self.context = context
def write(self, data):
"""See zope.app.interfaces.file.IWriteFile"""
self.context.source = unicode(data)
# Adapter for ISearchableText
class SearchableText:
"""This adapter provides an API that allows the Wiki Pages to be indexed
by the Text Index."""
implements(ISearchableText)
__used_for__ = IWikiPage
def __init__(self, page):
self.page = page
def getSearchableText(self):
return [unicode(self.page.source)]
# Component to fullfill mail subscriptions
class MailSubscriptions:
"""An adapter for WikiPages to provide an interface for collecting E-mails
for sending out change notices."""
implements(IMailSubscriptions)
__used_for__ = IWikiPage, IWiki
def __init__(self, context):
self.context = context
self._annotations = getAdapter(context, IAnnotations)
if not self._annotations.get(SubscriberKey):
self._annotations[SubscriberKey] = ()
def getSubscriptions(self):
"See zope.app.wiki.interfaces.IMailSubscriptions"
return self._annotations[SubscriberKey]
def addSubscriptions(self, emails):
"See zope.app.wiki.interfaces.IMailSubscriptions"
subscribers = list(self._annotations[SubscriberKey])
for email in emails:
# XXX: Make sure these are actually E-mail addresses.
if email not in subscribers:
subscribers.append(email.strip())
self._annotations[SubscriberKey] = tuple(subscribers)
def removeSubscriptions(self, emails):
"See zope.app.wiki.interfaces.IMailSubscriptions"
subscribers = list(self._annotations[SubscriberKey])
for email in emails:
if email in subscribers:
subscribers.remove(email)
self._annotations[SubscriberKey] = tuple(subscribers)
class WikiMailer:
"""Class to handle all outgoing mail."""
implements(ISubscriber)
def __init__(self, host="localhost", port="25"):
"""Initialize the the object."""
self.host = host
self.port = port
def notify(self, event):
"""See zope.app.interfaces.event.ISubscriber"""
if IWikiPage.isImplementedBy(event.object):
if IObjectAddedEvent.isImplementedBy(event):
self.handleAdded(event.object)
elif IObjectModifiedEvent.isImplementedBy(event):
self.handleModified(event.object)
elif IObjectRemovedEvent.isImplementedBy(event):
self.handleRemoved(event.object)
def handleAdded(self, object):
subject = 'Added: '+getName(object)
emails = self.getAllSubscribers(object)
body = object.source
self.mail(emails, subject, body)
def handleModified(self, object):
# XXX: Should have some nice diff code here.
# from diff import textdiff
subject = 'Modified: '+getName(object)
emails = self.getAllSubscribers(object)
body = object.source
self.mail(emails, subject, body)
def handleRemoved(self, object):
subject = 'Removed: '+getName(object)
emails = self.getAllSubscribers(object)
body = subject
self.mail(emails, subject, body)
def getAllSubscribers(self, object):
"""Retrieves all email subscribers by looking into the local Wiki Page
and into the Wiki for the global subscriptions."""
emails = tuple(getAdapter(object,
IMailSubscriptions).getSubscriptions())
emails += tuple(getAdapter(getParent(object),
IMailSubscriptions).getSubscriptions())
return emails
def mail(self, emails, subject, body):
"""Mail out the Wiki change message."""
if not emails:
return
msg = 'Subject: %s\n\n\n%s' %(subject, body)
server = smtplib.SMTP(self.host, self.port)
server.set_debuglevel(0)
server.sendmail('wiki at zope3.org', emails, msg)
server.quit()
# Create a global mailer object.
mailer = WikiMailer()
More information about the Zope3-Checkins
mailing list