Commit a036a0a6 authored by Casey Duncan's avatar Casey Duncan

Merging death (to index_html). Sorry about the previous noise. Note that the

new settings tab will have more stuff under it before 2.6 ships.
parent 7589c122
......@@ -12,7 +12,7 @@
##############################################################################
"""Access control package"""
__version__='$Revision: 1.168 $'[11:-2]
__version__='$Revision: 1.169 $'[11:-2]
import Globals, socket, SpecialUsers,re
import os
......@@ -720,7 +720,7 @@ class BasicUserFolder(Implicit, Persistent, Navigation, Tabs, RoleManager,
c is the physical container of the object
"""
if len(request.steps) == 0: # someone deleted root index_html
request.RESPONSE.notFoundError('no default view (root index_html'
request.RESPONSE.notFoundError('no default view (root default view'
' was probably deleted)')
n = request.steps[-1]
# default to accessed and container as v.aq_parent
......
......@@ -12,11 +12,11 @@
##############################################################################
__doc__='''Application support
$Id: Application.py,v 1.180 2002/02/07 17:20:59 andreasjung Exp $'''
__version__='$Revision: 1.180 $'[11:-2]
$Id: Application.py,v 1.181 2002/03/27 21:51:03 caseman Exp $'''
__version__='$Revision: 1.181 $'[11:-2]
import Globals,Folder,os,sys,App.Product, App.ProductRegistry, misc_
import time, traceback, os, Products
import time, traceback, os, Products, ObjectManager
from DateTime import DateTime
from AccessControl.User import UserFolder
from App.ApplicationManager import ApplicationManager
......@@ -59,6 +59,9 @@ class Application(Globals.ApplicationDefaultPermissions,
__allow_groups__=UserFolder()
# Set the universal default method to index_html
_object_manager_browser_default_id = 'index_html'
def title_and_id(self): return self.title
def title_or_id(self): return self.title
......@@ -700,6 +703,11 @@ def install_product(app, product_dir, product_name, meta_types,
raise
def install_standards(app):
# Check to see if we've already done this before
# Don't do it twice (Casey)
if getattr(app, '_standard_objects_have_been_added', 0):
return
# Install the replaceable standard objects
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
std_dir = os.path.join(Globals.package_home(globals()), 'standard')
......@@ -722,9 +730,11 @@ def install_standards(app):
else:
continue
wrote = 1
ob.__replaceable__ = Globals.REPLACEABLE
setattr(Application, fn, ob)
# Below is icky and sneaky since it makes these impossible to delete
#ob.__replaceable__ = Globals.REPLACEABLE
#setattr(Application, fn, ob)
if wrote:
app._standard_objects_have_been_added = 1
get_transaction().note('Installed standard objects')
get_transaction().commit()
......
......@@ -15,9 +15,9 @@
Folders are the basic container objects and are analogous to directories.
$Id: Folder.py,v 1.97 2001/11/28 15:50:57 matt Exp $"""
$Id: Folder.py,v 1.98 2002/03/27 21:51:03 caseman Exp $"""
__version__='$Revision: 1.97 $'[11:-2]
__version__='$Revision: 1.98 $'[11:-2]
import Globals, SimpleItem, ObjectManager, PropertyManager
import AccessControl.Role, webdav.Collection, FindSupport
......@@ -45,6 +45,9 @@ def manage_addFolder(self, id, title='',
ob.title=title
self._setObject(id, ob)
ob=self._getOb(id)
# Acquire browser_default from parent
ob.setBrowserDefaultId(acquire=1)
checkPermission=getSecurityManager().checkPermission
......@@ -61,7 +64,7 @@ def manage_addFolder(self, id, title='',
'You are not authorized to add Page Templates.'
)
ob.manage_addProduct['PageTemplates'].manage_addPageTemplate(
id='index_html', title='')
id=ob.getBrowserDefaultId(acquire=1), title='')
if REQUEST is not None:
return self.manage_main(self, REQUEST, update_menu=1)
......@@ -87,9 +90,9 @@ class Folder(
_properties=({'id':'title', 'type': 'string'},)
manage_options=(
(ObjectManager.ObjectManager.manage_options[0],)+
ObjectManager.ObjectManager.manage_options+
(
{'label':'View', 'action':'index_html',
{'label':'View', 'action':'',
'help':('OFSP','Folder_View.stx')},
)+
PropertyManager.PropertyManager.manage_options+
......
......@@ -12,19 +12,21 @@
##############################################################################
__doc__="""Object Manager
$Id: ObjectManager.py,v 1.147 2002/02/13 15:27:48 andreasjung Exp $"""
$Id: ObjectManager.py,v 1.148 2002/03/27 21:51:03 caseman Exp $"""
__version__='$Revision: 1.147 $'[11:-2]
__version__='$Revision: 1.148 $'[11:-2]
import App.Management, Acquisition, Globals, CopySupport, Products
import os, App.FactoryDispatcher, re, Products
from OFS.Traversable import Traversable
from OFS import SimpleItem
from Globals import DTMLFile, Persistent
from Globals import MessageDialog, default__class_init__
from Globals import REPLACEABLE, NOT_REPLACEABLE, UNIQUE
from webdav.NullResource import NullResource
from webdav.Collection import Collection
from Acquisition import aq_base
from AccessControl.SecurityInfo import ClassSecurityInfo
from urllib import quote
from cStringIO import StringIO
import marshal
......@@ -82,6 +84,23 @@ def checkValidId(self, id, allow_dup=0):
'The id "%s" contains characters illegal in URLs.' % id
)
class BrowserDefault(Acquisition.Implicit, Persistent):
"""Callable default browser object for object managers. This is made as a
class so that folderish objs not overriding browser_default can simply
not define it. We also define this class as replaceable so that TTW
scripts can override it
"""
security = ClassSecurityInfo()
__replaceable__ = REPLACEABLE # Allow this to be overridden in instances
def __call__(self, request):
"""Return the proper default method name to be published
This name is acquired from the parent object"""
return self.aq_parent, \
(self.aq_acquire('_object_manager_browser_default_id'),)
default__class_init__(BrowserDefault)
class BeforeDeleteException( Exception ): pass # raise to veto deletion
class BreakoutException ( Exception ): pass # raised to break out of loops
......@@ -113,6 +132,11 @@ class ObjectManager(
('manage_importObject','manage_importExportForm',
'manage_exportObject')
),
('View', ('getBrowserDefaultId',)),
('Manage folderish settings',
('manage_settings', 'setBrowserDefaultId',
'isBrowserDefaultAcquired','hasCustomBrowserDefault')
),
)
......@@ -124,12 +148,12 @@ class ObjectManager(
manage_main=DTMLFile('dtml/main', globals())
manage_index_main=DTMLFile('dtml/index_main', globals())
manage_settings=DTMLFile('dtml/objectManagerSettings', globals())
manage_options=(
{'label':'Contents', 'action':'manage_main',
'help':('OFSP','ObjectManager_Contents.stx')},
# {'label':'Import/Export', 'action':'manage_importExportForm',
# 'help':('OFSP','ObjectManager_Import-Export.stx')},
{'label':'Settings', 'action':'manage_settings'},
)
isAnObjectManager=1
......@@ -199,7 +223,6 @@ class ObjectManager(
self.aq_acquire('_getProductRegistryData')('ac_permissions')
)
def filtered_meta_types(self, user=None):
# Return a list of the types for which the user has
# adequate permission to add that type of object.
......@@ -642,6 +665,72 @@ class ObjectManager(
return NullResource(self, key, request).__of__(self)
raise KeyError, key
#######################################################################
# Death to index_html implementation (casey)
def setBrowserDefaultId(self, id='', acquire=0, REQUEST=None):
"""Set the id of the browser_default method. If acquire is true
then the local browser_default is cleared and the setting is
acquired
"""
if self.hasCustomBrowserDefault():
# If a custom browser default is installed, don't override it
raise BadRequestException, \
'Cannot override custom browser default'
if acquire:
try:
del self._object_manager_browser_default_id
except (AttributeError, KeyError):
pass # If its already gone, so be it
id = self.aq_acquire('_object_manager_browser_default_id')
else:
self._checkId(id, allow_dup=1)
self._object_manager_browser_default_id = id
if id == 'index_html':
# This is a small optimization since the publisher stills falls
# back on this default value if there is no browser_default
# method at all for bw compatibility
try:
del self.browser_default
except (AttributeError, KeyError):
pass
else:
# Create a browser_default callable
self.browser_default = BrowserDefault()
if REQUEST:
REQUEST.RESPONSE.redirect(REQUEST.URL1 +
'/manage_settings?manage_tabs_message=Settings+Changed')
def getBrowserDefaultId(self, acquire=0):
"""Get the id of the browser_default method. If acquire is true
then the acquired value is returned if there is no local setting,
otherwise None is returned. None is also returned if
browser_default has been overidden in this (or a higher) instance
using a custom callable.
"""
if self.hasCustomBrowserDefault():
return None
if acquire:
return self.aq_acquire('_object_manager_browser_default_id')
else:
return getattr(self, '_object_manager_browser_default_id', None)
def isBrowserDefaultAcquired(self):
"""Return true if the current browser default is being acquired"""
return not hasattr(self, '_object_manager_browser_default_id')
def hasCustomBrowserDefault(self):
"""Return true if a custom browser_default object has been
installed
"""
try:
return getattr(self.browser_default, '__class__', None) \
is not BrowserDefault
except AttributeError:
return 0
def findChilds(obj,dirname=''):
""" recursive walk through the object hierarchy to
......
<dtml-var manage_page_header>
<dtml-var manage_tabs>
<p class="form-help">
Use this form to change the behavior of this container
and its subordinates.
</p>
<dtml-unless name="hasCustomBrowserDefault">
<form action="setBrowserDefaultId" method="post">
<table width="100%" cellspacing="0" cellpadding="2" border="0">
<tr class="section-bar">
<td>
<div class="form-label">
Browser Default Id
</div>
</td>
</tr>
<tr><td>
<div class="form-help">
Enter the id of object used as the default presentation
<dtml-unless isTopLevelPrincipiaApplicationObject>
or select the checkbox to acquire this setting
from the parent container.
</dtml-unless>
Note that creating a custom callable browser_default
object in this folder will supercede this setting.
</div>
</td></tr>
<tr><td>
<span class="form-label">Browser Default Id</span>
<input class="form-element" type="text" name="id"
size="20" value="&dtml.null-getBrowserDefaultId;"
<dtml-unless isTopLevelPrincipiaApplicationObject>
onchange="if(this.value!='') this.form.acquire.checked=false"
</dtml-unless>
/>
<dtml-unless isTopLevelPrincipiaApplicationObject>
&nbsp;&nbsp;
<input class="form-element" type="checkbox"
name="acquire" id="acquire" value="1"
onclick="if(this.checked) this.form.id.value=''"
<dtml-if name="isBrowserDefaultAcquired">
checked
</dtml-if>
/>
<label class="form-text" for="acquire">
Acquire this setting
</label>
</dtml-unless>
</td></tr>
<tr><td>&nbsp;</td></tr>
<tr><td>
<input class="form-element" type="submit" value="Save Changes" />
</td></tr>
</table>
</form>
</dtml-unless>
<dtml-var manage_page_footer>
# Added to test new ObjectManager functions
# for death to index_html implementation
# Not really a complete test suite for OM yet -Casey
import os, sys, unittest
import string, cStringIO, re
import ZODB, Acquisition
from OFS.Application import Application
from OFS.Folder import manage_addFolder
from OFS.Image import manage_addFile
from OFS.ObjectManager import BadRequestException
from Testing.makerequest import makerequest
from webdav.common import rfc1123_date
from AccessControl import SecurityManager
from AccessControl.SecurityManagement import newSecurityManager
from AccessControl.SecurityManagement import noSecurityManager
from mimetools import Message
from multifile import MultiFile
class UnitTestSecurityPolicy:
"""
Stub out the existing security policy for unit testing purposes.
"""
#
# Standard SecurityPolicy interface
#
def validate( self
, accessed=None
, container=None
, name=None
, value=None
, context=None
, roles=None
, *args
, **kw):
return 1
def checkPermission( self, permission, object, context) :
return 1
class UnitTestUser( Acquisition.Implicit ):
"""
Stubbed out manager for unit testing purposes.
"""
def getId( self ):
return 'unit_tester'
getUserName = getId
def allowed( self, object, object_roles=None ):
return 1
def makeConnection():
import ZODB
from ZODB.DemoStorage import DemoStorage
s = DemoStorage(quota=(1<<20))
return ZODB.DB( s ).open()
def test_browser_default(self, request):
return self, ('foo.html',)
class TestObjectManager( unittest.TestCase ):
def setUp( self ):
self.connection = makeConnection()
try:
r = self.connection.root()
a = Application()
a.manage_addFolder = manage_addFolder
r['Application'] = a
self.root = a
responseOut = self.responseOut = cStringIO.StringIO()
self.app = makerequest( self.root, stdout=responseOut )
manage_addFolder( self.app, 'folder1' )
self.folder1 = folder1 = getattr( self.app, 'folder1' )
manage_addFolder( folder1, 'folder2' )
self.folder2 = folder2 = getattr( folder1, 'folder2' )
folder1.all_meta_types = folder2.all_meta_types = \
( { 'name' : 'File'
, 'action' : 'manage_addFile'
, 'permission' : 'Add images and files'
},
{ 'name':'Some Folderish',
'action':'manage_addFolder',
'permission':'Add Some Folderish'
},
{ 'name':'Folder',
'action':'manage_addFolder',
'permission':'Add Folders' }
)
manage_addFile( folder1, 'other_html'
, file='', content_type='text/plain')
manage_addFile( folder1, 'index_html'
, file='', content_type='text/plain')
# Hack, we need a _p_mtime for the file, so we make sure that it
# has one. We use a subtransaction, which means we can rollback
# later and pretend we didn't touch the ZODB.
get_transaction().commit()
except:
self.connection.close()
raise
get_transaction().begin()
self.policy = UnitTestSecurityPolicy()
self.oldPolicy = SecurityManager.setSecurityPolicy( self.policy )
newSecurityManager( None, UnitTestUser().__of__( self.root ) )
def tearDown( self ):
noSecurityManager()
SecurityManager.setSecurityPolicy( self.oldPolicy )
del self.oldPolicy
del self.policy
del self.folder2
del self.folder1
get_transaction().abort()
self.app._p_jar.sync()
self.connection.close()
del self.app
del self.responseOut
del self.root
del self.connection
def testSetBrowserDefaultBogus( self ):
# try to change it to an invalid id
try:
self.folder1.setBrowserDefaultId('_bogus')
self.fail()
except BadRequestException:
pass
# Try to override a custom browser_default
try:
self.folder1.browser_default = test_browser_default
self.folder1.setBrowserDefaultId('index_html')
self.fail()
except BadRequestException:
del self.folder1.browser_default
def testBrowserDefault( self ):
# Test setting and acquisition of setting
self.failUnless( self.folder1.isBrowserDefaultAcquired() )
self.folder1.setBrowserDefaultId('other_html')
self.failIf( self.folder1.isBrowserDefaultAcquired() )
self.assertEqual( self.folder1.getBrowserDefaultId(), 'other_html')
self.assertEqual( self.folder2.getBrowserDefaultId(), None )
self.assertEqual( self.folder2.getBrowserDefaultId(1), 'other_html' )
self.folder1.setBrowserDefaultId(acquire=1)
self.failUnless( self.folder1.isBrowserDefaultAcquired() )
self.assertEqual( self.folder1.getBrowserDefaultId(), None )
default = self.root.getBrowserDefaultId()
self.assertEqual( self.folder1.getBrowserDefaultId(1), default )
self.assertEqual( self.folder2.getBrowserDefaultId(1), default )
def test_suite():
suite = unittest.TestSuite()
suite.addTest( unittest.makeSuite( TestObjectManager ) )
return suite
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
main()
......@@ -131,8 +131,8 @@ class ObjectManager:
def __getitem__(id):
"""
Returns a child object given a child id. If there is no child
with the given id, returns None. This method makes it easy to
refer to children that have id with file extensions. For
with the given id, a KeyError is raised. This method makes it easy
to refer to children that have id with file extensions. For
example::
page=folder['index.html']
......@@ -148,3 +148,23 @@ class ObjectManager:
Permission -- 'Access contents information'
"""
def setBrowserDefaultId(id='', acquire=0):
"""
Sets the id of the object or method used as the default method when
the object manager is published. If acquire is set then the default
method id will be acquired from the parent container.
Permission -- 'Manage folderish settings'
"""
def getBrowserDefaultId(acquire=0):
"""
Returns the id of the object or method used as the default when the
object manager is published. By default, this setting is acquired. If
the acquire argument is true, then the return value will be acquired
from the parent if it is not set locally. Otherwise, None is returned
if the default id is not set on this object manager.
Permission -- 'View'
"""
......@@ -10,7 +10,7 @@
# FOR A PARTICULAR PURPOSE
#
##############################################################################
__version__='$Revision: 1.46 $'[11:-2]
__version__='$Revision: 1.47 $'[11:-2]
from urllib import quote
......@@ -196,17 +196,19 @@ class BaseRequest:
# How did this request come in? (HTTP GET, PUT, POST, etc.)
method=req_method=request_get('REQUEST_METHOD', 'GET').upper()
no_acquire_flag=0
# Set the default method
if method=='GET' or method=='POST':
method='index_html'
# Probably a browser
no_acquire_flag=0
# index_html is still the default method, only any object can
# override it by implementing its own browser_default method
method = 'index_html'
elif self.maybe_webdav_client:
# Probably a WebDAV client.
no_acquire_flag=1
else:
if self.maybe_webdav_client:
# Probably a WebDAV client.
no_acquire_flag=1
URL=request['URL']
no_acquire_flag=0
URL=request['URL']
parents=request['PARENTS']
object=parents[-1]
del parents[:]
......@@ -250,6 +252,24 @@ class BaseRequest:
# Check for method:
if path:
entry_name = path.pop()
elif hasattr(getattr(object, 'aq_base', object),
'browser_default'):
# If we have reached the end of the path. We look to see
# if the object implements browser_default. If so, we
# call it to let the object tell us how to publish it
# browser_default returns the object to be published
# (usually self) and a sequence of names to traverse to
# find the method to be published. (Casey)
request._hacked_path=1
object, default_path = object.browser_default(request)
if len(default_path) > 1:
path = list(default_path)
method = path.pop()
request['TraversalRequestNameStack'] = path
continue
else:
method = default_path[0]
entry_name = method
elif (method and hasattr(object,method)
and entry_name != method
and getattr(object, method) is not None):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment