ZF-8257: ContextSwitch not respecting default context

Description

Zend_Controller_Action_Helper_ContextSwitch is ignoring the default set with setDefaultContext()

Comments

I set component

The patch is no good, since it breaks functionality. I solved it in a different fashion, by doing the following:

<?php // .. $format = $this->_getParam('format', $this->_defaultContext); // Set the context $this->_helper ->contextSwitch() ->setDefaultContext($this->_defaultContext) ->setAutoDisableLayout(true) ->initContext($format); // .. ?>

(But it feels that I'm hacking broken functionality.)

I cannot see problem here. If this has been an issue it is likely already fixed as the source code around the patch provided here has notably changed. Please feel free to reopen if something new appears.

I have the same problem in latest 1.11.7

Alexander - could you provide detailed code to reproduce this issue and I will look into it again.

Code taken straight from my current project <?php

class TransactionController extends Zend_Controller_Action {

public function init()
{
   $this->_request->setParam('format', 'xml');
   $this->_helper->contextSwitch()
                 ->addActionContext('getbymonth', array('xml'))
                 ->setDefaultContext('xml')
                 ->initContext();
}

public function getbymonthAction()
{
    $month = $this->_request->getParam('month');
    $year = $this->_request->getParam('year');

    $this->view->month = $month;
    $this->view->year = $year;
    // then I build XML file from these vars in getbymonth.xml.phtml

}

}

With setDefaultContext('xml') I should not have to use $this->_request->setParam('format', 'xml'); and probably addActionContext too but not sure about that one. Right now, I have setParam doing job of setDefaultContext.

I have checked that {{setDefaultContext()}} has no effect in context switch process. You can set and get it, but the class does not use it.

I think that the use case addressed here is invalid and the way it was mentioned to be used is something like this


 /* Uses default context */
$this->_helper->contextSwitch()
              ->setDefaultContext('json')
              ->addActionContext('foo')
              ->addActionContexts(array('bar', 'baz'));

/* Does not use default context */
$this->_helper->contextSwitch()
              ->addActionContext('foo', 'json')
              ->addActionContexts(array('bar' => 'json', 'baz' => 'json'));

As far as I understand the format param cannot be set by default to match with the context, because it breaks the functionality.

sorry, not fully understanding your comment. Do you mean there is no place to use setDefaultContext in this plugin at all? Or there is no place for it in controller? (maybe during bootstrap plugin helper configuration?)

bq. sorry, not fully understanding your comment. Do you mean there is no place to use setDefaultContext in this plugin at all? Or there is no place for it in controller? (maybe during bootstrap plugin helper configuration?)

Alexander,

You can set the default context by using {{setDefaultContext()}}, but it does not have any effect while the decision of the context which to switch has been made. If you want to force the action context to be xml, it's correct to use ``` as you have done, and there is nothing wrong with it.

bq. With setDefaultContext('xml') I should not have to use {{$this->_request->setParam('format', 'xml');}}

As said, I think that your logic is - unfortunately - invalid. {{setDefaultContext()}} wasn't designed to work like that and in my opinion it even shouldn't because that breaks the functionality of the normal action.

Auto-reassign

I think changing initContext like this


        // Return if no context switching enabled, or no context switching
        // enabled for this action
        $contexts = $this->getActionContexts($action);
        if (empty($contexts)) {
            return;
        }

        // Return if no context parameter provided
        if (!$context = $request->getParam($this->getContextParam())) {
            if ($format === null && $this->_defaultContext === 0) {
                return;
            }
            $context = $this->_defaultContext;
        }

will be a better solution. This will not break forcing a context but will allow to fall back to the defaultContext.

After changing it you can sud the ContextSwitch like this:


$this->_helper->contextSwitch()->setDefaultContext('json')->initContext();

After that 'json' will be used if not format ist submited, but the format parameter will be used it submited. And it's still possible to force XML by "initContext('xml')"

gemuesepudding

A small fix. We have to check if _defaultContext is part of the action contexts:



        // Return if no context parameter provided
        if (!$context = $request->getParam($this->getContextParam())) {
            if ($format === null && $this->_defaultContext === null) {
                return;
            }
            if ($this->hasActionContext($action, $this->_defaultContext)) {
              $context = $this->_defaultContext;  
            } else {
              $context = $format;
            }
            
        }

and $format must be set to null;


        // Return if no context parameter provided
        if (!$context = $request->getParam($this->getContextParam())) {
            if ($format === null && $this->_defaultContext === null) {
                return;
            }
            if ($this->hasActionContext($action, $this->_defaultContext)) {
              $context = $this->_defaultContext;  
            } else {
              $context = $format;
              $format = null;
            }   
        }

Sorry