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