Having trouble understanding Events

I have a module I am working for on HumHub which is based on Yii Framework.

My question is, how can I raise a global event? In my application, I need to have a check to see if the system is in development mode, and if it is forward to a view/throw a exception. Currently it throws a exception as I am also having issues with rendering a simple view.

I come from days before frameworks, and am really in over my head. :(

Anyways, here is an example of what I have in place. It does nothing. I think because I am not using the $event variable.

autostart.php


	<?php


	Yii::app()->moduleManager->register(array(

		'id' => 'devmode',

		'class' => 'application.modules.devmode.DevModeModule',

		'import' => array(

			'application.modules.devmode.*',

		),

		// Events to Catch 

		'events' => array(

			array('class' => 'AdminMenuWidget', 'event' => 'onInit', 'callback' => array('DevModeEvents', 'onAdminMenuInit')),

			array('class' => 'TopMenuWidget', 'event' => 'onInit', 'callback' => array('DevModeEvents', 'devBlock')),

			array('class' => 'DashboardSidebarWidget', 'event' => 'onInit', 'callback' => array('DevModeModule', 'onSidebarInit')),

			),

	));



DevModeEvents.php


	<?php

	/**

	 * Defines the module events

	 *

	 * @package humhub.modules.devmode.events

	 * @author Jordan Thompson

	 */


	class DevModeEvents {

		

		public static function onAdminMenuInit($event)

		{

			$event->sender->addItem(array(

				'label' => Yii::t('devmode.base', 'Development Mode'),

				'url' => Yii::app()->createUrl('//devmode/config/config'),

				'group' => 'settings',

				'icon' => '<i class="fa fa-lock"></i>',

				'isActive' => (Yii::app()->controller->module && Yii::app()->controller->module->id == 'devmode' && Yii::app()->controller->id == 'admin'),

				'sortOrder' => 300,

			));


		}	

		

		public static function devBlock($event) {

			

                        // Nothing happens when this code is triggered. 

			$devMode = HSetting::Get('devMode', 'devmode');

			if ($devMode == 1 ) {

				if (!Yii::app()->user->isGuest) {

					if (!Yii::app()->user->isAdmin()) {

						throw new CHttpException('418', Yii::t('devmode.base', Yii::app()->name . ' is currently under maintenance, check back later.'));

					}

				} else {

					throw new CHttpException('418', Yii::t('devmode.base', Yii::app()->name . ' is currently under maintenance, check back later.'));

				}

			} 

			

		}


	}



type cast the devmode to int before you do the comparison in some cases if you compare string and an int it returns false, what if you change it like so


if ((int) $devMode == 1 )

That is not the issue this is me learning how to hook a global event. The system sets the value and it will be true to a int every time. So


$devMode == 1

simply checks if the variable is true/false, and since it never gets anything but a int input, it will be fine. I could simple use


if($devMode)

if I really wanted. The code works fine if placed in the Widget View to disable the Dashboard view. But I need a global event so the whole system is disabled to guests/members.

I figured I could use a callback from the TopMenuWidget as it appears on almost all the pages. I’m sure there is a better method to attach it to the whole system. But not very familiar with the system nor a simple list of targets.

I think the reason nothing happens is because you created a module (DevModeModule) and placed all your event declarations in there. I don’t think you can call more than 1 module at once, and everything in HumHub after a quick look at the source code already seems to revolve around calling its own modules (Dashboard module for instance) when serving pages. I think what you can do is attach events to something more global, like the WebApplication component.

Create a new component that extends from WebApplication.php and override its init() function, attaching events at the top the same way the application would attach its own events through the HInterceptor class . Something like this might work:

protected/components/MyWebApplication.php




class MyWebApplication extends WebApplication

{

    protected function init()

    {

        // List out your events here

        $events = array(

            // Attach an event handler to self, to be called during the onInit event. This event gets called automatically when HumHub initializes the WebApplication component 

            array('class' => 'MyWebApplication', 'event' => 'onInit', 'callback' => array('MyWebApplication', 'devBlock')),

        );

        foreach ($events as $event) {

            Yii::app()->interceptor->preattachEventHandler(

                $event['class'], $event['event'], $event['callback']

            );

        }

        

        // Call parent WebApplication::init();

        parent::init();

    }


    // Define your event callback methods here (or on a separate file if you wanted to, like DecM)

    public static function devBlock($event) {

        // Nothing happens when this code is triggered. 

        $devMode = HSetting::Get('devMode', 'devmode');

        if ($devMode == 1 ) {

            if (!Yii::app()->user->isGuest) {

                if (!Yii::app()->user->isAdmin()) {

                    // Throw CHttpException

                }

            } else {

                // Throw CHttpException

            }

        }

    }

}



Make sure you use this class instead of WebApplication.php

index.php




$yii = dirname(__FILE__) . '/protected/vendors/yii/yii.php';

$config = dirname(__FILE__) . '/protected/config/main.php';

$appClass = dirname(__FILE__) . '/protected/components/WebApplication.php';

$myWebApplication = dirname(__FILE__) . '/protected/components/MyWebApplication.php';


// Disable these 3 lines when in production mode

defined('YII_DEBUG') or define('YII_DEBUG', true);

defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL', 5);

ini_set('error_reporting', E_ALL);


require_once($yii);

require_once($appClass);

require_once($myWebApplication);


$app = Yii::createApplication('MyWebApplication', $config);


Yii::import('application.vendors.*');

EZendAutoloader::$prefixes = array('Zend', 'Custom');

Yii::import("ext.yiiext.components.zendAutoloader.EZendAutoloader", true);

Yii::registerAutoloader(array("EZendAutoloader", "loadClass"), true);


$app->run();



I did this in a hurry, didn’t test it much so I can’t guarantee that this will work (and is what you actually need)

Hmm in other words it cannot be a module because it has to edit index.php and I might as well just add it to WebApplication. Thanks.

My initial thought is it won’t work as a module because modules are supposed to act like applications of their own.

I believe the WebApplication component though is the entry point for the system so I figured I would start from there, extend it and apply events from there.

Wait are they? Modules are inherently a extension of a modular application. Not a suppose to act like a separate application, but part of the application.

Sorry, yeah that’s what I meant. Applications that live inside your main app.

Hmm. Not sure how HumHub expects Modules to do complex tasks then. There is a lot I’d like to do and while learning the framework is frustrating enough, it’s more-so to end up at continuous dead-ends. Part of the reason I make my own ‘frameworks’ for my applications of sorts and add functionality as I need it.

well I was merely pointing it out, if you compare int to a string it is false

Thanks, that pretty common. But when dealing with a int, and knowing it will be; doesn’t matter. That is something you use when handling a string from foreign input.

He is just comparing values by not doing a strict comparison so his code works out just fine.

Back on topic, does humhub not have any documentation for developers? Maybe try asking the devs on github for suggestions on hooking up your own events

Well I finally figured it out from one of the developers who’s helped me a lot when he has time.

[size="5"]HumHub Documentation[/size]

Also, for reference here is the event I am now using in autostart.php to hook globally


array('class' => 'Controller', 'event' => 'onBeforeAction', 'callback' => array('DevModeModule', 'devBlock')),