SVN: CMF/trunk/CMFCore/ Add option to template FSSTXMethods with ZPT, and make it the default.

Tres Seaver <[email protected]>
Newsgroups gmane.comp.web.zope.cmf.cvs
Message-ID <[email protected]>
Log message for revision 70814:
  Add option to template FSSTXMethods with ZPT, and make it the default.
  

Changed:
  U   CMF/trunk/CMFCore/FSSTXMethod.py
  U   CMF/trunk/CMFCore/tests/test_FSSTXMethod.py

-=-
Modified: CMF/trunk/CMFCore/FSSTXMethod.py
===================================================================
--- CMF/trunk/CMFCore/FSSTXMethod.py	2006-10-19 15:46:15 UTC (rev 70813)
+++ CMF/trunk/CMFCore/FSSTXMethod.py	2006-10-19 17:01:51 UTC (rev 70814)
@@ -1,6 +1,7 @@
 ##############################################################################
 #
-# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+# Copyright (c) 2001, 2006 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.
@@ -22,6 +23,7 @@
 from Globals import InitializeClass
 from OFS.DTMLDocument import DTMLDocument
 from StructuredText.StructuredText import HTML as STX_HTML
+from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
 
 from Products.CMFCore.DirectoryView import registerFileExtension
 from Products.CMFCore.DirectoryView import registerMetaType
@@ -32,7 +34,10 @@
 from Products.CMFCore.utils import _dtmldir
 from Products.CMFCore.utils import _checkConditionalGET
 from Products.CMFCore.utils import _setCacheHeaders
+from Products.CMFCore.utils import _ViewEmulator
 
+_STX_TEMPLATE = 'ZPT'  # or 'DTML'
+
 _DEFAULT_TEMPLATE_DTML = """\
 <dtml-var standard_html_header>
 <dtml-var cooked>
@@ -43,6 +48,50 @@
 <dtml-var stx fmt="structured-text">
 <dtml-var standard_html_footer>"""
 
+_DEFAULT_TEMPLATE_ZPT = """\
+<html metal:use-macro="context/main_template/macros/main">
+<body>
+
+<metal:block metal:fill-slot="body"
+><div tal:replace="structure options/cooked">
+COOKED TEXT HERE
+</div>
+</metal:block>
+
+</body>
+</html>
+"""
+
+_DEFAULT_TEMPLATE_ZPT = """\
+<html metal:use-macro="context/main_template/macros/master">
+<body>
+
+<metal:block metal:fill-slot="body"
+><div tal:replace="structure options/cooked">
+COOKED TEXT HERE
+</div>
+</metal:block>
+
+</body>
+</html>
+"""
+
+_CUSTOMIZED_TEMPLATE_ZPT = """\
+<html metal:use-macro="context/main_template/macros/master">
+<body>
+
+<metal:block metal:fill-slot="body"
+><div tal:define="std modules/Products/PythonScripts/standard;
+                  stx nocall:std/structured_text;"
+      tal:replace="structure python:stx(template.stx)">
+COOKED TEXT HERE
+</div>
+</metal:block>
+
+</body>
+</html>
+"""
+
 class FSSTXMethod(FSObject):
     """ A chunk of StructuredText, rendered as a skin method of a CMF site.
     """
@@ -67,7 +116,12 @@
         """
             Create a ZODB (editable) equivalent of this object.
         """
-        target = DTMLDocument(_CUSTOMIZED_TEMPLATE_DTML, __name__=self.getId())
+        if _STX_TEMPLATE == 'DTML':
+            target = DTMLDocument(_CUSTOMIZED_TEMPLATE_DTML,
+                                  __name__=self.getId())
+        elif _STX_TEMPLATE == 'ZPT':
+            target = ZopePageTemplate(self.getId(), _CUSTOMIZED_TEMPLATE_ZPT)
+
         target._setProperty('stx', self.raw, 'text')
         return target
 
@@ -107,7 +161,9 @@
             self._v_cooked = STX_HTML(self.raw, level=1, header=0)
         return self._v_cooked
 
-    _default_template = DTML_HTML(_DEFAULT_TEMPLATE_DTML)
+    _default_DTML_template = DTML_HTML(_DEFAULT_TEMPLATE_DTML)
+    _default_ZPT_template = ZopePageTemplate('stxmethod_view',
+                                             _DEFAULT_TEMPLATE_ZPT, 'text/html')
 
     def __call__( self, REQUEST={}, RESPONSE=None, **kw ):
         """ Return our rendered StructuredText.
@@ -117,11 +173,11 @@
         if RESPONSE is not None:
             RESPONSE.setHeader( 'Content-Type', 'text/html' )
 
-        faux_wrapped = self.__of__(self) # we are our own "content"
-        if _checkConditionalGET(faux_wrapped, extra_context={}):
+        view = _ViewEmulator(self.getId()).__of__(self)
+        if _checkConditionalGET(view, extra_context={}):
             return ''
 
-        _setCacheHeaders(faux_wrapped, extra_context={})
+        _setCacheHeaders(view, extra_context={})
 
         return self._render(REQUEST, RESPONSE, **kw)
 
@@ -133,8 +189,15 @@
     def _render(self, REQUEST={}, RESPONSE=None, **kw):
         """ Find the appropriate rendering template and use it to render us.
         """
-        template = getattr(self, 'stxmethod_view', self._default_template)
+        if _STX_TEMPLATE == 'DTML':
+            default_template = self._default_DTML_template
+        elif _STX_TEMPLATE == 'ZPT':
+            default_template = self._default_ZPT_template
+        else:
+            raise TypeError('Invalid STX template: %s' % _STX_TEMPLATE)
 
+        template = getattr(self, 'stxmethod_view', default_template)
+
         if getattr(template, 'isDocTemp', 0):
             #posargs = (self, REQUEST, RESPONSE)
             posargs = (self, REQUEST)

Modified: CMF/trunk/CMFCore/tests/test_FSSTXMethod.py
===================================================================
--- CMF/trunk/CMFCore/tests/test_FSSTXMethod.py	2006-10-19 15:46:15 UTC (rev 70813)
+++ CMF/trunk/CMFCore/tests/test_FSSTXMethod.py	2006-10-19 17:01:51 UTC (rev 70814)
@@ -16,9 +16,8 @@
 """
 import unittest
 import os
+import re
 
-#import Testing
-
 from Products.CMFCore.tests.base.testcase import FSDVTest
 from Products.CMFCore.tests.base.testcase import RequestTest
 from Products.CMFCore.tests.base.testcase import SecurityTest
@@ -46,28 +45,81 @@
 </html>
 """
 
-class FSSTXMethodTests(RequestTest, FSSTXMaker):
+_TEST_MAIN_TEMPLATE = """\
+<html metal:define-macro="main">
+<body>
 
+<metal:block define-slot="body">
+<h1>Title Goes Here</h1>
+<h2>  Subhead Here</h2>
+<p>    And this is a paragraph,
+    broken across lines.</p>
+</metal:block>
+</body>
+</html>
+"""
+
+WS = re.compile(r'\s+')
+
+def _normalize_whitespace(text):
+    return ' '.join(WS.split(text))
+
+
+class _TemplateSwitcher:
+
     def setUp(self):
+        import Products.CMFCore.FSSTXMethod
+        self._old_STX_TEMPLATE = Products.CMFCore.FSSTXMethod._STX_TEMPLATE
+
+    def tearDown(self):
+        RequestTest.tearDown(self)
+        FSSTXMaker.tearDown(self)
+        self._setWhichTemplate(self._old_STX_TEMPLATE)
+
+    def _setWhichTemplate(self, which):
+        import Products.CMFCore.FSSTXMethod
+        from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
+        Products.CMFCore.FSSTXMethod._STX_TEMPLATE = which
+
+        if which == 'DTML':
+            self.root.standard_html_header = (
+                    lambda *args, **kw: '<html>\n<body>\n')
+            self.root.standard_html_footer = (
+                    lambda *args, **kw: '</body>\n</html>\n')
+        elif which == 'ZPT':
+            main = ZopePageTemplate('main_template', _TEST_MAIN_TEMPLATE)
+            self.root._setOb('main_template', main)
+
+class FSSTXMethodTests(RequestTest, FSSTXMaker, _TemplateSwitcher):
+
+    def setUp(self):
+        _TemplateSwitcher.setUp(self)
         FSSTXMaker.setUp(self)
         RequestTest.setUp(self)
-        self.root.standard_html_header = (
-                lambda *args, **kw: '<html>\n<body>\n')
-        self.root.standard_html_footer = (
-                lambda *args, **kw: '</body>\n</html>\n')
 
     def tearDown(self):
         RequestTest.tearDown(self)
         FSSTXMaker.tearDown(self)
+        _TemplateSwitcher.tearDown(self)
 
-    def test___call__( self ):
+    def test___call___with_DTML( self ):
+        self._setWhichTemplate('DTML')
         script = self._makeOne( 'testSTX', 'testSTX.stx' )
         script = script.__of__(self.app)
-        self.assertEqual(script(self.REQUEST), _EXPECTED_HTML)
+        self.assertEqual(_normalize_whitespace(script(self.REQUEST)),
+                         _normalize_whitespace(_EXPECTED_HTML))
 
+    def test___call___with_ZPT( self ):
+        self._setWhichTemplate('ZPT')
+        script = self._makeOne( 'testSTX', 'testSTX.stx' )
+        script = script.__of__(self.app)
+        self.assertEqual(_normalize_whitespace(script(self.REQUEST)),
+                         _normalize_whitespace(_EXPECTED_HTML))
+
     def test_caching( self ):
         #   Test HTTP caching headers.
         from Products.CMFCore.tests.base.dummy import DummyCachingManager
+        self._setWhichTemplate('DTML')
         self.root.caching_policy_manager = DummyCachingManager()
         original_len = len( self.RESPONSE.headers )
         script = self._makeOne('testSTX', 'testSTX.stx')
@@ -108,12 +160,22 @@
         self.assertEqual( data, '' )
         self.assertEqual( self.RESPONSE.getStatus(), 304 )
 
-class FSSTXMethodCustomizationTests( SecurityTest, FSSTXMaker ):
+ADD_ZPT = 'Add page templates'
+ZPT_META_TYPES = ( { 'name'        : 'Page Template'
+                   , 'action'      : 'manage_addPageTemplate'
+                   , 'permission'  : ADD_ZPT
+                   }
+                 ,
+                 )
 
+class FSSTXMethodCustomizationTests( SecurityTest, FSSTXMaker,
+                                     _TemplateSwitcher ):
+
     def setUp( self ):
         from OFS.Folder import Folder
         FSSTXMaker.setUp(self)
         SecurityTest.setUp( self )
+        _TemplateSwitcher.setUp( self )
 
         self.root._setObject( 'portal_skins', Folder( 'portal_skins' ) )
         self.skins = self.root.portal_skins
@@ -129,10 +191,17 @@
 
         self.fsSTX = self.fsdir.testSTX
 
-    def test_customize( self ):
+    def tearDown( self ):
+        _TemplateSwitcher.tearDown( self )
+        FSSTXMaker.tearDown( self )
+        SecurityTest.tearDown( self )
+
+    def test_customize_with_DTML( self ):
         from OFS.DTMLDocument import DTMLDocument
         from Products.CMFCore.FSSTXMethod import _CUSTOMIZED_TEMPLATE_DTML
 
+        self._setWhichTemplate('DTML')
+
         self.fsSTX.manage_doCustomize(folder_path='custom')
 
         self.assertEqual(len(self.custom.objectIds()), 1)
@@ -147,10 +216,33 @@
 
         self.assertEqual(target.document_src(), _CUSTOMIZED_TEMPLATE_DTML)
 
+    def test_customize_with_ZPT( self ):
+        from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
+        from Products.CMFCore.FSSTXMethod import _CUSTOMIZED_TEMPLATE_ZPT
+
+        self._setWhichTemplate('ZPT')
+        self.custom.all_meta_types = ZPT_META_TYPES
+
+        self.fsSTX.manage_doCustomize(folder_path='custom')
+
+        self.assertEqual(len(self.custom.objectIds()), 1)
+        self.failUnless('testSTX' in self.custom.objectIds())
+        target = self.custom._getOb('testSTX')
+
+        self.failUnless(isinstance(target, ZopePageTemplate))
+
+        propinfo = target.propdict()['stx']
+        self.assertEqual(propinfo['type'], 'text')
+        self.assertEqual(target.stx, self.fsSTX.raw)
+
+        self.assertEqual(target.document_src(), _CUSTOMIZED_TEMPLATE_ZPT)
+
     def test_customize_caching(self):
         # Test to ensure that cache manager associations survive customizing
         from Products.StandardCacheManagers import RAMCacheManager
         cache_id = 'gofast'
+        self._setWhichTemplate('ZPT')
+        self.custom.all_meta_types = ZPT_META_TYPES
         RAMCacheManager.manage_addRAMCacheManager( self.root
                                                  , cache_id
                                                  , REQUEST=None
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.