Any Good Sendfriend Event Dispatch in Magento? - magento

Looking for a decent observer of the Mage_Sendfriend module, when the product is sent to a friend. I just traced it and don't see anything immediately useful. There is one dispatch written in the module, which actually fires when the send to friend form is loaded, not when it's actually submitted.

Looking at the events triggered, here are some events you might use:
controller_action_postdispatch_sendfriend_product_sendmail
controller_action_postdispatch_sendfriend
controller_action_postdispatch
And in the function you want to use for this event:
$controller = $observer->getControllerAction();
... your code here

You might have to resort to observing the model_save_after and model_save_before events, then checking $observer->getEvent()->getObject() to see if it's the Mage_Sendfriend model you're looking for.
An ugly solution, but sometimes the events just don't line up to solve a problem nicely.
Good luck! Let us know if you find anything good!
Edit: I would also suggest against observing a controller for this, though, since that isn't very modular. If a third-party module provides another interface for the Sendfriend feature, it wouldn't work with your module if you observe controller actions.

You can dispatch custom events when and where you want.
Mage::dispatchEvent('any_name_for_your_custom_event',
array('key'=>$value,'key'=>$value,'key'=>$value)); //can pass how many values you want in this array.
And in your config you just make your nodes to look for this event, and call one method from observer.
Its simple.

Related

Laravel - can I bind an event to a notification?

First, I'll describe the context.
I have a lot of notifications that refering to changes in the Offer, for example: offerEditedBySeller, offerEditedByAdmin, offerTurnOff, etc. They are triggered in many places in controllers.
Now I'm implementing an expanded cache and I want to make the event OfferChange in which the cache for specific offer will be reloaded. First, I wanted to trigger these notifications in events, but I realized that to make it work, I'll have to duplicate every notification.
For example, let's assume I have the event( new OfferEdited() ). Its listeners will be RefreshCacheForOffer, SendNotificationsAboutOfferEdit etc. For every notification like offerEdited I need to create listener SendNotificationsAboutOfferEdit, which just trigger specific Notification. I think it's not what I want to reach.
Is there a way to bind events/listeners with a notification? No matter if it would be offerEdited, offerApproved or offerDisapproved it would be bind with the event OfferChange, which would trigger the listener RefreshCacheForOffer and the specific job next. This way I wouldn't have to change the code in every controller's action and create a lot of unnecessary events and listeners. Is it possible?
Edit:
I know I can just do:
$user->notify(new offerEdited($offer));
event( new OfferChange($offer) );
But I hope there is a way to better organize it.
To avoid changing lots of code in your controllers you could model it inside your Model and pick up on the 'created' or 'updated' events of the model, and then call subsequent events.
class Offer extends Model
{
protected static function booted()
{
static::updated(function ($user) {
// check for condition and trigger event such as OfferEditedBySeller
});
}
}
If you want to use event/listener architecture then I think one event and listener for ever notification is the way you have to go.
Alternatively, don't bother with events/listeners - just send your notifications from the controller or from the 'created' or 'updated' events of the model. Cut out the middleman (events/listeners) and you'll have more explicit code which is easier to follow.
Events/listeners are good when you need to decouple and abstract - but if you are doing explicit things then not using them might be simpler for you.

Rails 3: Ensure before_save callback is called after others

Is there a way to ensure that a given before_save callback is executed after all other before_save callbacks in ActiveRecord short of actually ordering them so in the code?
I'm writing an external library that includes some before_save functionality but in order to be effective it really needs to be called after all others. I can get around it but it involves giving up dirty attributes which I really don't want to!
-- edit --
I didn't realise in this that dirty attributes are maintained after the save of the model. So #page.attribute_was will still work after the yield in an around_save.
You could make the callback you want executed last an around_save callback. Check out the list of available callbacks and see if you can simply use a different callback "bucket" for some of your callbacks to ensure they are executed in the desired order.
If you still end up with multiple before_save callbacks and need one to trigger last, you may want to create custom callbacks, like maybe define_model_callbacks :split_save, registering your regular before_save callbacks as before_split_save callbacks, the one you want executed last as a after_split_save callback, and then just a single before_save callback that runs those two groups of callbacks (run_callbacks :split_save). See ActiveModel::Callbacks for more on how to do this.
So this was to get around giving up dirty attributes by using ordered before_<type> callbacks instead of after_<type> callbacks, since dirty attributes changes get wiped after saving.
It turns out, however, that the changes are still accessible in after_<type> callbacks.
I only worked this out after trawling through Vestal Versions code to see how they did it.
Facepalm.
I'm accepting Carl's answer because it's a pretty complete answer to the rather badly presented question.

Creating logs from controllers in CakePhp

What is the best way to create logs & history in CakePHP. I was thinking if there is a way to create a Helper "that accesses" one table and then I call this helper inside of each controller that I want. However, I have read that this is not MVC standard. How would it be the correct way to do that?
I appreciate your time spent answering me that. Thanks!
thats what behaviors are for.
I use the LoggableBehavior from here:
https://github.com/alkemann/CakePHP-Assets/blob/master/models/behaviors/logable.php
works like a charm. they are then fetched and displayed in the view, if you want to.
Just implement a different log engine for that purpose. The CakeLog class actually works somewhat like an observer and the log engines like listeners.
Simply use CakeLog::write() and your custom engine that could load your log model in the constructor using ClassRegistry::init() and pass the incoming data from write() to the model.
The manual will help you with that. http://book.cakephp.org/2.0/en/core-libraries/logging.html#creating-and-configuring-log-streams

Create a plugin, expose events

How do I expose events to my plugin users?
I know that I should use:
$('#myPluginDiv').trigger('eventName', ["foo", "bar"]);
to trigger the event but I'm looking for best practices describing how to declare and invoke events in plugins.
I think you can inspect some of the most used plugins and make your own assumptions. We have no standards on this, just code convention.
Colorbox (source: https://github.com/jackmoore/colorbox/blob/master/jquery.colorbox.js) defines a prefix and some constants for the event names. It also have a function for triggering and running the callbacks.
jQuery UI (source: https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js) also have a common function on the widget class for triggering events (usage: https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.dialog.js), but you can see that the events are hard coded on the middle of the source, instead of constants on the top like on Colorbox.
I personally think, and do it in my own plugins, that creating constants is much better if you have a lot of events to trigger, but its not necessary if you will fire only 2 or 3 events.
A helper function is a must have and should be part of your template.
The event names I use and see around all follow the standard CamelCase e.g. beforeClose.
Some advocate the use of a prefix for events like on Colorbox's cbox_open or even click.myPlugin (see: http://api.jquery.com/on/#event-names)
Conclusion: try to follow best practices and conventions for programming in general and watch for the better examples out there.
in plugin create object litereal like
var plugin = {
show:function(){
// code for show()
}
};

Magento: What is the best way to extend Magento to add a class that is called on every page load

I am looking to create some new functionality to Magento. I am going to be looking to the url and grabbing a parameter. The issue is, this can be on any page. So I can't just extend a Catalog or Checkout Module.
I thought about extending the session classes but I wasn't sure it really fit. Basically I want to grab a parameter from the url and from there add some functionality if it is set or not. I don't think a class will get auto loaded unless it is instantiated somewhere else with a getModel method, am I wrong?
How can you add a module that doesn't have a url path for controller and what not, but doesn't fit extending one of the core modules?
I looked for a generic event but didn't really see one like before_page_load or something
Take a look at the event controller_action_predispatch in app/code/core/Mage/Core/Controller/Varien/Action.php. This event should get called on each dispatch and allow you to grab whatever parameters you need.
The event passes the controller as data, so you can do this:
function yourEvent( $event ) {
$controller = $event->getController();
// your processing here
}
Let me know if that doesn't fit the bill. Hope that helps!
Thanks,
Joe

Resources