Exclude Pages from Magento Website Restrictions - magento

We have several magento websites and some of them we would like to turn on the website restriction so only logged in customers can view it. This seems to work great except we have custom pages that we want the user to be able to access without having to login. And currently if we turn on access restriction it redirects all pages, except the login page and the password reset page, to the login page.
Does anyone know how to exclude other pages from being redirected to the login page? I think it would be a layout xml setting but I can't seem to figure it out or find anything on it.
Magento Enterprise version 1.12.02

Wow, this question is pretty valid, rather old, ranked high on on Google results, yet without a good answer. So here goes one.
The right way to exclude pages from restriction is by adding them to generic list of pages under Enterprise_WebsiteRestriction module config.
See app/code/core/Enterprise/WebsiteRestriction/etx/config.xml and config/frontend/enterprise/websiterestriction section in particular. Pages under full_action_names/generic are always accessible no matter what restriction level is set. Those in full_action_names/register are still accessible when restriction mode is set to "Login and Register" - i.e. they are intended for new registration to be possible.
The values under those sections are full actions names (i.e. <module>_<controller>_<action>), so e.g. to enable contact form for everyone, you need to add contacts_index_index to the generic list.
Note that editing files in core codepool is strongly discouranged, so to achieve this it's best to create your own module and add the configuration section.
It should look somewhat like this (remember to enable this module in app/etc/modules):
<?xml version="1.0"?>
<config>
<modules>
<Emki_WebsiteUnrestrict>
<version>0.1.0</version>
</Emki_WebsiteUnrestrict>
</modules>
<frontend>
<enterprise>
<websiterestriction>
<full_action_names>
<generic>
<contacts_index_index />
</generic>
</full_action_names>
</websiterestriction>
</enterprise>
</frontend>
</config>

Nick,There are several process for this function...
Step1:you can it from Controllers from using dispatch event.
/**
* Retrieve customer session model object
*
* #return Mage_Customer_Model_Session
*/
protected function _getSession()
{
return Mage::getSingleton('customer/session');
}
public function preDispatch()
{
// a brute-force protection here would be nice
parent::preDispatch();
if (!$this->getRequest()->isDispatched()) {
return;
}
$action = $this->getRequest()->getActionName();
/* put all action of this controllers for check ,if any actions of list is exit then redirect to login page*/
$openActions = array(
'index',
'post',
'autoy',
'confirmation'
);
$pattern = '/^(' . implode('|', $openActions) . ')/i';
if (!preg_match($pattern, $action)) {
if (!$this->_getSession()->authenticate($this)) {
$this->setFlag('', 'no-dispatch', true);
}
} else {
$this->_getSession()->setNoReferer(true);
}
}
/**
* Action postdispatch
*
* Remove No-referer flag from customer session after each action
*/
public function postDispatch()
{
parent::postDispatch();
$this->_getSession()->unsNoReferer(false);
}
Other thing is Using observer

Related

Magento: Navigation static page directly to specific product

I would like to add a static link at the navigation bar that can link directly to a specific product.
As I only have one product listing under category "pillow", I wish to set it to go into the product directly, skipping the catalog view.
I am aware of two methods, being URL rewrite management and static block, however I experience problem with both.
For "URL rewrite", it worked but once I update something at the category (e.g. moving the position), the system generate a new "URL rewrite" and delete the my custom one.
For "static block", I do not know what code to put in it. My guess was to add below code, but it doesn't work.
{{block type="catalog/product_view" product_id="896" template="catalog/category/view.phtml"}}
How do I get it done? Thanks in advance.
I have taken a different approach to the problem which may be helpful. It seems like your end goal is to skip the category view if a category only contains one product. So rather than fussing with hard coding templates or trying to clobber the category with URL rewrite, you can accomplish this using an event observer.
The approach will listen for the <catalog_controller_category_init_after> event to fire and check whether the category only has one product. If so it will send the request directly to the product. You will need to add a new extension or modify an existing one.
etc/config.xml
Create a new node under config/frontend/events:
<catalog_controller_category_init_after>
<observers>
<redirectSingleProduct>
<class>My_MyExtension_Model_Observer</class>
<method>redirectSingleProduct</method>
</redirectSingleProduct>
</observers>
</catalog_controller_category_init_after>
Model/Observer.php
Create the corresponding method to handle the event:
class My_MyExtension_Model_Observer
{
/**
* Check whether a category view only contains one product, if so send the request directly to it.
* #param Varien_Event_Observer $observer
* #return $this
*/
public function redirectSingleProduct(Varien_Event_Observer $observer)
{
$category = $observer->getCategory();
if ($category->getProductCount() == 1) {
$product = $category->getProductCollection()->addUrlRewrite()->getFirstItem();
$url = $product->getProductUrl();
$observer->getControllerAction()->getResponse()->setRedirect($url);
}
return $this;
}
}

Magento - Redirect on Login via Observer

I am trying to redirect specific users in Magento to the products.html page after logging in. Most every way I attempt to do this (setRedirect, header) results in a loop due to too many redirects.
Currently, I am trying to use an observer to setParam('return_url', "$customerRedirectUrl") as described in this rather popular post - Magento - Redirect Customer from Observer Method. The variable $customerRedirectUrl represents logic that together reliably creates the url I know I want the page to be. My relevant code looks like this.
public function redirect(Varien_Event_Observer $observer)
{
$helper = Mage::helper('personal_order');
$isPersonalOrderStore = $helper->isPersonalOrderStore(null);
$session = Mage::getSingleton('customer/session');
if ($isPersonalorderStore){
if(!$session->isLoggedIn()) {
$targetUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB).'customer/account/login';
Mage::app()->getResponse()->setRedirect($targetUrl);
} else {
$baseUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
$storeName = strtolower(Mage::app()->getStore()->getName());
$storeName = str_replace(' ', '', $storeName);
$customerRedirectUrl = "$baseUrl$storeName/products.html";
$observer->getRequest()->setParam('return_url',"$customerRedirectUrl");
}
}
The important part for my purposes now is the else statement, the rest of the function works fine. However, the call to setParam results in the following error:
Fatal error: Call to a member function setParam() on a non-object...
What about the Magento - Redirect Customer from Observer Method post am I not getting (there is a good chance I'm just oblivious to something due to being a fairly new user)? The observer is laid out in the relative config file under controller_action_postdispatch and is in an observer model. What is the context for getting setParam to operate correctly?
Thanks to any and all for your help!
I know this post is a bit old but I see have it worked out for a module of my own.
I run the redirect on 2 different events. When the customer registers or when a customer logs in.
<customer_register_success>
<observers>
<redirectAfterRegister>
<class>businessdirectory/profile_observer</class>
<method>redirectAfterRegister</method>
</redirectAfterRegister>
</observers>
</customer_register_success>
<customer_login>
<observers>
<redirectAfterLogin>
<class>businessdirectory/profile_observer</class>
<method>redirectAfterLogin</method>
</redirectAfterLogin>
</observers>
</customer_login>
I edited this answer because after testing I realized that two separate observers are needed for the two events. The good news is that you do not need to override files or rewrite controllers.
For the customer_register_success event, all you need to do is set the success_url param to whatever you want the url to be.
For the customer_login event, you will notice in your controller customer/account/_loginPostRedirect that the redirect URLs are being set on the customer session. As you can see in the second observer method below, all you need to do is grab the customer session and set the URL. For my purposes, I set the BeforeAuthUrl and AfterAuthUrl.
public function redirectAfterRegister($observer)
{
if(Mage::app()->getRequest()->getParam('listing_id') || Mage::app()->getRequest()->getParam('directory_id')){
$_session = Mage::getSingleton('customer/session');
$action = $_session->getDirectoryAction();
if(Mage::app()->getRequest()->getParam('listing_id')){
$listingId = Mage::app()->getRequest()->getParam('listing_id');
Mage::app()->getRequest()->setParam('success_url',Mage::getUrl($action,array('listing_id'=>$listingId)));
}elseif(Mage::app()->getRequest()->getParam('directory_id')){
$directoryId = Mage::app()->getRequest()->getParam('directory_id');
Mage::app()->getRequest()->setParam('success_url',Mage::getUrl($action,array('directory_id'=>$directoryId)));
}
}
}
public function redirectAfterLogin($observer)
{
if(Mage::app()->getRequest()->getParam('listing_id') || Mage::app()->getRequest()->getParam('directory_id')){
$_session = Mage::getSingleton('customer/session');
$action = $_session->getDirectoryAction();
if(Mage::app()->getRequest()->getParam('listing_id')){
$listingId = Mage::app()->getRequest()->getParam('listing_id');
$url = Mage::getUrl($action,array('listing_id'=>$listingId));
$_session->setBeforeAuthUrl($url);
$_session->setAfterAuthUrl($url);
}elseif(Mage::app()->getRequest()->getParam('directory_id')){
$directoryId = Mage::app()->getRequest()->getParam('directory_id');
$url = Mage::getUrl($action,array('directory_id'=>$directoryId));
$_session->setBeforeAuthUrl($url);
$_session->setAfterAuthUrl($url);
}
}
}
When you have a problem instantiating an object with $observer->getRequest(), try using $observer->getEvent()->getFront()->getResponse() instead. I believe this differs depending on what event the observer is listening to.

Redirecting to checkout after account is created and products are in cart

I have a special case where users have to sign up for an account via the account sign up page (e.g. /customer/account/create/). Upon completion, and in the event that they have a product in the cart, I need to redirect them back to the checkout screen.
I currently have an observer in place that listens to the customer_register_success event. The observer upgrades the users account to a membership group via this code:
class Hatclub_MembershipHandler_Model_Observer {
// members group id
const GROUP_ID = 4;
// called when a customer registers for the site
public function registrationSuccess(Varien_Event_Observer $observer) {
// extract customer data from event
$customer = $observer->getCustomer();
// a cookie should have been set with the membership id
if (isset($_COOKIE['membership_account_id'])) {
$customer
->setGroupId(self::GROUP_ID)
->setRmsId($_COOKIE['membership_account_id']);
}
return $this;
}
}
Is there another event that I can listen to that is better suited for what I want to do? I have a redirect_to cookie that is available as well if that helps.
After much trial and error, I came across a solution. Since I'm already using the customer_register_success event and modifying user data with my observer, I had to use another event called customer_save_after and it worked like a charm.
config.xml event block
<customer_save_after>
<observers>
<customer_session_observer>
<class>hatclub_membership_handler/observer</class>
<method>customerSave</method>
<type>singleton</type>
</customer_session_observer>
</observers>
</customer_save_after>
observer.php method
public function customerSave() {
// set redirect url from cookie, default to null
$redirect_url = (isset($_COOKIE['redirect_url']))
? isset($_COOKIE['redirect_url']) : null;
// if a redirect url was specified
if (isset($redirect_url)) {
// remove cookie to prevent infinite loop
unset($_COOKIE['redirect_url']);
// redirect to provided url
Mage::app()->getResponse()
->setHeader('Location', $redirect_url)
->sendHeaders();
}
}
The redirect within an observer was a bit of a struggle, but I managed to accomplish it using
Mage::app()->getResponse()
->setHeader('Location', $redirect_url)
->sendHeaders();
Suggestions and criticism welcome.

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.

Programmatically send email when shipping tracking number is set

I am looking for a way to programmatically send an email to the user when a tracking number is assigned to an order. I need to be able to do this programmatically because I am using an outside source to populate the tracking information.
I guess what I am really looking for here is a specific trigger or event that I could use to fire off the email that would normally be sent when the admin clicks the "Send Tracking Information" button. I have skimmed through the core code and have not been able to put my finger on what action is actually being triggered when that button is pushed.
We are using a third party (eBridge) to connect with our sales tools. Once an order has been marked as shipped and a tracking number is input into the eBridge tool, it will talk to magento and input the tracking number into the order. The problem is that it doesn't tell magento to fire off an email to provide the customer with this newly inputted tracking number. What I am trying to do is, once the information is put into magento fire off an email from magentos side. Is this possible? What we want, in a nutshell, is to be able to have magento send off an email with the tracking information without having to manually go into each order and click the "Send Tracking Information" button.
When you add a new shipment to an order via the control panel you can tick a box to send the e-mail. If you need to send this programmatically, the controller for the admin area simply calls the sendEmail method on the Mage_Sales_Model_Order_Shipment.
UPDATE: If the tracking number is being adding to the shipment via the 'standard' method, which is to say the addTrack method of the shipment api, then you would be able to hook into the sales_order_shipment_track_save_after event. Adding an observer that does something along the lines of...
public function sendTrackEmail($observer)
{
$track = $observer->getEvent()->getTrack();
$shipment = $track->getShipment(true);
$shipment->sendEmail();
}
FYI there is an undocumented API call that does exactly this, sendInfo(). I don't know as of what version this was added in, as far as I can tell it's over a year old, I just had to solve this same problem myself and this is one of the first results on Google.
Note: If you're implementing this, you likely do not want to send the email flag to the sales_order_shipment.create() API call, as this will result in two emails going out for the same order, one without a tracking number, then one with it.
addTrack() is likely implemented already, you just need to follow it immediately with sendInfo().
sales_order_shipment.addTrack(sessionId, shipmentIncrementId, carrier, title, trackNumber)
sales_order_shipment.sendInfo(sessionId, comment)
The email sent out is the same that you would get by clicking the "Send Tracking Information" button in the Magento backend manually. Reference the Magento API for more explanation on addTrack and using the SOAP API in general.
As for sendInfo() specifically, take a look at the source code from magento/app/code/core/Mage/Sales/Model/Order/Shipment/Api.php for help:
/**
* Send email with shipment data to customer
*
* #param string $shipmentIncrementId
* #param string $comment
* #return bool
*/
public function sendInfo($shipmentIncrementId, $comment = '')
{
/* #var $shipment Mage_Sales_Model_Order_Shipment */
$shipment = Mage::getModel('sales/order_shipment')->loadByIncrementId($shipmentIncrementId);
if (!$shipment->getId()) {
$this->_fault('not_exists');
}
try {
$shipment->sendEmail(true, $comment)
->setEmailSent(true)
->save();
$historyItem = Mage::getResourceModel('sales/order_status_history_collection')
->getUnnotifiedForInstance($shipment, Mage_Sales_Model_Order_Shipment::HISTORY_ENTITY_NAME);
if ($historyItem) {
$historyItem->setIsCustomerNotified(1);
$historyItem->save();
}
} catch (Mage_Core_Exception $e) {
$this->_fault('data_invalid', $e->getMessage());
}
return true;
}
If you want an email containing the tracking informationto get sent when some program e.g. eBridge calls the salesOrderShipmentAddTrack V2 API, you can also extend Mage_Sales_Model_Order_Shipment_Api
e.g.
class PKS_Sales_Model_Order_Shipment_Api extends Mage_Sales_Model_Order_Shipment_Api
public function addTrack
by adding the call to send the email in the try block e.g.
try {
$shipment->save();
$track->save();
$shipment->sendEmail(true, '')
->setEmailSent(true)
->save(); /* added email with null comment */
}
You also have to provide an extension to the SOAP V2 e.g.
class PKS_Sales_Model_Order_Shipment_Api_V2 extends PKS_Sales_Model_Order_Shipment_Api
even if it has no methods :)
(example has my app/code/local/PKS/Sales module, substitute your company name for PKS, apologies re formatting)
app/code/local/PKS/Sales/etc/config.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<PKS_Sales>
<version>4.0.0.0</version>
<depends>
<Mage_Sales />
</depends>
</PKS_Sales>
</modules>
<global>
<models>
<sales>
<rewrite>
<order_shipment_api>PKS_Sales_Model_Order_Shipment_Api</order_shipment_api>
<order_shipment_api_v2>PKS_Sales_Model_Order_Shipment_Api_V2</order_shipment_api_v2>
</rewrite>
</sales>
</models>
</global>
</config>
It took more time figuring out how to write the required PKS/Sales/etc/api.xml
(example has my app/code/local/PKS module, substitute your company name for PKS)
<config>
<api>
<resources>
<sales_order_shipment translate="title" module="PKS_Sales">
<title>Modified Shipment API</title>
<model>sales/order_shipment_api</model>
<acl>sales/order/shipment</acl>
<methods>
<addTrack translate="title" module="PKS_Sales">
<title>Add new tracking number</title>
<acl>sales/order/shipment/track</acl>
</addTrack>
</methods>
<faults module="PKS_Sales">
<not_exists>
<code>100</code>
<message>Requested shipment does not exist.</message>
</not_exists>
<filters_invalid>
<code>101</code>
<message>Invalid filters given. Details in error message.</message>
</filters_invalid>
<data_invalid>
<code>102</code>
<message>Invalid data given. Details in error message.</message>
</data_invalid>
<order_not_exists>
<code>103</code>
<message>Requested order does not exist.</message>
</order_not_exists>
<track_not_exists>
<code>104</code>
<message>Requested tracking does not exist.</message>
</track_not_exists>
<track_not_deleted>
<code>105</code>
<message>Tracking not deleted. Details in error message.</message>
</track_not_deleted>
</faults>
</sales_order_shipment>
</resources>
<resources_alias>
<order>sales_order</order>
<order_shipment>sales_order_shipment</order_shipment>
</resources_alias>
<v2>
<resources_function_prefix>
<order>salesOrder</order>
<order_shipment>salesOrderShipment</order_shipment>
</resources_function_prefix>
</v2>
</acl>
</api>
</config>
Please note that with this approach, and having System > Configuration > Sales > Sales Emails > Order and Shipment emails enabled, your customer will get
- one email confirming a new order
- a second email for the shipment with no tracking number
- a third email for the shipment with the tracking number, from your API extension.
I've tried commenting out the Api.php create function's
$shipment->sendEmail($email, ($includeComment ? $comment : ''));
but that second email just keeps getting sent.

Resources