This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
glasnost/shared/web/ObjectsWeb.py

1112 lines
41 KiB
Python

# -*- coding: iso-8859-15 -*-
# Glasnost
# By: Odile Bénassy <obenassy@entrouvert.com>
# Romain Chantereau <rchantereau@entrouvert.com>
# Nicolas Clapiès <nclapies@easter-eggs.org>
# Pierre-Antoine Dejace <padejace@entrouvert.be>
# Thierry Dulieu <tdulieu@easter-eggs.com>
# Florent Monnier <monnier@codelutin.com>
# Cédric Musso <cmusso@easter-eggs.org>
# Frédéric Péters <fpeters@entrouvert.be>
# Benjamin Poussin <poussin@codelutin.com>
# Emmanuel Raviart <eraviart@entrouvert.com>
# Sébastien Régnier <regnier@codelutin.com>
# Emmanuel Saracco <esaracco@easter-eggs.com>
#
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
# Emmanuel Saracco & Théridion
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
# Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
# Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
# Régnier, Emmanuel Saracco, Théridion & Vecam
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
__doc__ = """Glasnost Objects Web"""
__version__ = '$Revision$'[11:-2]
import md5
import time
import types
import glasnost.common.context as context
import glasnost.common.faults as faults
import glasnost.common.slots as slots
import glasnost.common.system as system
import glasnost.common.translation as translation
import glasnost.common.tools_new as commonTools
import glasnost.common.xhtmlgenerator as X
from glasnost.proxy.DispatcherProxy import MultiCall
import kinds # Do not remove!
import things
from tools import *
import WebAPI
register = things.register
class BaseObjectWebMixin(things.ThingMixin):
id_kind_stateInEditMode = 'hidden'
id_kind_stateInViewMode = 'hidden'
id_kind_widget_fieldLabel = N_('ID')
id_kind_widgetName = 'InputText'
serverRole_kind_stateInEditMode = 'hidden'
serverRole_kind_stateInViewMode = 'hidden'
version_kind_defaultValue = 0
version_kind_stateInEditMode = 'hidden'
version_kind_stateInViewMode = 'hidden'
version_kind_widget_fieldLabel = N_('Version Number')
version_kind_widgetName = 'InputText'
def getEmbeddedViewLayout(self):
fields = {}
self.makeFieldsFromInstance(fields)
self.repairFields(fields)
return self.getCompactViewLayout(fields, parentSlot = None)
def getLabelTranslated(self, destinationLanguages = None, multiCall = None):
translationsProxy = getProxyForServerRole('translations')
if translationsProxy:
if not destinationLanguages:
destinationLanguages = context.getVar('destinationLanguages')
try:
return translationsProxy.getTranslation(
self.getLabel(), self.getId(), 'self.getLabel()',
self.getLabelLanguage(), destinationLanguages,
multiCall = multiCall)
except faults.UnknownStringDigest:
return self.getLabel()
else:
return self.getLabel()
def getSlotToModifyNames(self, parentSlot = None):
return None # Modify all slots.
def getViewLayoutSlotNames(self, fields, parentSlot = None):
slotNames = things.ThingMixin.getViewLayoutSlotNames(
self, fields, parentSlot = parentSlot)
userToken = context.getVar('userToken', default = '')
if context.getVar('useCompactLayout', default = 0) or (
self.id and not self.getWeb().canModifyObject(self.id)):
slotNames = slotNames[:]
for slotName in ('language',):
if slotName in slotNames:
slotNames.remove(slotName)
return slotNames
def getWeb(self):
return getWebForServerRole(self.serverRole)
def makeContentTitle(self, contentSlot, contentLabel):
return contentLabel
def newWidget(self, parentSlot = None):
return commonTools.newThing('widget', 'Thing')
class AdminWithoutWritersMixin(BaseObjectWebMixin):
adminsSet_kind_widget_fieldLabel = N_('Administrators')
def newWidget(self, parentSlot = None):
return commonTools.newThing('widget', 'Thing')
class AdminMixin(AdminWithoutWritersMixin):
readersSet_kind_itemKind_value_defaultValue = system.generalPublicId
writersSet_kind_itemKind_value_defaultValue = None
class ObjectWebMixin(BaseObjectWebMixin):
addToId = None
addToId_kind_stateInEditMode = 'read-only'
addToId_kind_widget_fieldLabel = N_('Added to')
addToId_kind_widgetName = 'SelectId'
addToId_kindName = 'Id'
addToSlot = None
addToSlot_kind_stateInEditMode = 'hidden'
addToSlot_kind_stateInViewMode = 'hidden'
addToSlot_kind_widget_fieldLabel = N_('Added to slot')
addToSlot_kindName = 'String'
def getViewLayoutSlotNames(self, fields, parentSlot = None):
slotNames = BaseObjectWebMixin.getViewLayoutSlotNames(
self, fields, parentSlot = parentSlot)
if 'addToId' in slotNames:
slotNames.remove('addToId')
if 'addToSlot' in slotNames:
slotNames.remove('addToSlot')
return slotNames
def getEditLayoutSlotNames(self, fields, parentSlot = None):
slotNames = BaseObjectWebMixin.getEditLayoutSlotNames(
self, fields, parentSlot = parentSlot)
if 'addToId' in slotNames:
slotNames.remove('addToId')
if 'addToSlot' in slotNames:
slotNames.remove('addToSlot')
if fields.has_key('addToId') and fields['addToId'] and \
not (fields.has_key('id') and fields['id']):
slotNames.insert(0, 'addToId')
slotNames.insert(0, 'addToSlot')
return slotNames
class WebMixin(things.ThingMixin):
thingCategory = 'web'
class ObjectsWebMixin(WebMixin):
def admin(self):
context.push(_level = 'admin',
defaultDispatcherId = context.getVar('dispatcherId'))
try:
if not self.canGetAdmin():
return accessForbidden()
admin = self.getAdmin()
keywords = {}
admin.makeFieldsFromInstance(keywords)
admin.repairFields(keywords)
layout = X.array()
layout += admin.getViewLayout(keywords)
buttonsBar = X.div(_class = 'buttons-bar')
layout += buttonsBar
navigationButtonsBar = X.span(_class = 'navigation-buttons-bar')
buttonsBar += navigationButtonsBar
navigationButtonsBar += X.buttonStandalone(
'view-list', X.actionUrl())
if self.canModifyAdmin():
actionButtonsBar = X.span(_class = 'action-buttons-bar')
buttonsBar += actionButtonsBar
actionButtonsBar += X.buttonStandalone(
'edit', X.actionUrl('adminEdit'))
finally:
context.pull(_level = 'admin')
return writePageLayout(
layout,_('%s Settings') % _(self.objectsNameCapitalized))
admin.isPublicForWeb = 1
def adminEdit(self, again = '', error = '', **keywords):
context.push(_level = 'adminEdit',
defaultDispatcherId = context.getVar('dispatcherId'),
layoutMode = 'edit')
try:
if keywords is None:
keywords = {}
if not self.isAdmin():
return accessForbidden()
admin = self.getAdmin()
if not again:
admin.makeFieldsFromInstance(keywords)
admin.repairFields(keywords)
layout = X.array()
layout += admin.getErrorLayout(error, keywords)
form = X.form(
action = X.actionUrl('adminSubmit'),
enctype= 'multipart/form-data', method = 'post')
layout += form
form += admin.getEditLayout(keywords)
buttonsBar = X.div(_class = 'buttons-bar')
form += buttonsBar
actionButtonsBar = X.span(_class = 'action-buttons-bar')
buttonsBar += actionButtonsBar
actionButtonsBar += X.buttonInForm('modify', 'modifyButton')
finally:
context.pull(_level = 'adminEdit')
return writePageLayout(layout, _('Editing %s Settings') \
% _(self.objectsNameCapitalized))
adminEdit.isPublicForWeb = 1
def adminSubmit(self, **keywords):
uri = None
context.push(_level = 'adminSubmit',
defaultDispatcherId = context.getVar('dispatcherId'))
try:
if keywords is None:
keywords = {}
if not self.isAdmin():
return accessForbidden()
admin = self.getAdmin()
if isButtonSelected('applyButton', keywords):
keywords['again'] = '1'
keywords['hideErrors'] = '1'
admin = self.newAdmin(keywords)
admin.submitFields(keywords)
if keywords.has_key('again') and keywords['again']:
uri = X.actionUrl('adminEdit')
uri.addKeywords(keywords)
return # The redirect(uri) will be returned by the finally
# instruction.
try:
self.modifyAdmin(admin)
except faults.WrongVersion:
keywords['again'] = '1'
keywords['error'] = '1'
keywords['versionError'] = '1'
uri = X.actionUrl('adminEdit')
uri.addKeywords(keywords)
return # The redirect(uri) will be returned by the finally
# instruction.
except:
if context.getVar('debug'):
raise
return accessForbidden()
uri = X.actionUrl('admin')
# The redirect(uri) will be returned by the finally instruction.
finally:
context.pull(_level = 'adminSubmit')
if uri:
return redirect(uri)
adminSubmit.isPublicForWeb = 1
def clone(self, id):
if not id or not self.hasObject(id):
return pageNotFound()
if not self.canCloneObject(id):
return accessForbidden()
object = self.getObject(id)
keywords = {}
object.makeFieldsFromInstance(keywords)
del keywords['id']
keywords['again'] = 1
keywords['cloned'] = 1
uri = X.actionUrl('edit')
uri.addKeywords(keywords)
return redirect(uri)
clone.isPublicForWeb = 1
def delete(self, id):
method = context.getVar('httpMethod')
if id and self.hasObject(id):
try:
self.deleteObject(id)
except faults.Fault:
if context.getVar('debug'):
raise
return accessForbidden()
if method == 'DELETE':
return HTTP_NO_CONTENT
uri = X.actionUrl()
return redirect(uri)
else:
# TODO: error page when user tries to delete an object he can't
return pageNotFound()
delete.isPublicForWeb = 1
def download(self, id, path):
localId = commonTools.extractLocalId(id)
if localId == '__admin__':
if not self.canGetAdmin():
return accessForbidden()
object = self.getAdmin()
else:
if not self.hasObject(id):
return pageNotFound()
if not self.canGetObject(id):
return accessForbidden()
object = self.getObject(id)
rememberObject(id)
req = context.getVar('req')
uploadSlot = object.getSlotByPath(path)
upload = uploadSlot.getValue()
data = upload.getSlot('data', parentSlot = uploadSlot).getValue()
dataFileName = upload.getSlot(
'dataFileName', parentSlot = uploadSlot).getValue()
if dataFileName:
req.headers_out['Content-Disposition'] = \
'inline; filename="%s"' % dataFileName
req.headers_out['Content-Length'] = str(len(data))
req.content_type = upload.getSlot(
'dataType', parentSlot = uploadSlot).getValue()
setHttpCookie()
req.send_http_header()
if req.method == 'HEAD':
return OK
req.write(data)
return OK
download.isPublicForWeb = 1
def edit(self, id = '', again = '', error = '', **keywords):
if keywords is None:
keywords = {}
keywords['id'] = id
if id and not self.hasObject(id):
return pageNotFound()
if id:
if not self.canModifyObject(id):
return accessForbidden()
object = self.getObject(id)
rememberObject(id)
else:
if not self.canAddObject():
return accessForbidden()
object = self.newObject(keywords)
if id and not again:
object.makeFieldsFromInstance(keywords)
if not id and not again:
object.initFields(keywords)
object.repairFields(keywords)
if not id:
headerTitle = _(self.newObjectNameCapitalized)
else:
headerTitle = _('Editing %s - %s') % (
_(self.objectNameCapitalized), object.getLabel())
if keywords.has_key('headerTitle'):
headerTitle = keywords['headerTitle']
context.push(_level = 'edit',
isCreateEditMode = not id,
layoutMode = 'edit')
try:
layout = X.array()
leadIn = self.getEditLeadIn(object, keywords)
if leadIn:
layout += X.enclose(leadIn, _class = 'lead-in')
layout += object.getErrorLayout(error, keywords)
form = X.form(action = X.actionUrl('submit'),
enctype = 'multipart/form-data', method = 'post')
layout += form
if keywords.has_key('cloned') and keywords['cloned']:
form += X.input(name = 'cloned', type = 'hidden', value = '1')
if keywords.has_key('nextUri') and keywords['nextUri']:
form += X.input(name = 'nextUri', type = 'hidden',
value = keywords['nextUri'])
slot = slots.Root(object)
widget = slot.getWidget()
form += widget.getModelPageBodyLayout(slot, keywords)
buttonsBar = X.div(_class = 'buttons-bar')
form += buttonsBar
actionButtonsBar = X.span(_class = 'action-buttons-bar')
buttonsBar += actionButtonsBar
if not id:
actionButtonsBar += X.buttonInForm('create', 'createButton')
else:
if self.canDeleteObject(id):
actionButtonsBar += X.buttonInForm(
'delete', 'deleteButton')
actionButtonsBar += X.buttonInForm('modify', 'modifyButton')
return writePageLayout(layout, headerTitle)
finally:
context.pull(_level = 'edit')
edit.isPublicForWeb = 1
def getEditLeadIn(self, object, fields):
return None
def getObjectsLayout(self, partialObjects, objectIds,
slotNames = None):
layout = None
translationsProxy = getProxyForServerRole('translations')
if len(partialObjects) > 0:
if translationsProxy:
labelsMultiCall = MultiCall()
for objectId in objectIds:
partialObjects[objectId].getLabelTranslated(
context.getVar('readLanguages'),
multiCall = labelsMultiCall)
layout = X.array()
if slotNames:
table = X.table(_class = 'objects-table')
layout += table
partialObject = partialObjects.values()[0]
thead = X.thead()
table += thead
tr = X.tr()
thead += tr
tr += X.th()(X.nbsp)
for slotName in slotNames:
slot = partialObject.getSlot(slotName)
tr += slot.getWidget().getHtmlColumnLabel(slot)
tbody = X.tbody()
table += tbody
even = 0
else:
ul = X.ul()
layout += ul
if translationsProxy:
lazyLabels = labelsMultiCall.call()
else:
lazyLabels = objectIds # fastest way to get a list of same len
for objectId, lazyLabel in zip(objectIds, lazyLabels):
if translationsProxy:
try:
label = lazyLabel()
except faults.UnknownStringDigest:
label = partialObjects[objectId].getLabel()
else:
label = partialObjects[objectId].getLabel()
partialObject = partialObjects[objectId]
fields = {}
if slotNames:
for slotName in slotNames:
slot = partialObject.getSlot(slotName)
kind = slot.getKind()
if kind.hasToMakeFieldFromValue:
kind.makeFieldFromValue(
slot, fields, slot.getValue())
for slotName in slotNames:
slot = partialObject.getSlot(slotName)
kind = slot.getKind()
if kind.hasToRepairField:
kind.repairField(slot, fields)
tr = X.tr(_class = ((even and 'even') or 'odd'))
even = not even
tbody += tr
tr += X.td()(
X.a(href = X.idUrl(partialObject.id))(label))
for slotName in slotNames:
slot = partialObject.getSlot(slotName)
widget = slot.getWidget()
widget.setInForm(0)
widget.setReadOnly(0)
tr += widget.getHtmlColumnValue(slot, fields)
else:
ul += X.li()(
X.a(href = X.idUrl(partialObject.id))(label))
#layout += X.br()
return layout
def getObjectsSectionLayout(self, partialObjects, intertitle,
slotNames = None):
layout = None
translationsProxy = getProxyForServerRole('translations')
if len(partialObjects) > 0:
if translationsProxy:
labelsMultiCall = MultiCall()
for partialObject in partialObjects:
partialObject.getLabelTranslated(
context.getVar('readLanguages'),
multiCall = labelsMultiCall)
layout = X.array(X.h2()(intertitle))
table = X.table(_class = 'objects-table')
layout += table
partialObject = partialObjects[0]
if slotNames:
thead = X.thead()
table += thead
tr = X.tr()
thead += tr
tr += X.th()(X.nbsp)
for slotName in slotNames:
slot = partialObject.getSlot(slotName)
tr += slot.getWidget().getHtmlColumnLabel(slot)
tbody = X.tbody()
table += tbody
else:
tbody = table
even = 0
if translationsProxy:
lazyLabels = labelsMultiCall.call()
else:
lazyLabels = partialObjects # fastest way to get a list of same len
for partialObject, lazyLabel in zip(partialObjects, lazyLabels):
if translationsProxy:
label = lazyLabel()
else:
label = partialObject.getLabel()
fields = {}
if slotNames:
for slotName in slotNames:
slot = partialObject.getSlot(slotName)
kind = slot.getKind()
if kind.hasToMakeFieldFromValue:
kind.makeFieldFromValue(
slot, fields, slot.getValue())
for slotName in slotNames:
slot = partialObject.getSlot(slotName)
kind = slot.getKind()
if kind.hasToRepairField:
kind.repairField(slot, fields)
tr = X.tr(_class = ((even and 'even') or 'odd'))
even = not even
tbody += tr
tr += X.td()(X.a(href = X.idUrl(partialObject.id))(label))
if slotNames:
for slotName in slotNames:
slot = partialObject.getSlot(slotName)
widget = slot.getWidget()
widget.setInForm(0)
widget.setReadOnly(0)
tr += widget.getHtmlColumnValue(slot, fields)
layout += X.br()
return layout
def getSortedIds(self, objects):
translationsProxy = getProxyForServerRole('translations')
labels = {}
ids = objects.keys()
if not translationsProxy:
for k, v in objects.items():
labels[k] = v.getLabel()
else:
objectsByDispatcherId = {}
for id, object in objects.items():
dispatcherId = commonTools.extractDispatcherId(id)
if not objectsByDispatcherId.has_key(dispatcherId):
objectsByDispatcherId[dispatcherId] = {}
objectsByDispatcherId[dispatcherId][id] = object
readLanguages = context.getVar('readLanguages')
for sameDispatcherObjects in objectsByDispatcherId.values():
labelsMultiCall = MultiCall()
for object in sameDispatcherObjects.values():
object.getLabelTranslated(
readLanguages, multiCall = labelsMultiCall)
for id, lazyLabel in zip(ids, labelsMultiCall.call()):
try:
labels[id] = lazyLabel()
except faults.UnknownStringDigest:
labels[id] = objects[id].getLabel()
ids.sort(lambda id1, id2, labels = labels:
locale.strcoll(labels[id1], labels[id2]))
return ids
def getViewAboveButtonsBarLayout(self, object, fields):
return None
def getViewActionButtonsBarLayout(self, object, fields):
layout = X.array()
if self.canDeleteObject(object.id):
layout += X.buttonStandalone(
'delete', X.idUrl(object.id, 'submit').add(
'deleteButton', _('Delete')))
if self.canCloneObject(object.id):
layout += X.buttonStandalone(
'clone', X.idUrl(object.id, 'clone'))
if self.canModifyObject(object.id):
layout += X.buttonStandalone('edit', X.idUrl(object.id, 'edit'))
return layout
def getViewAllActionButtonsBarLayout(self):
layout = X.array()
if self.canAddObject():
layout += X.buttonStandalone('new', X.actionUrl('edit'))
return layout
def getViewAllButtonsBarLayout(self):
layout = X.div(_class = 'buttons-bar')
layout += X.span(_class = 'navigation-buttons-bar')(
self.getViewAllNavigationButtonsBarLayout())
layout += X.span(_class = 'other-action-buttons-bar')(
self.getViewAllOtherActionButtonsBarLayout())
layout += X.span(_class = 'action-buttons-bar')(
self.getViewAllActionButtonsBarLayout())
return layout
def getViewAllLeadIn(self):
return None
def getViewAllNavigationButtonsBarLayout(self):
layout = X.array()
userToken = context.getVar('userToken')
if self.canModifyAdmin() and userToken:
layout += X.buttonStandalone('settings', X.actionUrl('admin'))
return layout
def getViewAllOtherActionButtonsBarLayout(self):
return None
def getViewBelowButtonsBarLayout(self, object, fields):
return None
def getViewButtonsBarLayout(self, object, fields):
layout = X.div(_class = 'buttons-bar')
layout += X.span(_class = 'navigation-buttons-bar')(
self.getViewNavigationButtonsBarLayout(object, fields))
layout += X.span(_class = 'other-action-buttons-bar')(
self.getViewOtherActionButtonsBarLayout(object, fields))
layout += X.span(_class = 'action-buttons-bar')(
self.getViewActionButtonsBarLayout(object, fields))
return layout
def getViewLeadIn(self, object, fields):
return None
def getViewNavigationButtonsBarLayout(self, object, fields):
layout = X.array()
userToken = context.getVar('userToken', default = '')
if userToken:
layout += X.buttonStandalone('view-list', X.actionUrl())
return layout
def getViewOtherActionButtonsBarLayout(self, object, fields):
return None
def id(self, id):
if not self.hasObject(id):
return pageNotFound()
if not self.canGetObject(id):
return accessForbidden()
object = self.getObject(id)
return writePageLayout(
X.p(id),
_('Id for "%s"') % object.getLabel())
id.isPublicForWeb = 1
image = download
image.isPublicForWeb = 1
def imageEdit(self, id = '', path = '', **keywords):
if keywords is None:
keywords = {}
keywords['id'] = id
if id:
localId = commonTools.extractLocalId(id)
if localId == '__admin__':
if not self.canModifyAdmin():
return accessForbidden()
object = self.getAdmin()
else:
if not self.hasObject(id):
return pageNotFound()
if not self.canModifyObject(id):
return accessForbidden()
object = self.getObject(id)
rememberObject(id)
else:
if not self.canAddObject():
return accessForbidden()
object = self.newObject(keywords)
uploadSlot = object.getSlotByPath(path)
upload = uploadSlot.getValue()
data = upload.getSlot('data', parentSlot = uploadSlot).getField(
keywords)
req = context.getVar('req')
dataFileName = upload.getSlot(
'dataFileName', parentSlot = uploadSlot).getField(keywords)
if dataFileName:
req.headers_out['Content-disposition'] = \
'attachment; filename="%s"' % dataFileName
req.headers_out['Content-length'] = str(len(data))
req.content_type = upload.getSlot(
'dataType', parentSlot = uploadSlot).getField(keywords)
setHttpCookie()
req.send_http_header()
if req.method == 'HEAD':
return OK
req.write(data)
return OK
imageEdit.isPublicForWeb = 1
def rss(self):
lastObjects = self.getLastObjects(20, None, None, None)
req = context.getVar('req')
req.content_type = 'application/rss+xml'
req.send_http_header()
if req.caching:
req.openCachePage()
req.write("""\
<?xml version="1.0" encoding="iso-8859-15"?>
<rss version="2.0"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>%(websiteTitle)s (%(objectsName)s)</title>
<link>http://%(websiteUrl)s</link>
""" % {
'websiteTitle': context.getVar('virtualHost').getLabel(),
'websiteUrl': context.getVar('virtualHost').hostName,
'objectsName': _(self.objectsNameCapitalized),
})
# Workaround Python Emacs mode bug: """
for object in lastObjects:
req.write("""\
<item>
<title>%s</title>
<dc:language>%s</dc:language>
<link>%s</link>
</item>
""" % (
xmlEncode(object.getLabel()),
object.language,
X.idUrl(object.id).getAsAbsoluteUrl()))
req.write("""\
</channel>
</rss>
""")
if req.caching:
req.closeCachePage()
return OK
rss.isPublicForWeb = 1
def search(self, slotNames = None, **keywords):
if 'terms' in keywords.keys():
terms = keywords['terms']
del keywords['terms']
terms = terms.split(' ')
object = self.newObject(keywords)
allSlotNames = object.getSlotNames()
for slotName in ['addToId', 'addToSlot', 'serverRole',
'thingName', 'thingCategory']:
if slotName in allSlotNames:
allSlotNames.remove(slotName)
for slotName in allSlotNames:
kind = object.getSlot(slotName).getKind()
if kind.__class__.__name__ == 'String':
keywords['%s_PT' % slotName] = terms
for key in keywords.keys():
if not '_' in key:
del keywords[key]
if type(slotNames) is not types.ListType:
slotNames = None
if not self.canGetObjects():
return accessForbidden()
if slotNames:
objects = self.searchPartialObjects(requiredSlotNames = slotNames,
**keywords)
else:
objects = self.searchObjects(**keywords)
layout = X.array()
ids = self.getSortedIds(objects)
layout += self.getObjectsLayout(objects, ids, slotNames = slotNames)
layout += self.getViewAllButtonsBarLayout()
title = _(self.objectsNameCapitalized) + ' ' + _('Search Results')
return writePageLayout(layout, title)
search.isPublicForWeb = 1
def submit(self, id = '', **keywords):
if keywords is None:
keywords = {}
if id and not self.hasObject(id):
return pageNotFound()
if isButtonSelected('deleteButton', keywords):
return confirmDelete(
X.idUrl(id, 'delete'),
id = id,
objectName = self.objectName)
keywords['id'] = id
if isButtonSelected('applyButton', keywords):
keywords['again'] = '1'
keywords['hideErrors'] = '1'
error = 0
object = self.newObject(keywords)
if error:
keywords['again'] = '1'
keywords['error'] = '1'
else:
object.submitFields(keywords)
if keywords.has_key('again') and keywords['again']:
uri = X.idUrl(id, 'edit')
uri.addKeywords(keywords)
return redirect(uri)
if not id:
result = self.submitAddObject(object, **keywords)
else:
result = self.submitModifyObject(object, **keywords)
if result:
return result
if not id and keywords.has_key('addToId') and keywords['addToId']:
keywords['id'] = object.id
self.submitAddObjectToOther(**keywords)
if keywords.has_key('nextUri') and keywords['nextUri']:
return redirect(keywords['nextUri'])
return redirect(X.idUrl(object.id))
submit.isPublicForWeb = 1
def submitAddObject(self, object, **keywords):
try:
object.id = self.addObject(object)
except faults.UserAccessDenied:
if context.getVar('debug'):
raise
return accessForbidden()
def submitAddObjectToOther(self, **keywords):
# FIXME: proper error handling
addToId = keywords['addToId']
proxy = getProxy(addToId)
objectWeAddTo = proxy.getObject(addToId)
if keywords.has_key('addToSlot') and keywords['addToSlot']:
slotName = keywords['addToSlot']
slot = objectWeAddTo.getSlot(slotName)
else:
# if not slotname specified, we take the first sequence
for slotName in objectWeAddTo.getOrderedLayoutSlotNames():
slot = objectWeAddTo.getSlot(slotName)
kind = slot.getKind()
if kind.getThingName() != 'Sequence':
continue
if kind.itemKind.getThingName() != 'Id':
continue
break
else:
raise 'Unable to find a slot to add to'
kindName = slot.getKind().getThingName()
cV = slot.getValue()
if kindName == 'Sequence':
if not cV:
cV = []
cV.append(keywords['id'])
else:
cV = keywords['id']
setattr(objectWeAddTo, slotName, cV)
proxy.modifyObject(objectWeAddTo)
def submitModifyObject(self, object, **keywords):
try:
self.modifyPartialObject(object, object.getSlotToModifyNames())
except faults.WrongVersion:
keywords['again'] = '1'
keywords['error'] = '1'
keywords['versionError'] = '1'
uri = X.idUrl(object.id, 'edit')
uri.addKeywords(keywords)
return redirect(uri)
except faults.UserAccessDenied:
return accessForbidden()
def thumbnail(self, id, path, width = '', height = ''):
localId = commonTools.extractLocalId(id)
if localId == '__admin__':
if not self.canGetAdmin():
return accessForbidden()
object = self.getAdmin()
else:
if not self.hasObject(id):
return pageNotFound()
if not self.canGetObject(id):
return accessForbidden()
object = self.getObject(id)
rememberObject(id)
try:
width = int(width)
except ValueError:
width = 128
try:
height = int(height)
except ValueError:
height = 128
uploadSlot = object.getSlotByPath(path)
upload = uploadSlot.getValue()
data = upload.getSlot('data', parentSlot = uploadSlot).getValue()
if data and upload.isType('image'):
import cStringIO
# From Python Imaging Library.
try:
import Image as PILImage
except ImportError:
PILImage = None
if PILImage:
imageFile = cStringIO.StringIO(data)
imageObject = PILImage.open(imageFile)
imageObject.thumbnail((width, height))
thumbnailFile = cStringIO.StringIO()
imageObject.save(thumbnailFile, imageObject.format)
data = thumbnailFile.getvalue()
width, height = imageObject.size
req = context.getVar('req')
dataFileName = upload.getSlot(
'dataFileName', parentSlot = uploadSlot).getValue()
if dataFileName:
req.headers_out['Content-disposition'] = \
'attachment; filename="%s"' % dataFileName
req.headers_out['Content-length'] = str(len(data))
req.content_type = upload.getSlot(
'dataType', parentSlot = uploadSlot).getValue()
setHttpCookie()
req.send_http_header()
if req.method == 'HEAD':
return OK
req.write(data)
return OK
thumbnail.isPublicForWeb = 1
def use(self, id):
return self.view(id)
use.isPublicForWeb = 1
def view(self, id):
if not self.hasObject(id):
return pageNotFound()
if not self.canGetObject(id):
return accessForbidden()
object = self.getObject(id)
rememberObject(id)
keywords = {}
object.makeFieldsFromInstance(keywords)
object.repairFields(keywords)
label = object.getLabelTranslated(context.getVar('readLanguages'))
layout = X.array()
leadIn = self.getViewLeadIn(object, keywords)
if leadIn:
layout += X.enclose(leadIn, _class = 'lead-in')
slot = slots.Root(object)
widget = slot.getWidget()
layout += widget.getModelPageBodyLayout(slot, keywords)
pageTitle = context.getVar('pageTitle', default = None)
layout += self.getViewAboveButtonsBarLayout(object, keywords)
if context.getVar('userId'):
layout += self.getViewButtonsBarLayout(object, keywords)
layout += self.getViewBelowButtonsBarLayout(object, keywords)
context.push(
currentObject = WebAPI.GlasnostObject(object = object),
)
if not pageTitle:
pageTitle = '%s - %s' % (_(self.objectNameCapitalized), label)
layout = writePageLayout(layout, pageTitle)
context.pull()
return layout
view.isPublicForWeb = 1
def viewAll(self, slotNames = None):
if type(slotNames) is not types.ListType:
slotNames = None
context.push(_level = 'viewAll',
defaultDispatcherId = context.getVar('dispatcherId'))
try:
if not self.canGetObjects():
return accessForbidden()
objects = self.getObjects()
layout = X.array()
leadIn = self.getViewAllLeadIn()
if leadIn:
layout += X.enclose(leadIn, _class = 'lead-in')
ids = self.getSortedIds(objects)
layout += self.getObjectsLayout(
objects, ids, slotNames = slotNames)
layout += self.getViewAllButtonsBarLayout()
finally:
context.pull(_level = 'viewAll')
return writePageLayout(layout, _(self.objectsNameCapitalized))
viewAll.isPublicForWeb = 1
def viewAllPy(self, **keywords):
context.push(_level = 'viewAllPy',
defaultDispatcherId = context.getVar('dispatcherId'))
try:
keywords['objects'] = [WebAPI.GlasnostObject(id)
for id in self.getObjectIds()]
finally:
context.pull(_level = 'viewAllPy')
req = context.getVar('req')
keywords['req'] = req
stdO = sys.stdout
sys.stdout = req
try:
execfile(context.getVar('PyFile'), keywords)
sys.stdout = stdO
except:
sys.stdout = stdO
raise apache.SERVER_RETURN, HTTP_INTERNAL_SERVER_ERROR
return OK
def viewAllTal(self, **keywords):
context.push(_level = 'viewAllTal',
defaultDispatcherId = context.getVar('dispatcherId'))
try:
keywords['objects'] = [WebAPI.GlasnostObject(id)
for id in self.getObjectIds()]
finally:
context.pull(_level = 'viewAllTal')
file = context.getVar('TALFile')
return processTALFile(
'',
xtal = context.getVar('TALFileIsXTAL'),
file = file,
**keywords)
def viewTal(self, id, **keywords):
if not self.hasObject(id):
return pageNotFound()
if not self.canGetObject(id):
return accessForbidden()
file = context.getVar('TALFile')
keywords['currentObject'] = WebAPI.GlasnostObject(id)
rememberObject(id)
return processTALFile(
'',
xtal = context.getVar('TALFileIsXTAL'),
file = file,
**keywords)
def viewPy(self, id, **keywords):
req = context.getVar('req')
keywords['currentObject'] = WebAPI.GlasnostObject(id)
keywords['req'] = context.req
for k, v in getTemplateVars().items():
keywords[k] = v
rememberObject(id)
stdO = sys.stdout
sys.stdout = req
try:
execfile(context.getVar('PyFile'), keywords)
sys.stdout = stdO
except:
sys.stdout = stdO
raise apache.SERVER_RETURN, HTTP_INTERNAL_SERVER_ERROR
return OK