[CMF-checkins] SVN: CMF/branches/tseaver-viewification/ Branch for
viewifying CMFDefault.
Tres Seaver
tseaver at palladion.com
Fri Oct 21 19:27:46 EDT 2005
Log message for revision 39555:
Branch for viewifying CMFDefault.
Changed:
A CMF/branches/tseaver-viewification/
A CMF/branches/tseaver-viewification/CMFDefault/browser/
A CMF/branches/tseaver-viewification/CMFDefault/browser/__init__.py
A CMF/branches/tseaver-viewification/CMFDefault/browser/configure.zcml
A CMF/branches/tseaver-viewification/CMFDefault/browser/metadata.pt
A CMF/branches/tseaver-viewification/CMFDefault/browser/metadata.py
A CMF/branches/tseaver-viewification/CMFDefault/browser/tests/
A CMF/branches/tseaver-viewification/CMFDefault/browser/tests/__init__.py
A CMF/branches/tseaver-viewification/CMFDefault/browser/tests/test_metadata.py
U CMF/branches/tseaver-viewification/CMFDefault/configure.zcml
-=-
Copied: CMF/branches/tseaver-viewification (from rev 39553, CMF/trunk)
Added: CMF/branches/tseaver-viewification/CMFDefault/browser/__init__.py
===================================================================
--- CMF/trunk/CMFDefault/browser/__init__.py 2005-10-21 17:53:46 UTC (rev 39553)
+++ CMF/branches/tseaver-viewification/CMFDefault/browser/__init__.py 2005-10-21 23:27:46 UTC (rev 39555)
@@ -0,0 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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 package for CMFDefault.
+
+$Id$
+"""
Property changes on: CMF/branches/tseaver-viewification/CMFDefault/browser/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/tseaver-viewification/CMFDefault/browser/configure.zcml
===================================================================
--- CMF/trunk/CMFDefault/browser/configure.zcml 2005-10-21 17:53:46 UTC (rev 39553)
+++ CMF/branches/tseaver-viewification/CMFDefault/browser/configure.zcml 2005-10-21 23:27:46 UTC (rev 39555)
@@ -0,0 +1,24 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser"
+ >
+
+ <browser:page
+ for="Products.CMFCore.interfaces.IMutableDublinCore"
+ class=".metadata.MetadataView"
+ name="metadata.html"
+ template="metadata.pt"
+ permission="cmf.ModifyPortalContent"
+ layer="cmf"
+ />
+
+ <browser:page
+ for="Products.CMFCore.interfaces.IMutableDublinCore"
+ class=".metadata.MetadataView"
+ name="metadata.py"
+ attribute="controller"
+ permission="cmf.ModifyPortalContent"
+ layer="cmf"
+ />
+
+</configure>
Added: CMF/branches/tseaver-viewification/CMFDefault/browser/metadata.pt
===================================================================
--- CMF/trunk/CMFDefault/browser/metadata.pt 2005-10-21 17:53:46 UTC (rev 39553)
+++ CMF/branches/tseaver-viewification/CMFDefault/browser/metadata.pt 2005-10-21 23:27:46 UTC (rev 39555)
@@ -0,0 +1,125 @@
+<html metal:use-macro="context/@@standard_macros/page"
+>
+<body>
+
+<metal:slot metal:fill-slot="header"
+ i18n:domain="cmf_default">
+<h1 i18n:translate="">
+ Resource Metadata: <tal:span tal:content="context/Title"
+ i18n:name="obj_title">Title</tal:span></h1>
+</metal:slot>
+
+<metal:slot metal:fill-slot="body"
+ i18n:domain="cmf_default"
+ tal:define="minfo view/getMetadataInfo;
+ finfo view/getFormInfo;
+ ">
+
+<form action="metadata.py" method="post">
+<table class="FormLayout">
+ <tr>
+ <th i18n:translate="">Enable Discussion?</th>
+ <td colspan="3"
+ tal:define="allowed finfo/allow_discussion" >
+ <select name="allow_discussion" >
+ <option value="default"
+ tal:attributes="selected python: allowed is None"
+ i18n:translate="">Default</option>
+ <option value="off"
+ tal:attributes="selected python: allowed is False"
+ i18n:translate="">Off</option>
+ <option value="on"
+ tal:attributes="selected python: allowed is True"
+ i18n:translate="">On</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Identifier</th>
+ <td colspan="3"> <span tal:replace="minfo/Identifier"></span>
+ </td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Title</th>
+ <td colspan="3">
+ <input type="text" name="title" value="" size="65"
+ tal:attributes="value minfo/Title" />
+ </td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Description</th>
+ <td colspan="3">
+ <textarea name="description:text" rows="5" cols="65" wrap="soft"
+ tal:content="minfo/Description"></textarea>
+ </td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Subject</th>
+ <td>
+ <textarea name="subject:lines" rows="3" cols="20"
+ tal:content="finfo/subject_lines"></textarea>
+ </td>
+ <th i18n:translate="">Contributors</th>
+ <td>
+ <textarea name="contributors:lines" rows="5" cols="30"
+ tal:content="finfo/contributor_lines"></textarea>
+ </td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Creation Date</th>
+ <td> <span tal:replace="minfo/CreationDate"></span>
+ </td>
+ <th i18n:translate="">Last Modified Date</th>
+ <td> <span tal:replace="minfo/ModificationDate"></span>
+ </td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Effective Date</th>
+ <td>
+ <input type="text" name="effective_date" value=""
+ tal:attributes="value minfo/EffectiveDate" />
+ </td>
+ <th i18n:translate="">Expiration Date</th>
+ <td>
+ <input type="text" name="expiration_date" value=""
+ tal:attributes="value minfo/ExpirationDate" />
+ </td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Format</th>
+ <td> <input type="text" name="format" value=""
+ tal:attributes="value minfo/Format" />
+ </td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Language</th>
+ <td> <input type="text" name="language" value=""
+ tal:attributes="value minfo/Language" />
+ </td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Rights</th>
+ <td> <input type="text" name="rights" value=""
+ tal:attributes="value minfo/Rights" />
+ </td>
+ </tr>
+ <tr>
+ <td> </td>
+ <td colspan="3">
+ <div class="FormButtons">
+ <tal:loop tal:repeat="button finfo/buttons"
+ ><input type="submit" name="ButtonName" value="ButtonValue"
+ tal:attributes="name button/name;
+ value button/value;
+ "
+ i18n:attributes="value" /></tal:loop>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+</metal:slot>
+
+</body>
+</html>
Property changes on: CMF/branches/tseaver-viewification/CMFDefault/browser/metadata.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: CMF/branches/tseaver-viewification/CMFDefault/browser/metadata.py
===================================================================
--- CMF/trunk/CMFDefault/browser/metadata.py 2005-10-21 17:53:46 UTC (rev 39553)
+++ CMF/branches/tseaver-viewification/CMFDefault/browser/metadata.py 2005-10-21 23:27:46 UTC (rev 39555)
@@ -0,0 +1,142 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+""" Metadata view class
+
+$Id$
+"""
+from Globals import InitializeClass
+from Products.Five.browser import BrowserView
+from Products.CMFCore.interfaces import IDublinCore
+from Products.CMFCore.interfaces import ICatalogableDublinCore
+from Products.CMFCore.utils import getToolByName
+
+from Products.CMFDefault.utils import MessageID as _
+
+_DC_NAMES = IDublinCore.names()
+_CDC_NAMES = ICatalogableDublinCore.names()
+
+_BUTTONS = {
+ 'change':
+ {'value': _('Change'),
+ 'redirect' : 'metadata.html',
+ },
+ 'change_and_edit':
+ {'value': _('Change and Edit'),
+ 'redirect': 'edit.html',
+ },
+ 'change_and_view':
+ {'value': _('Change and View'),
+ 'redirect': 'view.html',
+ },
+}
+
+_BUTTON_NAMES = ('change', 'change_and_edit', 'change_and_view')
+
+def _tuplify( value ):
+
+ if isinstance(value, basestring):
+ value = (value,)
+ elif not isinstance(value, tuple):
+ value = tuple(value)
+
+ return tuple(filter(None, value))
+
+class MetadataView(BrowserView):
+
+ def getMetadataInfo(self):
+ """ Return a mapping describing all our context's metadata.
+ """
+ result = {}
+ context = self.context
+
+ for name in _DC_NAMES + _CDC_NAMES:
+
+ if name.startswith('list'):
+ key = name[4:]
+ elif name == 'Contributors':
+ key = name
+ name = 'listContributors'
+ else:
+ key = name
+
+ result[key] = getattr(context, name)()
+
+ return result
+
+ def getFormInfo(self):
+ """ Return a mapping describing all our context formstate.
+ """
+ result = {}
+ context = self.context
+ result['allow_discussion'] = getattr(context, 'allow_discussion', None)
+ result['subject_lines'] = '\n'.join(context.Subject())
+ result['contributor_lines'] = '\n'.join(context.listContributors())
+ result['buttons'] = [{'name': name, 'value': _BUTTONS[name]['value']}
+ for name in _BUTTON_NAMES]
+ return result
+
+ def update(self, form):
+ context = self.context
+ dtool = getToolByName(context, 'portal_discussion', None)
+
+ if 'title' in form:
+ context.setTitle(form['title'])
+
+ if 'description' in form:
+ context.setDescription(form['description'])
+
+ if 'subject' in form:
+ context.setSubject(_tuplify(form['subject']))
+
+ if 'contributors' in form:
+ context.setContributors(_tuplify(form['contributors']))
+
+ if 'effective_date' in form:
+ context.setEffectiveDate(form['effective_date'])
+
+ if 'expiration_date' in form:
+ context.setExpirationDate(form['expiration_date'])
+
+ if 'format' in form:
+ context.setFormat(form['format'])
+
+ if 'language' in form:
+ context.setLanguage(form['language'])
+
+ if 'rights' in form:
+ context.setRights(form['rights'])
+
+ if dtool and 'allow_discussion' in form:
+ allow_discussion = form['allow_discussion']
+ if allow_discussion == 'default':
+ allow_discussion = None
+ elif allow_discussion == 'off':
+ allow_discussion = False
+ elif allow_discussion == 'on':
+ allow_discussion = True
+ dtool.overrideDiscussionFor(context, allow_discussion)
+
+ def controller(self, RESPONSE):
+ """ Process a form post and redirect, if needed.
+ """
+ context = self.context
+ form = self.request.form
+ for button in _BUTTONS.keys():
+ if button in form:
+ self.update(form)
+ redirect = _BUTTONS[button]['redirect']
+ RESPONSE.redirect('%s/%s' % (context.absolute_url(), redirect))
+ return
+
+ return self.index()
+
Property changes on: CMF/branches/tseaver-viewification/CMFDefault/browser/metadata.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/tseaver-viewification/CMFDefault/browser/tests/__init__.py
===================================================================
--- CMF/trunk/CMFDefault/browser/tests/__init__.py 2005-10-21 17:53:46 UTC (rev 39553)
+++ CMF/branches/tseaver-viewification/CMFDefault/browser/tests/__init__.py 2005-10-21 23:27:46 UTC (rev 39555)
@@ -0,0 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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 package unit tests for CMFDefault.
+
+$Id$
+"""
Property changes on: CMF/branches/tseaver-viewification/CMFDefault/browser/tests/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: CMF/branches/tseaver-viewification/CMFDefault/browser/tests/test_metadata.py
===================================================================
--- CMF/trunk/CMFDefault/browser/tests/test_metadata.py 2005-10-21 17:53:46 UTC (rev 39553)
+++ CMF/branches/tseaver-viewification/CMFDefault/browser/tests/test_metadata.py 2005-10-21 23:27:46 UTC (rev 39555)
@@ -0,0 +1,234 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+""" Unit tests for CMFDefault's metadata views
+
+$Id$
+"""
+import unittest
+from Products.Five.traversable import FakeRequest
+from DateTime.DateTime import DateTime
+
+_DC_VALUES = {
+ 'Title': "Title",
+ 'Creators': ("Creator",),
+ 'Subject': ("Subject",),
+ 'Description': "Description",
+ 'Publisher': "Publisher",
+ 'Contributors': ("Contributors",),
+ 'created': DateTime('2005-10-21'),
+ 'effective': DateTime('2005-10-23'),
+ 'expires': DateTime('2005-10-24'),
+ 'modified': DateTime('2005-10-22'),
+ 'Type': "Type",
+ 'Format': "Format",
+ 'Identifier': "Identifier",
+ 'Language': "Language",
+ 'Rights': "Rights",
+}
+
+_DC_DATE_STRINGS = [
+ ('created', 'CreationDate',),
+ ('modified', 'ModificationDate',),
+ ('effective', 'EffectiveDate',),
+ ('expires', 'ExpirationDate',),
+]
+
+_EXAMPLE_URL = 'http://www.example.com/document'
+
+class MetadataViewTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from Products.CMFDefault.browser.metadata import MetadataView
+ return MetadataView
+
+ def _makeOne(self, context, request=None, *args, **kw):
+ if request is None:
+ request = FakeRequest()
+ return self._getTargetClass()(context, request, *args, **kw)
+
+ def _makeContext(self, **kw):
+ from zope.interface import implements
+ from Products.CMFCore.interfaces import IMutableDublinCore
+
+ class _Dummy:
+ implements(IMutableDublinCore)
+ allow_discussion = None
+ def __init__(self, kw):
+ self.__dict__.update(dict([('_%s' % k, v)
+ for k, v in _DC_VALUES.items()]))
+ self.__dict__.update(kw)
+
+ def Title(self):
+ return self._Title
+
+ def listCreators(self):
+ return self._Creators
+
+ def Creator(self):
+ return self._Creators[0]
+
+ def Subject(self):
+ return self._Subject
+
+ def Description(self):
+ return self._Description
+
+ def Publisher(self):
+ return self._Publisher
+
+ def listContributors(self):
+ return self._Contributors
+
+ def Date(self):
+ return self._created.Date()
+
+ def CreationDate(self):
+ return self._created.Date()
+
+ def EffectiveDate(self):
+ return self._effective.Date()
+
+ def ExpirationDate(self):
+ return self._expires.Date()
+
+ def ModificationDate(self):
+ return self._modified.Date()
+
+ def Type(self):
+ return self._Type
+
+ def Format(self):
+ return self._Format
+
+ def Identifier(self):
+ return self._Identifier
+
+ def Language(self):
+ return self._Language
+
+ def Rights(self):
+ return self._Rights
+
+ def created(self):
+ return self._created
+
+ def effective(self):
+ return self._effective
+
+ def expires(self):
+ return self._expires
+
+ def modified(self):
+ return self._modified
+
+ def absolute_url(self):
+ return _EXAMPLE_URL
+
+ def setTitle(self, value):
+ self._Title = value
+
+ return _Dummy(kw)
+
+ def test_empty(self):
+ context = self._makeContext()
+ request = FakeRequest()
+ view = self._makeOne(context, request)
+ self.failUnless(view.context is context)
+ self.failUnless(view.request is request)
+
+ def test_getMetadataInfo(self):
+ context = self._makeContext()
+ view = self._makeOne(context)
+
+ minfo = view.getMetadataInfo()
+
+ for k, v in _DC_VALUES.items():
+ self.assertEqual(minfo[k], v)
+
+ for dn, sn in _DC_DATE_STRINGS:
+ mapped = _DC_VALUES[dn].Date()
+ self.assertEquals(minfo[sn], mapped)
+
+ def test_getFormInfo_allow_discussion(self):
+ context = self._makeContext()
+ view = self._makeOne(context)
+
+ finfo = view.getFormInfo()
+ self.assertEqual(finfo['allow_discussion'], None)
+
+ context.allow_discussion = False
+ finfo = view.getFormInfo()
+ self.assertEqual(finfo['allow_discussion'], False)
+
+ context.allow_discussion = True
+ finfo = view.getFormInfo()
+ self.assertEqual(finfo['allow_discussion'], True)
+
+ def test_getFormInfo_subject_lines(self):
+ SUBJECTS = ('abc', 'def')
+ context = self._makeContext()
+ context._Subject = SUBJECTS
+ view = self._makeOne(context)
+ finfo = view.getFormInfo()
+ self.assertEqual(finfo['subject_lines'], '\n'.join(SUBJECTS))
+
+ def test_getFormInfo_contributor_lines(self):
+ CONTRIBUTORS = ('abc', 'def')
+ context = self._makeContext()
+ context._Contributors = CONTRIBUTORS
+ view = self._makeOne(context)
+ finfo = view.getFormInfo()
+ self.assertEqual(finfo['contributor_lines'], '\n'.join(CONTRIBUTORS))
+
+ def test_getFormInfo_buttons(self):
+ BUTTONS =(('change', 'Change'),
+ ('change_and_edit', 'Change and Edit'),
+ ('change_and_view', 'Change and View'),
+ )
+ context = self._makeContext()
+ view = self._makeOne(context)
+ finfo = view.getFormInfo()
+ buttons = finfo['buttons']
+
+ self.assertEqual(len(buttons), len(BUTTONS))
+ for found, expected in zip(buttons, BUTTONS):
+ self.assertEqual(found['name'], expected[0])
+
+ def test_controller_redirect(self):
+ NEW_TITLE = 'New Title'
+
+ class _DummyResponse:
+ _redirected = None
+ def redirect(self, target):
+ self._redirected = target
+
+ context = self._makeContext()
+ request = FakeRequest()
+ request.form = {'title': NEW_TITLE, 'change': 'Change'}
+ response = _DummyResponse()
+
+ view = self._makeOne(context, request)
+ view.controller(response)
+ self.assertEqual(response._redirected,
+ '%s/%s' % (_EXAMPLE_URL, 'metadata.html'))
+ self.assertEqual(context._Title, NEW_TITLE)
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(MetadataViewTests),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
+
Property changes on: CMF/branches/tseaver-viewification/CMFDefault/browser/tests/test_metadata.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Modified: CMF/branches/tseaver-viewification/CMFDefault/configure.zcml
===================================================================
--- CMF/trunk/CMFDefault/configure.zcml 2005-10-21 17:53:46 UTC (rev 39553)
+++ CMF/branches/tseaver-viewification/CMFDefault/configure.zcml 2005-10-21 23:27:46 UTC (rev 39555)
@@ -1,5 +1,6 @@
<configure
xmlns="http://namespaces.zope.org/zope"
+ xmlns:five="http://namespaces.zope.org/five"
>
<include
@@ -7,7 +8,19 @@
/>
<include
+ file="configure.zcml"
+ package=".browser"
+ />
+
+ <include
file="exportimport.zcml"
/>
+ <!-- XXX: Setting this is required to make the views accessible TTW, but it
+ breaks tests for now. 2005/10/21, TS
+ <five:traversable
+ class="Products.CMFDefault.Document.Document"
+ />
+ -->
+
</configure>
More information about the CMF-checkins
mailing list