Back to index

plone3  3.1.7
TraverseToAction.py
Go to the documentation of this file.
00001 from BaseFormAction import BaseFormAction
00002 import TraverseTo
00003 
00004 from Products.CMFCore.utils import getToolByName
00005 from Products.CMFFormController.FormController import registerFormAction
00006 from urlparse import urlsplit
00007 
00008 def factory(arg):
00009     """Create a new traverse-to-action action"""
00010     return TraverseToAction(arg)
00011 
00012 
00013 class TraverseToAction(BaseFormAction):
00014 
00015     def __call__(self, controller_state):
00016         action = self.getArg(controller_state)
00017         action_url = None
00018         haveAction = False
00019 
00020         context = controller_state.getContext()
00021         actions_tool = getToolByName(context, 'portal_actions')
00022         fti = context.getTypeInfo()
00023         REQUEST = getattr(context, 'REQUEST', None)
00024 
00025         try:
00026             # Test to see if the action is defined in the FTI as an object or
00027             # folder action
00028             action_ob = fti.getActionObject('object/'+action)
00029             if action_ob is None:
00030                 action_ob = fti.getActionObject('folder/'+action)
00031             # Use portal actions here so we have a full expression context
00032             ec = actions_tool._getExprContext(context)
00033             actiondict = action_ob.getAction(ec)
00034             haveAction = True
00035         except (ValueError, AttributeError):
00036             actions = actions_tool.listFilteredActionsFor(
00037                                                 controller_state.getContext())
00038             # flatten the actions as we don't care where they are
00039             actions = reduce(lambda x,y,a=actions:  x+a[y], actions.keys(), [])
00040             for actiondict in actions:
00041                 if actiondict['id'] == action:
00042                     haveAction = True
00043                     break
00044         # For traversal, our 'url' must be a traversable path
00045         if haveAction:
00046             action_url = actiondict['url'].strip()
00047             url_parts = urlsplit(action_url)
00048             # Check to see if we have a protocol, if so convert to a path,
00049             # otherwise make the assumption that we are dealing with a
00050             # physical path
00051             if url_parts[0] and REQUEST is not None:
00052                 action_url = '/'.join(REQUEST.physicalPathFromURL(action_url))
00053             else:
00054                 action_url = url_parts[2]
00055         else:
00056             raise ValueError, 'No %s action found for %s' % (action, controller_state.getContext().getId())
00057 
00058         # If we have CMF 1.5, the actual action_url may be hidden behind a method
00059         # alias. Attempt to resolve this
00060         try:
00061             if action_url:
00062                 # If our url is a path, then we need to see if it contains the
00063                 # path to the current object, if so we need to check if the
00064                 # remaining path element is a method alias
00065                 possible_alias = action_url
00066                 current_path = '/'.join(context.getPhysicalPath())
00067                 if possible_alias.startswith(current_path):
00068                     possible_alias = possible_alias[len(current_path)+1:]
00069                 if possible_alias:
00070                     action_url = fti.queryMethodID(possible_alias,
00071                                                    default = action_url,
00072                                                    context = context)
00073         except AttributeError:
00074             # Don't raise if we don't have CMF 1.5
00075             pass
00076 
00077         # XXX: Is there a better way to check this?
00078         if not action_url.startswith('string:'):
00079             action_url = 'string:%s' % (action_url,)
00080         return TraverseTo.TraverseTo(action_url)(controller_state)
00081 
00082 registerFormAction('traverse_to_action',
00083                    factory,
00084                    'Traverse to the action specified in the argument (a TALES expression) for the current context object (e.g. string:view)')