Post by JeffroDH » Fri Jul 01, 2016 9:56 pm

Good day. I posted this in general support, but realized that this section may be more appropriate.

I'm attempting to hook into a function using opencart's event system in order to include a class that automatically updates a product's image and description from a source on the internet.

I've got it successfully firing after the addProduct method in the admin side, but can't seem to get it to fire after a protected method in an extension I've got installed. (Import/Export 3.3)

Here's the relevant code for the install/uninstall routine in my module.

Code: Select all

public function install() {
		$this->load->model('extension/event');
		$this->model_extension_event->addEvent('jeffrodh_scrapeComics', 'admin/model/catalog/product/addProduct/after', 'module/scrape_comics');
		$this->model_extension_event->addEvent('jeffrodh_scrapeComics_01', 'admin/model/tool/export_import/storeProductIntoDatabase/after', 'module/scrape_comics/on_import');
		$this->log->write('Installation Successful: Scrape Comics');
	}
	
	public function uninstall() {
		$this->load->model('extension/event');
		$this->model_extension_event->deleteEvent('jeffrodh_scrapeComics');
		$this->model_extension_event->deleteEvent('jeffrodh_scrapeComics_01');
		$this->log->write('Uninstallation Successful: Scrape Comics');
	}
And the index:

Code: Select all

public function index($data, $product_id) { //Interesting stuff happens } 
and the alternative method:

Code: Select all

public function on_import($route, $product) { //Interesting stuff happens } 

Additionally, I don't really understand where the $product_id is being passed FROM in the first example. I plugged in variables from the admin/model/catalog/product.php and it just worked. Therefore, I'm not certain that I'm going to be able to successfully pass variables from the other model into this event given that the storeProductIntoDatabase method is protected within its parent class. Documentation is almost nonexistent, and if someone would be willing to pass along some knowledge, I think this could really benefit the community.

Many thanks in advance.

Active Member

Posts

Joined
Thu Jul 11, 2013 8:29 am

Post by inactiveaccount9912 » Sat Jul 02, 2016 7:40 pm

Since its private then it is called from within the class so the callback method from loader isnt used (and that is where the model events get loaded). Maybe you could link it to the method calling the private one if its not called from within as well.
As for the product_id, it is beeing returned by the addProduct method, and since your event is after, the return is added to args.

Expert Member

Posts

Joined
Fri May 14, 2010 2:36 am

Post by JeffroDH » Wed Jul 06, 2016 8:16 am

florinsith wrote:Since its private then it is called from within the class so the callback method from loader isnt used (and that is where the model events get loaded). Maybe you could link it to the method calling the private one if its not called from within as well.
As for the product_id, it is beeing returned by the addProduct method, and since your event is after, the return is added to args.
... The private method in question is called at the end of another, rather lengthy public function... What would the implications be of simply making the method public?

Also, are you saying that all of the variables within the scope of the triggering method are available to be passed (by name) to the triggered method?

Active Member

Posts

Joined
Thu Jul 11, 2013 8:29 am

Post by inactiveaccount9912 » Thu Jul 07, 2016 12:37 am

JeffroDH wrote:Also, are you saying that all of the variables within the scope of the triggering method are available to be passed (by name) to the triggered method?
Input params for :before event and input params + return for :after events.
Changing it to public I dont think will solve the issue because it would still be called inside the object. The methods supporting events are the ones called like:

Code: Select all

$this->model_route_ofmodel->methodName();
Id say since you are willing to modify that file to change the method to public then you could just modify the method and put your code in there.(or maybe via ocmod)

Expert Member

Posts

Joined
Fri May 14, 2010 2:36 am

Post by straightlight » Thu Jul 07, 2016 3:37 am

An additional methodology I would recommend rather than putting any method from private / protected methods would be to propagate the Opencart registry into the __construct method instead. Then, from the library / engine file, simply callback your initialized class name and reuse it into your preferred method instead. :)

To answer your question; setting the method to public would allow Opencart to access the preferred method throughout possibly the entire script as I do not fully recommend this approach for security / conflict reasons since extensions are involved with Opencart and the Object Registry from Opencart is already propagating and recalled from its engine and can be re-called at any time throughout the model files or by directly using the long object recall method manually once being passed to the method parameter.

Dedication and passion goes to those who are able to push and merge a project.

Regards,
Straightlight
Programmer / Opencart Tester


Legendary Member

Posts

Joined
Mon Nov 14, 2011 11:38 pm
Location - Canada, ON

Post by JeffroDH » Sat Jul 09, 2016 5:27 am

florinsith wrote:Input params for :before event and input params + return for :after events.
So for any event I register that is triggered ::before the Method indicated, the input parameters are available, and additionally I can access the data returned by the Method for events that are triggered ::after the Method?

I'm still fairly new to OOP, so some of the concepts are not well-grasped, and I'd like to make sure I've got it straight.
florinsith wrote: Changing it to public I dont think will solve the issue because it would still be called inside the object. The methods supporting events are the ones called like:

Code: Select all

$this->model_route_ofmodel->methodName();
Id say since you are willing to modify that file to change the method to public then you could just modify the method and put your code in there.(or maybe via ocmod)
According to the documentation, any Method can be a trigger for an event, but only a method inside a controller can be triggered. Do I have that right? If so, then my code should be able to be triggered by the method in question.

I'm attempting to include all the necessary code within an extension (that is dependent on another), such that I don't have to rewrite my extension every time the code is changed slightly in the other 3rd party extension. VQMod/OCMod are relatively vulnerable, but if I can figure out how to do this with the event system, it makes my code entirely self-contained and much cleaner.

Thanks very much for your input and time.

Active Member

Posts

Joined
Thu Jul 11, 2013 8:29 am

Post by JeffroDH » Sat Jul 09, 2016 5:33 am

straightlight wrote:An additional methodology I would recommend rather than putting any method from private / protected methods would be to propagate the Opencart registry into the __construct method instead. Then, from the library / engine file, simply callback your initialized class name and reuse it into your preferred method instead. :)

To answer your question; setting the method to public would allow Opencart to access the preferred method throughout possibly the entire script as I do not fully recommend this approach for security / conflict reasons since extensions are involved with Opencart and the Object Registry from Opencart is already propagating and recalled from its engine and can be re-called at any time throughout the model files or by directly using the long object recall method manually once being passed to the method parameter.
I understand the words that you're typing, but not what they mean when put together. I suspect that's because I don't have any knowledge of how the OC registry/engine works. I'm trying to decipher the __construct ->library->callback, but it is simply going over my head.

Active Member

Posts

Joined
Thu Jul 11, 2013 8:29 am

Post by straightlight » Sat Jul 09, 2016 5:52 am

JeffroDH wrote:
straightlight wrote:An additional methodology I would recommend rather than putting any method from private / protected methods would be to propagate the Opencart registry into the __construct method instead. Then, from the library / engine file, simply callback your initialized class name and reuse it into your preferred method instead. :)

To answer your question; setting the method to public would allow Opencart to access the preferred method throughout possibly the entire script as I do not fully recommend this approach for security / conflict reasons since extensions are involved with Opencart and the Object Registry from Opencart is already propagating and recalled from its engine and can be re-called at any time throughout the model files or by directly using the long object recall method manually once being passed to the method parameter.
I understand the words that you're typing, but not what they mean when put together. I suspect that's because I don't have any knowledge of how the OC registry/engine works. I'm trying to decipher the __construct ->library->callback, but it is simply going over my head.
There's no need to instantiate a callback from the library, in this case.

How about posting your codes so to show what you're trying to develop?

Dedication and passion goes to those who are able to push and merge a project.

Regards,
Straightlight
Programmer / Opencart Tester


Legendary Member

Posts

Joined
Mon Nov 14, 2011 11:38 pm
Location - Canada, ON

Post by inactiveaccount9912 » Mon Jul 11, 2016 4:40 pm

JeffroDH wrote: So for any event I register that is triggered ::before the Method indicated, the input parameters are available, and additionally I can access the data returned by the Method for events that are triggered ::after the Method?

According to the documentation, any Method can be a trigger for an event, but only a method inside a controller can be triggered. Do I have that right? If so, then my code should be able to be triggered by the method in question.
Yes, look at the code from the callback method in system/engine/loader.php, you have:

Code: Select all

//before
$result = $registry->get('event')->trigger('model/' . $route . '/before', array_merge(array(&$route), $args));
....
//method called
$output = call_user_func_array(array($model, $method), $args);
....
//after
$result = $registry->get('event')->trigger('model/' . $route . '/after', array_merge(array(&$route, &$output), $args));
As for the second question, not only controller, it can be a model using another model as well.

Expert Member

Posts

Joined
Fri May 14, 2010 2:36 am
Who is online

Users browsing this forum: No registered users and 4 guests