Hook into module function from base controller?

Heyas,

I have an application that has modules which may be enabled or disabled based upon who logs in. What I’m after is some instruction as to how I may create a “hook” from a base controller that grabs information from currently enabled modules.

IE. If I’m logged in as user “A” my menu does a call (ie. “get_menu()” to all the enabled modules to see what menu items are available in each of the modules. Likewise, user “B” may have different modules enabled and require additional results.

I can easily create the function on the module to get the data specific to that module, however I’m not sure the best way to do it.

Currently I have a function called “loadedModules” which I can loop through and perform the “get_menu()” on each module, however I know this is probably the way NOT to do it?? :) I thought events may be the way to go, however the wiki page is quite unclear as to how I would actually implement something like this?

Thoughts, comments… suggestions?? :)

If you implemented the built in RBAC with your ‘modules’ as authorization items, then you could simply use the checkAccess method




Yii::app()->user->checkAccess('someModuleName'); // returns boolean



You could also implement some extra logic (bizrule) that will be executed as the second parameter…

Check CModule. You can list them and check if they are enabled.

I think defining an API/ interface for your modules, which contains a getMenu() function isn’t wrong.

However, if you like to use events, you can do it like this:

Your Module:




class ModuleAModule extends CWebModule

{

  public function init()

  {

    parent::init();

    

    // module initialization

    [...]


    // raise event

    $this->onModuleInitialized( new ModuleInitializedEvent($this, array(

      ModuleInitializedEvent::PARAM_MENU_ITEMS  => $this->getMenuItems(),

      [...]

    )) );

  }


  public function onModuleInitialized( ModuleInitializedEvent $event )

  {

    $this->raiseEvent( 'onModuleInitialized', $event );

  }

}



The Event (you can also use CEvent directly, but I prefer to know which events I use):




class ModuleInitializedEvent extends CEvent

{

  const PARAM_MENU_ITEMS = 'PARAM_MENU_ITEMS';


  public function getMenuItems()

  {

    return $this->params[ InterceptionEvent::PARAM_MENU_ITEMS ];

  }

}



And finally, you can register to the event in you config:




// This is the main Web application configuration. Any writable

// CWebApplication properties can be configured here.

return array(

  [...]


  'modules' => array(

    'moduleA' => array(

      'class'               => 'application.modules.moduleA.ModuleAModule'

      'onModuleInitialized' => // valid callback

    ),

  ),


  [...]

);



Now, a problem might be, that at this early stage, you don’t have any objects at hand. So you can eighter specify a static method as a callback, or use a anonymous function (which requires PHP 5.3).

I lately reflected on how modules should be used and how they should best interact with the rest of the application or other modules (if at all). So if you have some spare time, I would love to read about your thoughts in "How to think of modules".

Thanks all for the feedback, it certainly is food for thought. I’ll have a think about it all and let you know what I come up with !