[Zope-Checkins] SVN: Zope/trunk/lib/python/Products/PageTemplates/ replaced ZopePageTemplate implementation with Z3 ZPT

Andreas Jung andreas at andreas-jung.com
Mon Feb 27 12:46:22 EST 2006


Log message for revision 65525:
  replaced ZopePageTemplate implementation with Z3 ZPT
  (PageTemplateFile needs more migration work)
  

Changed:
  U   Zope/trunk/lib/python/Products/PageTemplates/ZopePageTemplate.py
  A   Zope/trunk/lib/python/Products/PageTemplates/pt/
  A   Zope/trunk/lib/python/Products/PageTemplates/pt/default.html
  A   Zope/trunk/lib/python/Products/PageTemplates/pt/exclamation.gif
  A   Zope/trunk/lib/python/Products/PageTemplates/pt/ptAdd.pt
  A   Zope/trunk/lib/python/Products/PageTemplates/pt/ptEdit.pt
  A   Zope/trunk/lib/python/Products/PageTemplates/pt/zpt.gif
  U   Zope/trunk/lib/python/Products/PageTemplates/tests/testZopePageTemplate.py

-=-
Modified: Zope/trunk/lib/python/Products/PageTemplates/ZopePageTemplate.py
===================================================================
--- Zope/trunk/lib/python/Products/PageTemplates/ZopePageTemplate.py	2006-02-27 17:37:42 UTC (rev 65524)
+++ Zope/trunk/lib/python/Products/PageTemplates/ZopePageTemplate.py	2006-02-27 17:46:20 UTC (rev 65525)
@@ -10,41 +10,56 @@
 # FOR A PARTICULAR PURPOSE
 #
 ##############################################################################
-"""Zope Page Template module
 
-Zope object encapsulating a Page Template.
-"""
+""" Zope Page Template module (wrapper for the Zope 3 ZPT implementation) """
 
 __version__='$Revision: 1.48 $'[11:-2]
 
-import os, AccessControl, Acquisition, sys, types
-from types import StringType
-from Globals import DTMLFile, ImageFile, MessageDialog, package_home
+import re
+import os
+import Acquisition 
+from Globals import ImageFile, package_home, InitializeClass
 from OFS.SimpleItem import SimpleItem
+from OFS.content_types import guess_content_type
 from DateTime.DateTime import DateTime
-from Shared.DC.Scripts.Script import Script, BindingsUI
+from Shared.DC.Scripts.Script import Script 
 from Shared.DC.Scripts.Signature import FuncCode
-from AccessControl import getSecurityManager
-try:
-    from AccessControl import Unauthorized
-except ImportError:
-    Unauthorized = "Unauthorized"
+
 from OFS.History import Historical, html_diff
 from OFS.Cache import Cacheable
 from OFS.Traversable import Traversable
 from OFS.PropertyManager import PropertyManager
-from PageTemplate import PageTemplate
-from Expressions import SecureModuleImporter
-from PageTemplateFile import PageTemplateFile
 
+from AccessControl import getSecurityManager, safe_builtins, ClassSecurityInfo
+from AccessControl.Permissions import view, ftp_access, change_page_templates, view_management_screens
+
 from webdav.Lockable import ResourceLockedError
 from webdav.WriteLockInterface import WriteLockInterface
+from zope.pagetemplate.pagetemplate import PageTemplate 
+from zope.pagetemplate.pagetemplatefile import sniff_type
 
+# regular expression to extract the encoding from the XML preamble
+encoding_reg= re.compile('<\?xml.*?encoding="(.*?)".*?\?>', re.M)
+
+preferred_encodings = ['utf-8', 'iso-8859-15']
+if os.environ.has_key('ZPT_PREFERRED_ENCODING'):
+    preferred_encodings.insert(0, os.environ['ZPT_PREFERRED_ENCODING'])
+
+class SecureModuleImporter:
+    __allow_access_to_unprotected_subobjects__ = 1
+    def __getitem__(self, module):
+        mod = safe_builtins['__import__'](module)
+        path = module.split('.')
+        for name in path[1:]:
+            mod = getattr(mod, name)
+        return mod
+
+
 class Src(Acquisition.Explicit):
-    " "
+    """ I am scary code """
 
+    index_html = None
     PUT = document_src = Acquisition.Acquired
-    index_html = None
 
     def __before_publishing_traverse__(self, ob, request):
         if getattr(request, '_hacked_path', 0):
@@ -55,9 +70,31 @@
         return self.document_src(REQUEST)
 
 
+def sniffEncoding(text, default_encoding='utf-8'):
+    """ try to determine the encoding from html or xml """
+
+    if text.startswith('<?xml'):
+        mo = encoding_reg.search(text)
+        if mo:
+            return mo.group(1)
+    return default_encoding
+
+
+def guess_type(filename, text):
+
+    content_type, dummy = guess_content_type(filename, text)
+    if content_type in ('text/html', 'text/xml'):
+        return content_type
+
+    return sniff_type(text) or 'text/html'
+
+
+_default_content_fn = os.path.join(package_home(globals()), 'pt', 'default.html')
+  
+
 class ZopePageTemplate(Script, PageTemplate, Historical, Cacheable,
                        Traversable, PropertyManager):
-    "Zope wrapper for Page Template using TAL, TALES, and METAL"
+    """ Z2 wrapper class for Zope 3 page templates """
 
     __implements__ = (WriteLockInterface,)
 
@@ -67,8 +104,7 @@
     func_code = FuncCode((), 0)
 
     _default_bindings = {'name_subpath': 'traverse_subpath'}
-    _default_content_fn = os.path.join(package_home(globals()),
-                                       'www', 'default.html')
+    _default_content_fn = os.path.join(package_home(globals()), 'www', 'default.html')
 
     manage_options = (
         {'label':'Edit', 'action':'pt_editForm',
@@ -79,52 +115,44 @@
         + SimpleItem.manage_options \
         + Cacheable.manage_options
 
-    _properties=({'id':'title', 'type': 'string', 'mode': 'wd'},
+
+    _properties=({'id':'title', 'type': 'ustring', 'mode': 'w'},
                  {'id':'content_type', 'type':'string', 'mode': 'w'},
                  {'id':'expand', 'type':'boolean', 'mode': 'w'},
                  )
 
-    def __init__(self, id, text=None, content_type=None):
-        self.id = str(id)
+    security = ClassSecurityInfo()
+    security.declareObjectProtected(view)
+    security.declareProtected(view, '__call__')
+
+    def __init__(self, id, text=None, content_type=None, encoding='utf-8', strict=False):
+        self.id = id
+        self.expand = 0                                                               
+        self.strict = strict
         self.ZBindings_edit(self._default_bindings)
-        if text is None:
-            text = open(self._default_content_fn).read()
-        self.pt_edit(text, content_type)
+        self.pt_edit(text, content_type, encoding)
 
-    def _setPropValue(self, id, value):
-        PropertyManager._setPropValue(self, id, value)
-        self.ZCacheable_invalidate()
+    security.declareProtected(change_page_templates, 'pt_edit')
+    def pt_edit(self, text, content_type, encoding='utf-8'):
 
-    security = AccessControl.ClassSecurityInfo()
+        text = text.strip()
+        if self.strict and not isinstance(text, unicode):
+            text = unicode(text, encoding)
 
-    security.declareObjectProtected('View')
-    security.declareProtected('View', '__call__')
+        self.ZCacheable_invalidate()
+        PageTemplate.pt_edit(self, text, content_type)
 
-    security.declareProtected('View management screens',
-      'pt_editForm', 'manage_main', 'read',
-      'ZScriptHTML_tryForm', 'PrincipiaSearchSource',
-      'document_src', 'source_dot_xml')
+    security.declareProtected(change_page_templates, 'pt_editAction')
+    def pt_editAction(self, REQUEST, title, text, content_type, encoding, expand):
+        """Change the title and document."""
 
-    security.declareProtected('FTP access',
-      'manage_FTPstat','manage_FTPget','manage_FTPlist')
+        if self.wl_isLocked():
+            raise ResourceLockedError("File is locked via WebDAV")
 
-    pt_editForm = PageTemplateFile('www/ptEdit', globals(),
-                                   __name__='pt_editForm')
-    pt_editForm._owner = None
-    manage = manage_main = pt_editForm
+        self.expand = expand
+        self.pt_setTitle(title, encoding)
 
-    source_dot_xml = Src()
-
-    security.declareProtected('Change Page Templates',
-      'pt_editAction', 'pt_setTitle', 'pt_edit',
-      'pt_upload', 'pt_changePrefs')
-    def pt_editAction(self, REQUEST, title, text, content_type, expand):
-        """Change the title and document."""
-        if self.wl_isLocked():
-            raise ResourceLockedError, "File is locked via WebDAV"
-        self.expand=expand
-        self.pt_setTitle(title)
-        self.pt_edit(text, content_type)
+        self.pt_edit(text, content_type, encoding)
         REQUEST.set('text', self.read()) # May not equal 'text'!
         REQUEST.set('title', self.title)
         message = "Saved changes."
@@ -133,36 +161,45 @@
                        % '<br>'.join(self._v_warnings))
         return self.pt_editForm(manage_tabs_message=message)
 
-    def pt_setTitle(self, title):
-        charset = getattr(self, 'management_page_charset', None)
-        if type(title) == types.StringType and charset:
-            try:
-                title.decode('us-ascii')
-                title = str(title)
-            except UnicodeError:
-                title = unicode(title, charset)
-        elif type(title) != types.UnicodeType:
-            title = str(title)
+
+    security.declareProtected(change_page_templates, 'pt_setTitle')
+    def pt_setTitle(self, title, encoding='utf-8'):
+        if self.strict and not isinstance(title, unicode):
+            title = unicode(title, encoding)
         self._setPropValue('title', title)
 
-    def pt_upload(self, REQUEST, file='', charset=None):
+
+    def _setPropValue(self, id, value):
+        """ set a property and invalidate the cache """
+        PropertyManager._setPropValue(self, id, value)
+        self.ZCacheable_invalidate()
+
+
+    security.declareProtected(change_page_templates, 'pt_upload')
+    def pt_upload(self, REQUEST, file='', encoding='utf-8'):
         """Replace the document with the text in file."""
+
         if self.wl_isLocked():
-            raise ResourceLockedError, "File is locked via WebDAV"
+            raise ResourceLockedError("File is locked via WebDAV")
 
-        if type(file) is not StringType:
-            if not file: raise ValueError, 'File not specified'
-            file = file.read()
-        if charset:
-            try:
-                unicode(file, 'us-ascii')
-                file = str(file)
-            except UnicodeDecodeError:
-                file = unicode(file, charset)
-        self.write(file)
-        message = 'Saved changes.'
-        return self.pt_editForm(manage_tabs_message=message)
+        if isinstance(file, str):
+            filename = None
+            text = file
+        else:
+            if not file: 
+                raise ValueError('File not specified')
+            filename = file.filename
+            text = file.read()
 
+        content_type = guess_type(filename, text)   
+        if not content_type in ('text/html', 'text/xml'):
+            raise ValueError('Unsupported mimetype: %s' % content_type)
+
+        encoding = sniffEncoding(text, encoding)
+        self.pt_edit(text, content_type, encoding)
+        return self.pt_editForm(manage_tabs_message='Saved changes')
+
+    security.declareProtected(change_page_templates, 'pt_changePrefs')
     def pt_changePrefs(self, REQUEST, height=None, width=None,
                        dtpref_cols="100%", dtpref_rows="20"):
         """Change editing preferences."""
@@ -183,20 +220,20 @@
         setCookie("dtpref_rows", rows, path='/', expires=e)
         setCookie("dtpref_cols", cols, path='/', expires=e)
         REQUEST.other.update({"dtpref_cols":cols, "dtpref_rows":rows})
-        return self.manage_main()
+        return self.pt_editForm()
 
     def ZScriptHTML_tryParams(self):
         """Parameters to test the script with."""
         return []
 
-    def manage_historyCompare(self, rev1, rev2, REQUEST,
-                              historyComparisonResults=''):
-        return ZopePageTemplate.inheritedAttribute(
-            'manage_historyCompare')(
-            self, rev1, rev2, REQUEST,
-            historyComparisonResults=html_diff(rev1._text, rev2._text) )
+#    def manage_historyCompare(self, rev1, rev2, REQUEST,
+#                              historyComparisonResults=''):
+#        return ZopePageTemplate.inheritedAttribute(
+#            'manage_historyCompare')(
+#            self, rev1, rev2, REQUEST,
+#            historyComparisonResults=html_diff(rev1._text, rev2._text) )
 
-    def pt_getContext(self):
+    def pt_getContext(self, *args, **kw):
         root = self.getPhysicalRoot()
         context = self._getContext()
         c = {'template': self,
@@ -207,13 +244,12 @@
              'options': {},
              'root': root,
              'request': getattr(root, 'REQUEST', None),
-             'modules': SecureModuleImporter,
+             'modules': SecureModuleImporter(),
              }
         return c
 
-    def write(self, text):
-        self.ZCacheable_invalidate()
-        ZopePageTemplate.inheritedAttribute('write')(self, text)
+    security.declareProtected(view_management_screens, 'read',
+      'ZScriptHTML_tryForm')
 
     def _exec(self, bound_names, args, kw):
         """Call a Page Template"""
@@ -228,7 +264,7 @@
         except AttributeError:
             pass
 
-        security=getSecurityManager()
+        security = getSecurityManager()
         bound_names['user'] = security.getUser()
 
         # Retrieve the value from the cache.
@@ -244,8 +280,13 @@
 
         # Execute the template in a new security context.
         security.addContext(self)
+
         try:
-            result = self.pt_render(extra_context=bound_names)
+            # XXX: check the parameters for pt_render()! (aj)
+            result = self.pt_render(self.pt_getContext())
+        
+
+#            result = self.pt_render(extra_context=bound_names)
             if keyset is not None:
                 # Store the result in the cache.
                 self.ZCacheable_set(result, keywords=keyset)
@@ -253,37 +294,50 @@
         finally:
             security.removeContext(self)
 
-    security.declareProtected('Change Page Templates',
-      'PUT', 'manage_FTPput', 'write',
+    security.declareProtected(change_page_templates,
       'manage_historyCopy',
       'manage_beforeHistoryCopy', 'manage_afterHistoryCopy')
 
+    security.declareProtected(change_page_templates, 'PUT')
     def PUT(self, REQUEST, RESPONSE):
         """ Handle HTTP PUT requests """
         self.dav__init(REQUEST, RESPONSE)
         self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
-        self.write(REQUEST.get('BODY', ''))
+        ## XXX:this should be unicode or we must pass an encoding
+        self.pt_edit(REQUEST.get('BODY', ''))
         RESPONSE.setStatus(204)
         return RESPONSE
 
+    security.declareProtected(change_page_templates, 'manage_FTPput')
     manage_FTPput = PUT
 
+    security.declareProtected(ftp_access, 'manage_FTPstat','manage_FTPlist')
+
+    security.declareProtected(ftp_access, 'manage_FTPget')
     def manage_FTPget(self):
         "Get source for FTP download"
         self.REQUEST.RESPONSE.setHeader('Content-Type', self.content_type)
         return self.read()
 
+    security.declareProtected(view_management_screens, 'html')
+    def html(self):
+        return self.content_type == 'text/html'
+        
+    security.declareProtected(view_management_screens, 'get_size')
     def get_size(self):
         return len(self.read())
+
+    security.declareProtected(view_management_screens, 'getSize')
     getSize = get_size
 
+    security.declareProtected(view_management_screens, 'PrincipiaSearchSource')
     def PrincipiaSearchSource(self):
         "Support for searching - the document's contents are searched."
         return self.read()
 
+    security.declareProtected(view_management_screens, 'document_src')
     def document_src(self, REQUEST=None, RESPONSE=None):
         """Return expanded document source."""
-
         if RESPONSE is not None:
             RESPONSE.setHeader('Content-Type', 'text/plain')
         if REQUEST is not None and REQUEST.get('raw'):
@@ -302,10 +356,8 @@
                               'title': 'This template has an error'},)
         return icons
 
-    def __setstate__(self, state):
-        # This is here for backward compatibility. :-(
-        ZopePageTemplate.inheritedAttribute('__setstate__')(self, state)
 
+    security.declareProtected(view, 'pt_source_file')
     def pt_source_file(self):
         """Returns a file name to be compiled into the TAL code."""
         try:
@@ -315,53 +367,126 @@
             # acquisition context, so we don't know where it is. :-(
             return None
 
+    def wl_isLocked(self):
+        return 0
+
+    security.declareProtected(view, 'strictUnicode')
+    def strictUnicode(self):
+        """ Return True if the ZPT enforces the use of unicode,
+            False otherwise.
+        """
+        return self.strict
+
+
+    def manage_convertUnicode(self, preferred_encodings=preferred_encodings, RESPONSE=None):
+        """ convert non-unicode templates to unicode """
+
+        if not isinstance(self._text, unicode):
+
+            for encoding in preferred_encodings:
+                try:
+                    self._text = unicode(self._text, encoding)
+                    if RESPONSE:
+                        return RESPONSE.redirect(self.absolute_url() + '/pt_editForm?manage_tabs_message=ZPT+successfully+converted')
+                    else:
+                        return
+                except UnicodeDecodeError:
+                    pass
+
+            raise RuntimeError('Pagetemplate could not be converted to unicode')
+
+        else:
+            if RESPONSE:
+                return RESPONSE.redirect(self.absolute_url() + '/pt_editForm?manage_tabs_message=ZPT+already+converted')
+            else:
+                return
+
+
+    security.declareProtected(view_management_screens, 'getSource')
+    getSource = Src()
+    source_dot_xml = Src()
+
+InitializeClass(ZopePageTemplate)
+
+
 setattr(ZopePageTemplate, 'source.xml',  ZopePageTemplate.source_dot_xml)
 setattr(ZopePageTemplate, 'source.html', ZopePageTemplate.source_dot_xml)
 
-# Product registration and Add support
-manage_addPageTemplateForm = PageTemplateFile(
-    'www/ptAdd', globals(), __name__='manage_addPageTemplateForm')
 
-from urllib import quote
+def _newZPT(id, filename):
+    """ factory to generate ZPT instances from the file-system
+        based templates (basically for internal purposes)
+    """
+    zpt = ZopePageTemplate(id, open(filename).read(), 'text/html')
+    zpt.__name__= id
+    return zpt
 
-def manage_addPageTemplate(self, id, title=None, text=None,
-                           REQUEST=None, submit=None):
+class FSZPT(ZopePageTemplate):
+    """ factory to generate ZPT instances from the file-system
+        based templates (basically for internal purposes)
+    """
+
+    def __init__(self, id, filename):
+        ZopePageTemplate.__init__(self, id, open(filename).read(), 'text/html')
+        self.__name__= id
+
+InitializeClass(FSZPT)
+
+
+ZopePageTemplate.pt_editForm = FSZPT('pt_editForm', os.path.join(package_home(globals()),'pt', 'ptEdit.pt'))
+# this is scary, do we need this?
+ZopePageTemplate.manage = ZopePageTemplate.pt_editForm
+
+manage_addPageTemplateForm= FSZPT('manage_addPageTemplateForm', os.path.join(package_home(globals()), 'pt', 'ptAdd.pt'))
+
+def manage_addPageTemplate(self, id, title='', text='', encoding='utf-8', submit=None, REQUEST=None, RESPONSE=None):
     "Add a Page Template with optional file content."
 
-    id = str(id)
-    if REQUEST is None:
-        self._setObject(id, ZopePageTemplate(id, text))
-        ob = getattr(self, id)
-        if title:
-            ob.pt_setTitle(title)
-        return ob
-    else:
-        file = REQUEST.form.get('file')
+    filename = ''
+    content_type = 'text/html'
+
+    if REQUEST and REQUEST.has_key('file'):
+        file = REQUEST['file']
+        filename = file.filename
+        text = file.read()
         headers = getattr(file, 'headers', None)
-        if headers is None or not file.filename:
-            zpt = ZopePageTemplate(id, text) # collector 596
+        if headers and headers.has_key('content_type'):
+            content_type = headers['content_type']
         else:
-            zpt = ZopePageTemplate(id, file, headers.get('content_type'))
+            content_type = guess_type(filename, text) 
+        encoding = sniffEncoding(text, encoding)
 
-        self._setObject(id, zpt)
+    else:
+        if hasattr(text, 'read'):
+            filename = getattr(text, 'filename', '')
+            headers = getattr(text, 'headers', None)
+            text = text.read()
+            if headers and headers.has_key('content_type'):
+                content_type = headers['content_type']
+            else:
+                content_type = guess_type(filename, text) 
+        encoding = sniffEncoding(text, encoding)
 
-        # collector 596
-        if title:
-            ob = getattr(self, id)
-            ob.pt_setTitle(title)
+    if not text:
+        text = open(_default_content_fn).read()
+        encoding = 'utf-8'
+        content_type = 'text/html'
 
-        try:
-            u = self.DestinationURL()
-        except AttributeError:
-            u = REQUEST['URL1']
+    zpt = ZopePageTemplate(id, text, content_type, encoding)
+    zpt.pt_setTitle(title, encoding)
+    self._setObject(id, zpt)
+    zpt = getattr(self, id)
 
+    if RESPONSE:    
         if submit == " Add and Edit ":
-            u = "%s/%s" % (u, quote(id))
-        REQUEST.RESPONSE.redirect(u+'/manage_main')
-    return ''
+            RESPONSE.redirect(zpt.absolute_url() + '/pt_editForm')
+        else:
+            RESPONSE.redirect(self.absolute_url() + '/manage_main')
+    else:        
+        return zpt
 
 from Products.PageTemplates import misc_
-misc_['exclamation.gif'] = ImageFile('www/exclamation.gif', globals())
+misc_['exclamation.gif'] = ImageFile('pt/exclamation.gif', globals())
 
 def initialize(context):
     context.registerClass(
@@ -369,7 +494,7 @@
         permission='Add Page Templates',
         constructors=(manage_addPageTemplateForm,
                       manage_addPageTemplate),
-        icon='www/zpt.gif',
+        icon='pt/zpt.gif',
         )
     context.registerHelp()
     context.registerHelpTitle('Zope Help')

Added: Zope/trunk/lib/python/Products/PageTemplates/pt/default.html
===================================================================
--- Zope/trunk/lib/python/Products/PageTemplates/pt/default.html	2006-02-27 17:37:42 UTC (rev 65524)
+++ Zope/trunk/lib/python/Products/PageTemplates/pt/default.html	2006-02-27 17:46:20 UTC (rev 65525)
@@ -0,0 +1,13 @@
+<html>
+  <head>
+    <title tal:content="template/title">The title</title>
+  </head>
+  <body>
+    
+    <h2><span tal:replace="here/title_or_id">content title or id</span>
+        <span tal:condition="template/title"
+              tal:replace="template/title">optional template title</span></h2>
+
+    This is Page Template <em tal:content="template/id">template id</em>.
+  </body>
+</html>

Added: Zope/trunk/lib/python/Products/PageTemplates/pt/exclamation.gif
===================================================================
(Binary files differ)


Property changes on: Zope/trunk/lib/python/Products/PageTemplates/pt/exclamation.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: Zope/trunk/lib/python/Products/PageTemplates/pt/ptAdd.pt
===================================================================
--- Zope/trunk/lib/python/Products/PageTemplates/pt/ptAdd.pt	2006-02-27 17:37:42 UTC (rev 65524)
+++ Zope/trunk/lib/python/Products/PageTemplates/pt/ptAdd.pt	2006-02-27 17:46:20 UTC (rev 65525)
@@ -0,0 +1,62 @@
+<h1 tal:replace="structure here/manage_page_header">Header</h1>
+
+<h2 tal:define="form_title string:Add Page Template"
+    tal:replace="structure here/manage_form_title">Form Title</h2>
+
+<p class="form-help">
+Page Templates allow you to use simple HTML or XML attributes to
+create dynamic templates.  You may choose to upload the template text
+from a local file by typing the file name or using the <em>browse</em>
+button.
+</p>
+
+<form action="manage_addPageTemplate" method="post" 
+ enctype="multipart/form-data">
+<table cellspacing="0" cellpadding="2" border="0">
+  <tr>
+    <td align="left" valign="top">
+    <div class="form-label">
+    Id
+    </div>
+    </td>
+    <td align="left" valign="top">
+    <input type="text" name="id" size="40" />
+    </td>
+  </tr>
+  <tr>
+    <td align="left" valign="top">
+    <div class="form-optional">
+    File
+    </div>
+    </td>
+    <td align="left" valign="top">
+    <input type="file" name="file" size="25" value="" />
+    </td>
+  </tr>
+  <tr>
+    <td align="left" valign="top">
+    <div class="form-optional">
+    Encoding
+    </div>
+    </td>
+    <td align="left" valign="top">
+      <input type="text" name="encoding" size="25" value="utf-8" />
+      <em>(only used for non-XML and non-HTML content)</em>
+    </td>
+  </tr>
+  <tr>
+    <td align="left" valign="top">
+    </td>
+    <td align="left" valign="top">
+    <div class="form-element">
+    <input class="form-element" type="submit" name="submit" 
+     value=" Add " /> 
+    <input class="form-element" type="submit" name="submit" 
+     value=" Add and Edit " />
+    </div>
+    </td>
+  </tr>
+</table>
+</form>
+
+<h1 tal:replace="structure here/manage_page_footer">Footer</h1>

Added: Zope/trunk/lib/python/Products/PageTemplates/pt/ptEdit.pt
===================================================================
--- Zope/trunk/lib/python/Products/PageTemplates/pt/ptEdit.pt	2006-02-27 17:37:42 UTC (rev 65524)
+++ Zope/trunk/lib/python/Products/PageTemplates/pt/ptEdit.pt	2006-02-27 17:46:20 UTC (rev 65525)
@@ -0,0 +1,156 @@
+
+<h1 tal:replace="structure python: context.manage_page_header(management_page_charset='utf-8')">Header</h1>
+<h2 tal:define="manage_tabs_message options/manage_tabs_message | nothing"
+    tal:replace="structure context/manage_tabs">Tabs</h2>
+
+<tal:block define="global body request/other/text | request/form/text
+| context/read" /> 
+<form action="" method="post" tal:attributes="action request/URL1">
+<input type="hidden" name=":default_method" value="pt_changePrefs">
+<input type="hidden" name="encoding" value="utf-8"/>
+<table width="100%" cellspacing="0" cellpadding="2" border="0">
+  <tr>
+    <td align="left" valign="middle">
+    <div class="form-optional">
+    Title
+    </div>
+    </td>
+    <td align="left" valign="middle">
+    <input type="text" name="title" size="40" 
+           tal:attributes="value request/title | context/title" />
+    </td>
+    <td align="left" valign="middle">
+    <div class="form-label"> Last Modified </div>
+    </td>
+    <td align="left" valign="middle">
+      <div class="form-text" 
+       tal:content="python:context.bobobase_modification_time().strftime('%Y-%m-%d %I:%M %p')">1/1/2000
+      </div>
+    </td>
+  </tr>
+  <tr>
+    <td align="left" valign="middle">
+    <div class="form-label">
+    Content-Type
+    </div>
+    </td>
+    <td align="left" valign="middle">
+      <select name="content_type" size="1" tal:define="ct context/content_type">
+        <option value="text/html" tal:attributes="SELECTED python: ct == 'text/html'">text/html</option>
+        <option value="text/xml" tal:attributes="SELECTED python: ct == 'text/xml'">text/xml</option>
+      </select>
+    </td>
+    <td align="left" valign="top" colspan=2>
+      <a href="source.html" tal:condition="context/html">Browse HTML source</a>
+      <a href="source.xml" tal:condition="not:context/html">Browse XML source</a>
+      <br>
+      <input type="hidden" name="expand:int:default" value="0">
+      <input type="checkbox" value="1" name="expand:int"
+       tal:attributes="checked request/expand | context/expand">
+      Expand macros when editing
+    </td>
+  </tr>
+
+
+  <!-- XXX: check if 'None' is a proper argument for 'namespace' -->
+  <tr tal:define="errors python: context.pt_errors(None)" tal:condition="errors">
+    <tal:block define="global body python:context.document_src({'raw':1})"/>
+    <td align="left" valign="middle" class="form-label">Errors</td>
+    <td align="left" valign="middle" style="background-color: #FFDDDD"
+    colspan="3">
+<pre tal:content="python: '\n'.join(errors)">errors</pre>
+    </td>
+  </tr>
+
+  <tr tal:define="warnings context/pt_warnings" tal:condition="warnings">
+    <td align="left" valign="middle" class="form-label">Warnings</td>
+    <td align="left" valign="middle" style="background-color: #FFEEDD"
+     colspan="3">
+<pre tal:content="python: '\n'.join(warnings)">errors</pre>
+    </td>
+  </tr>
+
+
+
+  <tr>
+    <td align="left" valign="top" colspan="4"
+      tal:define="width request/dtpref_cols | string:100%;
+                  relative_width python:str(width).endswith('%')">
+      <textarea name="text:text" wrap="off" style="width: 100%;" rows="20"
+        tal:condition="relative_width"
+        tal:attributes="style string:width: $width;;;
+                        rows request/dtpref_rows | default"
+        tal:content="body">Template Body</textarea>
+      <textarea name="text:text" wrap="off" rows="20" cols="50"
+        tal:condition="not:relative_width"
+        tal:attributes="cols width; rows request/dtpref_rows | default"
+        tal:content="body">Template Body</textarea>
+    </td>
+  </tr>
+
+<tr>
+  <td align="left" valign="top" colspan="4">
+  <div class="form-element">
+    <em tal:condition="context/wl_isLocked">Locked by WebDAV</em>
+    <input tal:condition="not:context/wl_isLocked"
+     class="form-element" type="submit" 
+     name="pt_editAction:method" value="Save Changes">
+  &nbsp;&nbsp;
+  <input class="form-element" type="submit" name="height" value="Taller">
+  <input class="form-element" type="submit" name="height" value="Shorter">
+  <input class="form-element" type="submit" name="width" value="Wider">
+  <input class="form-element" type="submit" name="width" value="Narrower">
+  </div>
+  </td>
+</tr>
+</table>
+</form>
+
+<p class="form-help">
+You can upload the text for <span tal:replace="context/title_and_id" />
+using the following form.
+Choose an existing HTML or XML file from your local computer by clicking
+<em>browse</em>.  You can also <a href="document_src">click context</a>
+to view or download the current text.
+</p>
+
+<form action="pt_upload" method="post" 
+ enctype="multipart/form-data">
+<table cellpadding="2" cellspacing="0" border="0">
+<tr>
+  <td align="left" valign="top">
+  <div class="form-label">
+  File &nbsp;
+  </div>
+  </td>
+  <td align="left" valign="top">
+  <input type="file" name="file" size="40" value="">
+  </td>
+</tr>
+<tr>
+  <td align="left" valign="top">
+    <div class="form-label">
+      Encoding &nbsp;
+    </div>
+  </td>
+  <td align="left" valign="top" colspan="2">
+    <input name="encoding" value="utf-8"/>
+  </td>
+  <td align="left" valign="top" colspan="1">
+    <em>(only used for non-XML and non-XHTML content)</em>
+  </td>
+</tr>
+<tr>
+  <td></td>
+  <td align="left" valign="top">
+  <div class="form-element">
+    <em tal:condition="context/wl_isLocked">Locked by WebDAV</em>
+    <input tal:condition="not:context/wl_isLocked"
+    class="form-element" type="submit" value="Upload File">
+  </div>
+  </td>
+</tr>
+</table>
+</form>
+
+<h1 tal:replace="structure context/manage_page_footer">Footer</h1>

Added: Zope/trunk/lib/python/Products/PageTemplates/pt/zpt.gif
===================================================================
(Binary files differ)


Property changes on: Zope/trunk/lib/python/Products/PageTemplates/pt/zpt.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: Zope/trunk/lib/python/Products/PageTemplates/tests/testZopePageTemplate.py
===================================================================
--- Zope/trunk/lib/python/Products/PageTemplates/tests/testZopePageTemplate.py	2006-02-27 17:37:42 UTC (rev 65524)
+++ Zope/trunk/lib/python/Products/PageTemplates/tests/testZopePageTemplate.py	2006-02-27 17:46:20 UTC (rev 65525)
@@ -12,6 +12,7 @@
 import transaction
 
 from Testing.makerequest import makerequest
+from Products.PageTemplates.ZopePageTemplate import _default_content_fn
 
 class ZPTRegressions(unittest.TestCase):
 
@@ -34,9 +35,9 @@
 
     def testAddWithoutParams(self):
         pt = self._addPT('pt1')
-        default_text = open(pt._default_content_fn).read()
+        default_text = open(_default_content_fn).read()
         self.assertEqual(pt.title, '')
-        self.assertEqual(pt.document_src(), default_text)
+        self.assertEqual(pt.document_src().strip(), default_text.strip())
 
     def testAddWithRequest(self):
         """Test manage_add with file"""



More information about the Zope-Checkins mailing list