News:

You may pay someone to create your store, or you visit our seminar and become a professional yourself with the silver certification

Main Menu

Issues with controller override

Started by jvhm, November 10, 2013, 18:25:05 PM

Previous topic - Next topic

jvhm

Hello everyone!

I'm having some issues on trying to override a core controller in Virtuemart (specifically, the 'VirtuemartControllerPaymentmethod' in 'administrator/components/com_virtuemart/controllers/paymentmethod.php') and I'll try to explain exactly what I'm doing so far and what the issues are.

First of all, as I wanted to override the core controller, I created a system plugin with the following code:


public function onAfterRoute() {
          $app = JFactory::getApplication();
          if('com_virtuemart' == JRequest::getCMD('option') && 'paymentmethod' == JRequest::getCMD('view') && $app->isAdmin()) {
          if (!class_exists( 'VirtuemartControllerPaymentmethod' ))
          require_once(OVERRIDES . DS . 'virtuemart' . DS. 'controllers' . DS . 'paymentmethod.php');
        }
    }


After running the page "WWWROOT/administrator/index.php?option=com_virtuemart&view=paymentmethod", I've got the error:

QuoteFatal error: Cannot redeclare class VirtuemartControllerPaymentmethod in xxxxxxx/administrator/components/com_virtuemart/controllers/paymentmethod.php on line 57

So, basically, this erros is telling me that Virtuemart is trying to require a file which declares the same class again, which is, obviously, the file "paymentmethod.php" from the core structure. Conclusion: my plugin is actually doing the right thing: it calls the class definition before Joomla/VirtueMart calls the core definition. So, if I run the code below inside my plugin, before it calls the file, I can see that "VirtuemartControllerPaymentmethod" isn't declared yet, so it's not my plugin that is trying to redeclare any class.


print_r(get_declared_classes());


With that in mind, I started looking for the place where VirtueMart is trying to redeclare "VirtuemartControllerPaymentmethod", i.e., where it's trying to call the "com_virtuemart/controllers/paymentmethod.php" file. And the place is at line 55 of file "admin.virtuemart.php":


// Require specific controller if requested
if($_controller = JRequest::getWord('view', JRequest::getWord('controller', 'virtuemart'))) {
if (file_exists(JPATH_VM_ADMINISTRATOR.DS.'controllers'.DS.$_controller.'.php')) {
// Only if the file exists, since it might be a Joomla view we're requesting...
require (JPATH_VM_ADMINISTRATOR.DS.'controllers'.DS.$_controller.'.php');
} else {
// try plugins
JPluginHelper::importPlugin('vmextended');
$dispatcher = JDispatcher::getInstance();
$results = $dispatcher->trigger('onVmAdminController', array($_controller));
if (empty($results)) {
$app = JFactory::getApplication();
$app->enqueueMessage('Fatal Error in maincontroller admin.virtuemart.php: Couldnt find file '.$_controller);
$app->redirect('index.php?option=com_virtuemart');
}
}
}


As you can see, on the excerpt "require (JPATH_VM_ADMINISTRATOR.DS.'controllers'.DS.$_controller.'.php');", VirtueMart is calling a file without verifying if any class exists or not. Maybe I'm wrong, but it seems like a flaw to me. As a tested, I could overwrite, for example, a class inside a "view.html.php" file without a problem with my plugin, but it's really not working for controllers. And also, if I commented that line, it would work.

So, I'd like to know if there's something I can do about it without needing to hack the core.

And, just to finish, so no one gets lost on what I'm developing: I'm developing a Payment Method plugin, like PayPal, for a company. And one of the reasons I need to override this class: I need to override the "save()" method because I need to do some really specific validations in the moment of saving the plugin configurations (among other things I'll need to customize during the development).

Thanks in advance.
Best regards.
Cheers!