Hi.

In a FC plugin's routeStartup() I'm pushing custom actions onto the
actionstack like this:

        public function initModules() {
                $this->logger->info(__METHOD__);
                
Zend_Controller_Front::getInstance()->addModuleDirectory($this->config->modulesPath);

                $actionstack =
Zend_Controller_Action_HelperBroker::getStaticHelper('ActionStack');
                
                $modules = $this->config->module->toArray();
                //reverse it in order to achieve the same stack pop order as in 
.ini
                $moduleOrder = array_reverse(explode(' 
',$this->config->moduleOrder));
                $this->logger->info($modules);
                
                foreach($moduleOrder as $module) {
                        $settings = $modules[$module];
                        if($settings['active'] && $settings['navbar']) {
                                $this->logger->warn('module navpane: ' . 
$module);
                                
$actionstack->actionToStack('navpane','index',$module /*,
$this->getRequest()->getParams()/**/ );
                        }
                }
                /**
                 * It can be done here, or in 
My_Controller_Action::preDispatch()
                 * If done here, it is impossible not to have the default 
action triggered.
                 * If done there, you can ensure you get an 
/default/index/index only if a
                 * My_Controller_Action is instanced, which should provide a 
greater
                 * flexibility later, That's why it's commented out [!].
                 */
                $actionstack->actionToStack('index','index','default');
                Zend_Registry::set('my_action_controller',array());
                return $this;
        }

Then, my base class for these actions (in the order pushed on the
stack: /assessments/index/navpane, /forum/index/navpane,
/default/index/index) looks like this

<?php
require_once 'Zend/Controller/Action.php';

class My_Controller_Action extends Zend_Controller_Action {
        protected $_isDirectCall = FALSE;//module/controller/action only if
it has not already been done
        protected $_isStartAction = FALSE;//is the /default/index/index action
        
        /*
         * array containing three keys, each in the format 0 => module 1 =>
controller 2 => action
         * 'default'    : what the front controller returns as "default 
homepage"
         * 'this'               : this very object/request
         * 'url'                : what is actually in the url
         */
        private $_mvcs = NULL;

        public function preDispatch() {
                $logger = Zend_Registry::get('logger');
                $mvc = $this->getMVCs();
                $logger->info('BEGIN PREdispatching for action /' .
implode('/',$mvc['this']));
                
                $mvcs = $this->getMVCs();
                if($mvcs['default'] === $mvcs['this']) {//startpage
                        $this->_isStartAction = TRUE;
                        $logger->info('IS DEFAULT');
                }
                if($mvcs['this'] === $mvcs['url']) {//direct call
                        $this->_isDirectCall = TRUE;
                        $logger->info('IS DIRECT');
                }
                
                $this->view->MVCs = $this->_mvcs;
                $this->view->isDirectCall = $this->_isDirectCall;
                $this->view->isDefaultAction = $this->_isStartAction;
                parent::preDispatch();
        }
        
        public function postDispatch() {
                $logger = Zend_Registry::get('logger');
                $mvc = $this->getMVCs();
                $logger->info($mvc);
                $logger->info('END POSTdispatching for action /' . 
implode('/',$mvc['this']));
                parent::postDispatch();
                $this->_isDirectCall = FALSE;
                $this->_isStartAction = FALSE;
        }
        
        public function getMVCs() {
                $fc = Zend_Controller_Front::getInstance(); 
//$this->getFrontController();
                if(!$this->_mvcs) {
                        $this->_mvcs = array();
                        $this->_mvcs['default'] = array($fc->getDefaultModule(),
$fc->getDefaultControllerName(),
                                $fc->getDefaultAction()); // usually 
/default/index/index
                        
                        $t = $this->getRequest()->getParams();
                        $this->_mvcs['url'] =
array($t['module'],$t['controller'],$t['action']);//this is what you
see in the URL
                }
                $t = $fc->getRequest();
                $this->_mvcs['this'] =
array($t->getModuleName(),$t->getControllerName(),$t->getActionName());//the
module/controller/action of this very object
                return $this->_mvcs;
        }
}

navpane.html for my two modules, assessments and forum, look similar
(only with different ID attributes, etc):

<?php
$this->placeholder('default_ui_navPane')->captureStart();
echo $this->accordionPane('assessments_navpane_navpane','automatically
generated assessments pane',
        array('title' => 'Assessments'));
$this->placeholder('default_ui_navPane')->captureEnd();

The placeholders are then echo'd in layout.phtml. Considering the
order of the modules ($modulesOrder in the POC above) being
"assessments forum", everything works as expected if I go to the
/assessments/index/index (or whichever is the first, if there are more
modules), but when I visit /forum/index/index, it tries to generate
two times the dijit div with the id assessments_navpane_navpane (or
whichever is the previous on stack).

What causes this and how to fix it in a clean way? To me personally,
it looks like a "circular overwrite" of inherited object properties.

Also, if the modules are "assessments forum wiki", then /assessments works fine,
/forum generates
<div id="assessments_navpane_navpane" title="Assessments"
dojoType="dijit.layout.AccordionPane">automatically generated forum
pane</div>
<div id="wiki_navpane_navpane" title="Wikis"
dojoType="dijit.layout.AccordionPane">automatically generated wiki
pane</div>

and /wiki/index/index:
<div id="forum_navpane_navpane" title="Forums"
dojoType="dijit.layout.AccordionPane">automatically generated forum
pane</div>
<div id="forum_navpane_navpane" title="Forums"
dojoType="dijit.layout.AccordionPane">automatically generated wiki
pane</div>

Where the message 'automatically generated '.$this->module.' pane'
uses a variable defined in each navpaneAction() of my concrete
subclasses of My_Controller_Action, like Forum_IndexController, etc.

PS: sorry for the long POC, I reduced it as much as I could.

--Flavius

Reply via email to