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> _______________________________________________ CMF-checkins mailing list [email protected] http://mail.zope.org/mailman/listinfo/cmf-checkins
