Change theme based on param url - magento

I would like to know if I can change the theme based on url parameter (or if it's too late) and if it is possible which is the right event to observe
I have only found a guy who was talking about observing controller_action_predispatch but with this event I can't still access to the parameters url (based on this answer https://stackoverflow.com/a/19214765/1139052)

Yes, you could do that a number of different ways. That answer is not saying the URL params are inaccessible in the controller_action_predispatch event, however you might want to do it during an event like controller_action_layout_load_before instead and create custom layout handles from your param value. You can get them in your observer like this:
public function getExampleParam(Varien_Event_Observer $observer)
{
$request = $observer->getControllerAction()->getRequest();
$param = $request->getParam('example');
return $this;
}

Related

Call an index controller with parameter

So basically, I have a setup of restful controller in my route. Now my problem is how can I call the Index page if there is a parameter.. it gives me an error of Controller not found
Im trying to call it like this www.domain.com/sign-up/asdasdasd
Route::controller('sign-up','UserRegisterController');
then in my Controller
class UserRegisterController extends \BaseController {
protected $layout = 'layouts.unregistered';
public function getIndex( $unique_code = null )
{
$title = 'Register';
$this->layout->content = View::make( 'pages.unregistred.sign-up', compact('title', 'affiliate_ash'));
}
By registering:
Route::controller('sign-up','UserRegisterController');
You're telling the routes that every time the url starts with /sign-up/ it should look for corresponding action in UserRegisterController in verbAction convention.
Suppose you have:
http://domain.com/sign-up/social-signup
Logically it'll be mapped to UserRegister#getSocialSignup (GET verb because it is a GET request). And if there is nothing after /sign-up/ it'll look for getIndex() by default.
Now, consider your example:
http://domain.com/sign-up/asdasdasd
By the same logic, it'll try looking for UserRegister#getAsdasdasd which most likely you don't have. The problem here is there is no way of telling Route that asdasdasd is actually a parameter. At least, not with a single Route definition.
You'll have to define another route, perhaps after your Route::controller
Route::controller('sign-up','UserRegisterController');
// If above fail to find correct controller method, check the next line.
Route::get('sign-up/{param}', 'UserRegisterController#getIndex');
You need to define the parameter in the route Route::controller('sign-up/{unique_code?}','UserRegisterController');. The question mark makes it optional.
Full documentation here: http://laravel.com/docs/routing#route-parameters

Observe customer account verification event in Magento

Is there a way to catch the event when the customer verifies it's account? I need this feature to enable user's access to other integrated subsystem
Since confirmAction() doesnt seem to fire any events in
/app/code/core/Mage/Customer/controllers/AccountController.php
You could do either
Overriding Frontend Core Controllers to create you own event using Mage::dispatchEvent() or add code directly to confirmAction in AccountController.php
Use #Pavel Novitsky answer but you may need to check that you are on the confirm account controller or check for the changing of email verification flag, because this event will trigger every time a customer information is change/updated
eg
public function myObserver(Varien_Event_Observer $observer)
{
if(Mage::app()->getRequest()->getControllerName() == '....account_confirm'){
$customer = $observer->getCustomer();
....
}
}
Every model has standard load_before, load_after, save_before, save_after, etc. events. Look at the Mage_Core_Model_Abstract to get the list of all predefined events.
For customers you can use customer_save_after event. In observer check original data vs new data:
public function myObserver(Varien_Event_Observer $observer)
{
$customer = $observer->getCustomer();
$orig_active_flag = $custoner->getOrigData('is_active');
$new_active_flag = $customer->getData('is_active');
// do something here …
return $this;
}
Even you can create your own event after customer vefication using below code.
Mage::dispatchEvent('Yuor_Unique_Event_Name', array());
Now using this event you can do anything you want.

Magento Observer generate errors and Magento areas confusing

I've made controller_front_init_routers event observer, which retrieves data from a REST service to construct a menu.
All was ok until I discovered that the observer generates errors in the backend (no way to save products for example) and also in the rest services.
I am struggling for any conclusions, So I raised some interrogations.
I tried to make a condition in order to trigger my Observer
methods in case we are in frontend only. But Magento considers that we are
always in frontend area.
(var_dump(Mage::app()->getStore()->isAdmin()) return always false
and the same with var_dump(Mage::getDesign()->getArea() ==
'adminhtml'))
Can anyone explain what's happened ?
Also one solution is to place the event observer in frontend
area in the config.xml and to load it with
Mage::app()->loadArea($this->getLayout()->getArea()); but where should I
place this piece of code ? in a new observer ? Is that the most
appropriate process ?
Is it a way to listen once an event then to pause the listener?
(once my menu is registered, I don't need to listen to the event any more)
Is the use of controller_front_init_routers event the best choice ?
Who has ever seen that kind of problem ?
I work on Magento ver. 1.12.0.2
Here the config.xml
<globals>
....
<events>
<controller_front_init_routers>
<observers>
<connector_services_observer>
<type>singleton</type>
<class>Connector_Services_Model_Observer</class>
<method>getEvent</method>
</connector_services_observer>
</observers>
</controller_front_init_routers>
</events>
</globals>
Here the function getEvent in my model observer
public function getEvent($observer){
//model which do post or get requests and return xml and menu
$_getRest = Mage::getModel('connector_services/RestRequest');
//the paths
$_menu_url = Mage::getStoreConfig('connector_service_section/connector_service_url/service_menu_url');
//put a store config
$path_nlist = 'veritas-pages-list.xml';
$_isAdmin = Mage::helper('connector_services');
$currentUrl=Mage::helper("core/url")->getCurrentUrl();
//the way I found to trigger methods only in frontend
//that's not very beautiful I know
$admin = preg_match("#/admin/#",$currentUrl);
$api = preg_match("#/api/#",$currentUrl);
//
if ( !$admin && ! $api ){
$_menuXml = $_getRest->postRequest($_menu_url);
if( $_menuXml )
{
$_menu = $_getRest->makeMenu($_menuXml);
Mage::register('menu',$_menu);
}
}
You should be able to pass a querystring to the rest service, similar to how you'd just type it out in the address bar. Magento will forward it on to the observer, and you can use it as a flag.
Add something like the following to your code:
const USE_FRONTEND = 'usefront';
public function getEvent($observer){
this->request = $observer->getEvent()->getData('front')->getRequest();
// If the constant is in the query string
if ($this->request->{self::USE_FRONTEND}) {
// Do code related to this request
die('Frontend flag detected');
}
}
Call to your site like this and pass the querystring
http://www.yourmagentosite.com/?usefront=true
I am not extremely familiar with Magento's new REST api, but I know it works in the browser. Maybe this explanation can help you out.

Symfony2: Change rendered view with a listener

I would like to render different views in different context in my Symfony2 project.
I'm using multiple routes for the same actions and I would like to render a different page (view) but with the same controller.
For example I have:
#Route("/articles/show", name="articles_show")
#Route("/mobile/articles/show", name="mobile_articles_show")
Both routes are using the same action : ArticlesController:showAction(), but should render 2 differents templates (for mobile users and regulars ones).
show.html.twig
mobile.show.html.twig
I do not want to use a if statement or whatever in my controller, so I created a listener (similar to a preExecute function)
Here is a part or my config.yml that defines my listener
services:
controller.pre_execute_listener:
class: MyProject\MyBundle\Listener\ControllerListener
arguments: ["#security.context", "#doctrine", "#router", "#session"]
tags:- { name: kernel.event_listener, event: kernel.controller, method: preExecute }
I was thinking about doing something like that in the listener preExecute function:
if(substr($route,0,7) == 'mobile_'){
$view = 'mobile.'.$view;
}
Unfortunately I cannot find a way to get $view or update the view "on the fly", just before it's rendered.
I hope my question is clear enough, thanks in advance, any idea is welcome :)
J.
Here is the solution:
First I have to listen to kernel.view, not kernel.controller.
Then I use the "#templating" service (Thanks Marko Jovanovic for the hint)
So here is my new config.yml:
services:
controller.pre_execute_listener:
class: MyProject\MyBundle\Listener\ControllerListener
arguments: ["#templating"]
tags:
- { name: kernel.event_listener, event: kernel.view, method: preExecute }
Finally here is my listener preExecute function
public function preExecute(\Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent $event){
//result returned by the controller
$data = $event->getControllerResult();
/* #var $request \Symfony\Component\HttpFoundation\Request */
$request = $event->getRequest();
$template = $request->get('_template');
$route = $request->get('_route');
if(substr($route,0,7) == 'mobile_'){
$newTemplate = str_replace('html.twig','mobile.html.twig',$template);
//Overwrite original template with the mobile one
$response = $this->templating->renderResponse($newTemplate, $data);
$event->setResponse($response);
}
}
Hope this helps!
J.
Worth noting: The accepted solution doesn't actually work if you directly return a Response-object (e.g. when you call $this->render()), because the kernel.view event is not fired in that case:
If the controller doesn't return a Response object, then the kernel dispatches another event - kernel.view.
— see Symfony's HTTP Kernel Docs
I couldn't work out a way around this, but found another interesting solution for the same problem:
You could simply extend twig's render engine like the ZenstruckMobileBundle does or write your own file locator like the LiipThemeBundle.
[edit:] Alternatively you could also override the TemplateNameParser.
You can add "#templating" service as argument for the controller.pre_execute_listener.
It seems your device detection is done before you come to your route, so I bet you expect that mobile user will use the mobile routes thanks to some detection before the request, this seems to be painful to deal with in every templates and url generation.
May be better to detect device either before or later (thanks to Categorizr or some nice apache configuration) but not relying on used route for the mobile detection.
An integration of Categorizr with that way of calling templates rendering might be nice.
Then using a nice bundle for using the right templates/themes or using one which provides some more generic functions

Magento: Obtain Id for order, listening to the event checkout_onepage_controller_success_action

When I look at the event checkout_onepage_controller_success_action and works, but I can not get the Id of the newly created order.
Anyone have any idea??
Use magento-1.4.1.0
Thanks
The event is dispatched like this:
Mage::dispatchEvent('checkout_onepage_controller_success_action', array('order_ids' => array($lastOrderId)));
So to get the last orderId, simply make your observer method like this:
public function orderSuccessEvent($observer)
{
$observer->getData('order_ids'));
}
This is an answer provided by Branko Ajzele and I've just successfully tested:
$order = new Mage_Sales_Model_Order();
$incrementId = Mage::getSingleton('checkout/session')->getLastRealOrderId();
$order->loadByIncrementId($incrementId);
Thanks to him and hope it'll work.
That event probably gets called before the action itself executes. Can you use sales_order_save_after instead?
EDIT: Here's your ID code. In your observer:
public function setLinkStatus($observer) {
$order = $observer->getEvent()->getOrder();
$id = $order->getId();
// do something useful
}
The Onepage Checkout controller in the Magento version 1.4.1 is not updated to have functions that can obtain the Order ID and thus you cant have the order object and data from the event observer. To have this working in Magento 1.4.1 simply update your OnepageController with the necessary functions.
The best approach would be to create your own module and override the core controller.
Add this in the config xml of your module so that your controller is called before the core OnepageController.
<frontend><routers><checkout><use>standard</use><args><modules><MyCompany_MyModule before="Mage_Checkout">MyCompany_MyModule</MyCompany_MyModule></modules></args></checkout></routers></frontend>
Hope this helps

Resources