[gen] Added the possility to get an XML version of every object by calling URL <objectUrl>/xml; added the possiblity to call any method on any object by calling <objectUrl>?do=myMethod and retrieve the result as XML.
This commit is contained in:
parent
5269b278f7
commit
c3aa01a554
|
@ -9,8 +9,9 @@ import appy.gen as gen
|
||||||
from appy.gen.utils import *
|
from appy.gen.utils import *
|
||||||
from appy.gen.layout import Table, defaultPageLayouts, ColumnLayout
|
from appy.gen.layout import Table, defaultPageLayouts, ColumnLayout
|
||||||
from appy.gen.descriptors import WorkflowDescriptor, ClassDescriptor
|
from appy.gen.descriptors import WorkflowDescriptor, ClassDescriptor
|
||||||
from appy.shared.utils import sequenceTypes, normalizeText
|
from appy.shared.utils import sequenceTypes, normalizeText, Traceback
|
||||||
from appy.shared.data import rtlLanguages
|
from appy.shared.data import rtlLanguages
|
||||||
|
from appy.shared.xml_parser import XmlMarshaller
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class BaseMixin:
|
class BaseMixin:
|
||||||
|
@ -344,6 +345,27 @@ class BaseMixin:
|
||||||
iNames = self.wrapperClass.getIndexes().keys()
|
iNames = self.wrapperClass.getIndexes().keys()
|
||||||
catalog.catalog_object(self, path, idxs=iNames)
|
catalog.catalog_object(self, path, idxs=iNames)
|
||||||
|
|
||||||
|
def xml(self, action=None):
|
||||||
|
'''If no p_action is defined, this method returns the XML version of
|
||||||
|
this object. Else, it calls method named p_action on the
|
||||||
|
corresponding Appy wrapper and returns, as XML, the its result.'''
|
||||||
|
self.REQUEST.RESPONSE.setHeader('Content-Type','text/xml;charset=utf-8')
|
||||||
|
# Check if the user is allowed to consult this object
|
||||||
|
if not self.allows('View'):
|
||||||
|
return XmlMarshaller().marshall('Unauthorized')
|
||||||
|
if not action:
|
||||||
|
marshaller = XmlMarshaller(rootTag=self.getClass().__name__,
|
||||||
|
dumpUnicode=True)
|
||||||
|
res = marshaller.marshall(self, objectType='appy')
|
||||||
|
else:
|
||||||
|
appyObj = self.appy()
|
||||||
|
try:
|
||||||
|
methodRes = getattr(appyObj, action)()
|
||||||
|
res = XmlMarshaller().marshall(methodRes)
|
||||||
|
except Exception, e:
|
||||||
|
res = XmlMarshaller().marshall(Traceback.get())
|
||||||
|
return res
|
||||||
|
|
||||||
def say(self, msg, type='info'):
|
def say(self, msg, type='info'):
|
||||||
'''Prints a p_msg in the user interface. p_logLevel may be "info",
|
'''Prints a p_msg in the user interface. p_logLevel may be "info",
|
||||||
"warning" or "error".'''
|
"warning" or "error".'''
|
||||||
|
@ -664,13 +686,14 @@ class BaseMixin:
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getAppyTypes(self, layoutType, pageName):
|
def getAppyTypes(self, layoutType, pageName):
|
||||||
'''Returns the list of appyTypes that belong to a given p_page, for a
|
'''Returns the list of fields that belong to a given page (p_pageName)
|
||||||
given p_layoutType.'''
|
for a given p_layoutType. If p_pageName is None, fields of all pages
|
||||||
|
are returned.'''
|
||||||
res = []
|
res = []
|
||||||
for appyType in self.getAllAppyTypes():
|
for field in self.getAllAppyTypes():
|
||||||
if appyType.page.name != pageName: continue
|
if pageName and (field.page.name != pageName): continue
|
||||||
if not appyType.isShowable(self, layoutType): continue
|
if not field.isShowable(self, layoutType): continue
|
||||||
res.append(appyType)
|
res.append(field)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getCssJs(self, fields, layoutType, res):
|
def getCssJs(self, fields, layoutType, res):
|
||||||
|
@ -1414,7 +1437,14 @@ class BaseMixin:
|
||||||
|
|
||||||
def index_html(self):
|
def index_html(self):
|
||||||
'''Redirects to /ui.'''
|
'''Redirects to /ui.'''
|
||||||
return self.REQUEST.RESPONSE.redirect(self.getUrl())
|
rq = self.REQUEST
|
||||||
|
if rq.has_key('do'):
|
||||||
|
# The user wants to call a method on this object and get its result
|
||||||
|
# as XML.
|
||||||
|
return self.xml(action=rq['do'])
|
||||||
|
else:
|
||||||
|
# The user wants to consult the view page for this object
|
||||||
|
return rq.RESPONSE.redirect(self.getUrl())
|
||||||
|
|
||||||
def userIsAnon(self):
|
def userIsAnon(self):
|
||||||
'''Is the currently logged user anonymous ?'''
|
'''Is the currently logged user anonymous ?'''
|
||||||
|
|
|
@ -622,11 +622,15 @@ class XmlMarshaller:
|
||||||
elif fieldType == 'dict': self.dumpDict(res, value)
|
elif fieldType == 'dict': self.dumpDict(res, value)
|
||||||
elif isRef:
|
elif isRef:
|
||||||
if value:
|
if value:
|
||||||
|
if self.objectType == 'appy':
|
||||||
|
suffix = '/xml'
|
||||||
|
else:
|
||||||
|
suffix = ''
|
||||||
if type(value) in sequenceTypes:
|
if type(value) in sequenceTypes:
|
||||||
for elem in value:
|
for elem in value:
|
||||||
self.dumpField(res, 'url', elem.absolute_url())
|
self.dumpField(res, 'url', elem.absolute_url()+suffix)
|
||||||
else:
|
else:
|
||||||
self.dumpField(res, 'url', value.absolute_url())
|
self.dumpField(res, 'url', value.absolute_url()+suffix)
|
||||||
elif fieldType in ('list', 'tuple'):
|
elif fieldType in ('list', 'tuple'):
|
||||||
# The previous condition must be checked before this one because
|
# The previous condition must be checked before this one because
|
||||||
# referred objects may be stored in lists or tuples, too.
|
# referred objects may be stored in lists or tuples, too.
|
||||||
|
@ -751,27 +755,34 @@ class XmlMarshaller:
|
||||||
self.dumpField(res, field.getName(),field.get(instance),
|
self.dumpField(res, field.getName(),field.get(instance),
|
||||||
fieldType=fieldType)
|
fieldType=fieldType)
|
||||||
elif objectType == 'appy':
|
elif objectType == 'appy':
|
||||||
for field in instance.getAllAppyTypes():
|
for field in instance.getAppyTypes('view', None):
|
||||||
# Dump only needed fields
|
# Dump only needed fields
|
||||||
|
if (field.type == 'Computed') and not field.plainText:
|
||||||
|
# Ignore fields used for producing custom chunks of HTML
|
||||||
|
# within the web UI.
|
||||||
|
continue
|
||||||
if field.name in self.fieldsToExclude: continue
|
if field.name in self.fieldsToExclude: continue
|
||||||
if (field.type == 'Ref') and field.isBack: continue
|
|
||||||
if (type(self.fieldsToMarshall) in sequenceTypes) \
|
if (type(self.fieldsToMarshall) in sequenceTypes) \
|
||||||
and (field.name not in self.fieldsToMarshall): continue
|
and (field.name not in self.fieldsToMarshall): continue
|
||||||
# Determine field type
|
# Determine field type and value
|
||||||
fieldType = 'basic'
|
fieldType = 'basic'
|
||||||
if field.type == 'File':
|
if field.type == 'File':
|
||||||
fieldType = 'file'
|
fieldType = 'file'
|
||||||
|
v = field.getValue(instance)
|
||||||
|
if v: v = v._zopeFile
|
||||||
elif field.type == 'Ref':
|
elif field.type == 'Ref':
|
||||||
fieldType = 'ref'
|
fieldType = 'ref'
|
||||||
self.dumpField(res, field.name,field.getValue(instance),
|
v = field.getValue(instance, type='zobjects')
|
||||||
fieldType=fieldType)
|
else:
|
||||||
|
v = field.getValue(instance)
|
||||||
|
self.dumpField(res, field.name, v, fieldType=fieldType)
|
||||||
# Dump the object history.
|
# Dump the object history.
|
||||||
|
if hasattr(instance.aq_base, 'workflow_history'):
|
||||||
histTag = self.getTagName('history')
|
histTag = self.getTagName('history')
|
||||||
eventTag = self.getTagName('event')
|
eventTag = self.getTagName('event')
|
||||||
res.write('<%s type="list">' % histTag)
|
res.write('<%s type="list">' % histTag)
|
||||||
wfInfo = instance.portal_workflow.getWorkflowsFor(instance)
|
key = instance.workflow_history.keys()[0]
|
||||||
if wfInfo:
|
history = instance.workflow_history[key]
|
||||||
history = instance.workflow_history[wfInfo[0].id]
|
|
||||||
for event in history:
|
for event in history:
|
||||||
res.write('<%s type="object">' % eventTag)
|
res.write('<%s type="object">' % eventTag)
|
||||||
for k, v in event.iteritems():
|
for k, v in event.iteritems():
|
||||||
|
|
Loading…
Reference in a new issue