How do I stop Magento merging the basket on login? - magento

If you were to login to Magento and add some products to your basket and then leave the site, these are saved for the next time you return to the site.
This, however, causes an issue when you do return. If, on your return, you added a product to your basket without logging in and then logged in at the start of the checkout process, your guest and saved basket will be merged. This is undesirable.
Is there any way to make Magento clear the saved basket on login if your current basket has items in it?

It looks like the code that governs this is in Mage_Checkout_Model_Session, specifically where it calls Mage_Sales_Model_Quote::merge. This means that you have a few options.
Override the session class and force it not to cause the merge.
Override the quote class and cause it never to merge carts. There may be secondary bugs to this approach if other parts of the system also attempt to merge carts.
Hook into the event that quote calls (sales_quote_merge_before) and use that opportunity to empty one of the carts. You would have to detect around when this should be done, but it is by far cleaner than the other two.

I've amended the Quote.php (/Sales/Model/) on line 1344 within the merge function the following.
foreach ($this->getAllItems() as $item) {
$this->removeItem($item->getId());
}

There's a Magento extension that prevents the carts from being merged:
https://github.com/jacquesbh/jbh_cartmerge
It makes use of the sales_quote_merge_before event where it removes the quote items of the customer's cart.

Based on Joseph Mastey's answer, for the event / observer, I used the describeas event, and then I removed the quote as follows:
public function emptyCartUserNoLogged($observer){
$event = $observer->getEvent();
$quote = $event->getSource();
$quote->setIsActive(false);
$quote->delete();
}

Related

Codeigniter - is it risky to modify the cart $product_name_rules to accept any character?

I'm using the Cart Class in CI, and my product names contain lots of "dangerous" characters, such as apostrophe, brackets, semicolon, ampersands, and many non latin characters.
The Cart Class limits the allowed characters like so:
var $product_name_rules = '\.\:\-_ a-z0-9'; // alpha-numeric, dashes, underscores, colons or periods
I know I can extend the Cart Class and override this limitation with something like this in a MY_Cart Class:
$this->product_name_rules = '\d\D';
But this makes me wonder - perhaps the CI people had a reason for limiting the product names. Maybe by removing the limitation I'm opening a backdoor to hackers.
Obviously, when I add items from the cart to my database, I use Active Records and query binding, which should (to my best understanding) provide a sufficient defense against sql injections and the like.
So what was the idea behind limiting the characters in the first place?
NO! Well, let me say: "None that I could see":
Although codeigniter seemed to throw some errors when I modified regex of the cart core directly. So I just tweaked by leaving what's there and just adding /d/D at the end like this:
var $product_name_rules = '\.\:\-_ a-z0-9\d\D'; // alpha-numeric, dashes, underscores, colons or periods
To not mess with original classes for reasons you might not know, try to extend the class
You could find guides here:
http://ponderwell.net/2010/07/codeigniter-extending-the-cart-class-for-robust-product-names/
Create a file in application/libraries and call it "MY_cart.php". In that file, paste the following code:
< ?php
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Cart extends CI_Cart {
function __construct() {
parent::__construct();
$this->product_name_rules = '\d\D';
}
}
Its worth getting to know the CI cart library. Because then when you make your own cart, it will make you feel really good about yourself. :-) Seriously though, everyone who tries the CI cart runs into this issue and there are many posts about it. So yes you can modify it so you can use different characters in the names - but i would seriously urge you to make your own cart as soon as possible.
what does a shopping cart really need from the product page? It needs the ID of the product, and the Qty. thats it - everything else should come directly from your product table.
do not set up your app so that there is a price on a product page, and then you take that price and send it to the cart. someone could easily modify the form and send a lower price to the cart.
so verify the product id - then get the product price DIRECTLY from the product table. and thats easy because you just did it to show the product. you can also get the product name that way and - hey suddenly you dont have to worry at all about dangerous characters, and you know that the price will be accurate.
and Steward has the excellent answer for working with ci cart lib, and the blog post he links to steps through the issues. you can also copy parts of the cart lib and put them in MY_cart, its a good way to see how it works and you can do simple mods.

Shipping Methods are not working in magento 1.7

I activated flat shipping in the shipping options and whenever you do checkout it says “Sorry, no quotes are available for this order at this time.”Any one please help me since i am a beginner in magento.
EDIT
I have tried other shipping methods too its also showing the same. we have upgraded Magento ver. 1.4.1.1 to magento 1.7. Any help would be greatly appreciated..
EDIT 2
After upgrading community folder contains only Phoenix folder. After that i added Biebersdorffolder by seeing an error in checkout page. I don't the the purpose of folders AW and RocketWeb. Since i am not familiar with magento.
If the image is not visible i have added the image in this url
http://i47.tinypic.com/14smix1.jpg
do you have any Checkout files modified on your project? Or maybe custom checkout.
I will list the code locations you need to check to make sure your Shipping works correctly.
So to begin with: Magento has very special work process with Shipping rates - it's called "collectRates" and is some modification of pattern "composite".
To make sure that everything works correctly on the code basis you need to first check the Onepage.php model (app/code/core/Mage/Checkout/Model/Type/Onepage.php): lines 330, 341, 556, 616; There should be code
{address}->setCollectShippingRates(true)
where {address} is current address variable.
This code is significant for future "collectRates" processes, because just when the Onepage Checkout page is initializing the "collectRates" process has already been processed, and the flag "collect_shipping_rates" is set to "false". If it's not set back to true, the next "collectRates" process will not be performed.
After you check the location above, and it still doesn't work - you might want to add some logging to Mage_Checkout_Block_Onepage_Shipping_Method_Available::getShippingRates method. If method is properly executed and return some rates from $this->getAddress()->getGroupedAllShippingRates() call, there might be some issues with .phtml template on your locan theme (default path to .phtml is app/design/frontend/base/default/template/checkout/onepage/shipping_method/available.phtml).
Here's how you can log the outcome from $this->getAddress()->getGroupedAllShippingRates() call (Mage_Checkout_Block_Onepage_Shipping_Method_Available::getShippingRates method):
$groups = $this->getAddress()->getGroupedAllShippingRates();
$printGroupes = array();
foreach ($groups as $code => $groupItems) {
foreach ($groupItems as $item) {
$printGroupes[$code][] = $item->getData();
}
}
Mage::log($printGroupes, null,'special.log');
Please note, that the result array with all rates will be logged into "special.log" under var/logs folder.
I wish I could be more of help, but the issue requires some digging into code, the debugger will be even more helpful than logging, if you can get hold of one.
Cheers!
Price should be entered for Flat Rate shipping to work
The problem might be of the country selection
Ship to applicable countries is set to "Specific Country" and you selected "Canada".
So you will see this shipping method only if you select Canada on the frontend during the checkout.
Or
You can make this to All Countries and check whether its working or not.

Magento redirected to other URL after order editting

Currently I'm experiencing a problem after editing orders in the Magento admin. The page is always redirected to another URL, the base of which belongs to the store view that the order belongs to. And this page requires re-login to the admin.
For example, I have two base URLs, each belongs to one store view:
www.example.old.com //old store view (default)
www.example.new.com //new store view
The system uses www.example.old.com as the default base URL. So under www.example.old.com I create an order for the new store and invoice it. Then on submitting the invoice, the page is redirected from
http://www.example.old.com/index.php/admin/sales_order_invoice/new/order_id/1234/
to
http://www.example.new.com/admin/sales_order/view/order_id/1234/
And it requires login for another time.
I traced the redirection code to Mage_Core_Model_Url
public function getRouteUrl($routePath=null, $routeParams=null)
...
$url = $this->getBaseUrl().$this->getRoutePath($routeParams);
public function getBaseUrl($params = array())
....
if (isset($params['_store'])) {
$this->setStore($params['_store']);
}
....
return $this->getStore()->getBaseUrl($this->getType(), $this->getSecure());
Then I don't know what to do. There is no parameter _store but it seems that Magento determines which store view to run based on the order being treated, when it is supposed to stay on the same base URL throughout the admin.
Have you tried to enable customer data sharing between the stores in the backend?
Sorry for newbie answer, still learning magento
For those who may still show interests to this old entry, I share my solution. It is not a good one, indeed it is a hard-coded redirection to avoid going back to an uncertain URL, but it fixed the problem for me.
In the controller action where the redirection happens, modify
$this->_redirect(..., array(... => ...));
to
$this->_redirect(..., array(... => ..., '_store' => Mage::app()->getStore($storeId)));
This ensures that the redirection always goes to the specified store.
Reason is that Magento switchs context to store of order because it requires to translate the email template correctly.
Look at class Mage_Core_Model_Template there are two method _applyDesignConfig and _cancelDesignConfig. First function switches context and remember old context, second function should return all back. But, there is a bug. See more at: http://www.magthemes.com/magento-blog/magento-142-multiwebsite-admin-redirect-problem-quick-workaround/#comment-1084

Yii: Piggybacking on Session GC For Cart Cleanup?

I am building a shopping cart using the Yii framework. I have created a cart model to store the items the user adds to the cart, and I'm keeping track of the products that guest shoppers are adding to the cart by using a session_id field that stores the current session.
However, if the shopper abandons the cart or the session simply times out before they proceed to the checkout I find that I have a bunch of records in the cart table that need to be cleaned up.
I was thinking that the best way to do this would be to piggy back on the garbage collection process that Yii uses to clean up the session table, but I'm not sure how to do this, or even if this is the best way.
Am I on the right track here?
If so, how do I go about piggybacking on Yii's garbage collection?
I don't know much about PHP's session garbage collection, so I don't know if this is a better way to go than a cron job. The little I do know I just learned from Professor Google, and it makes me think relying on the session garbage collection may not be as reliable as you want:
How do I expire a PHP session after 30 minutes?
But it could work, I suppose. Kind of clever, actually, if it does. And in this case, you would need to override the gcSession() method in the CDbHttpSession class in the Yii core (assuming, as you say, you are using the database session storage). You can override this method very easily, actually, in your config.php file.
First, create your new MyCustomHttpSession class which extends CDbHttpSession (drop it in your /components folder probably). Be sure to add your new custom Cart garbage collection to the gcSession() function!
class MyCustomHttpSession extends CDbHttpSession
{
public function gcSession($maxLifetime) {
/**** ADD YOUR CUSTOM LOGIC HERE ****/
$sql="DELETE FROM {$this->sessionTableName} WHERE expire<".time();
$this->getDbConnection()->createCommand($sql)->execute();
return true;
}
}
Then, tell Yii to use your new MyCustomHttpSession class in the components configuration array:
'components'=>array(
'session'=>array(
'class' => 'application.components.MyCustomHttpSession',
'connectionID' => 'db',
'timeout'=>14400, // 4 hour session time
),
),
I did not test this, but it should work just fine. Good luck!

How do I get the shipping method the user has chosen during checkout?

I want to get the name of the shipping method the user has chosen during checkout. Does anyone know how to retrieve that info?
This will get it to some extent but it is cached:
Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress()->getShippingDescription();
When I am on the onestep checkout and I go back to the shipping tab and change the shipping, it is still holding the old shipping method. I need to figure out how to get the current one.
Foreword
Constructed from Magento app/code/core/Mage/Checkout/Block/Onepage/Shipping/Method/Available.php and others:
app/design/frontend/base/default/template/checkout/onepage/shipping_method/available.phtml uses this code to determine which shipping method was selected:
$this->getAddressShippingMethod()
app/code/core/Mage/Checkout/Block/Onepage/Shipping/Method/Available.php expands that code to this:
return $this->getAddress()->getShippingMethod();
Let's research a bit and expand it even deeper:
$this->getQuote()->getShippingAddress()->getShippingMethod();
Parent block expands method getQuote():
return $this->getCheckout()->getQuote();
And deeper:
public function getChechout() {
return Mage::getSingleton('checkout/session');
}
Merging all that code gives us this:
Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress()->getShippingMethod()
That gives you the shipping method code. Giving that, you could manipulate it just as you wish. This data is stored within the database, so when you change shipping method, the code changes too.
Getting deeper and deeper!
If you've ever created your own shipping method, you'd know, that it has the method called collectRates().
It fills a set of shipping/rate_result_method models, stores it within the instance of shipping/rate_result model and returns it (you can get each model' instance using Mage::getModel(<model i've named>); ).
Yet, note: one could contain multiple rate_result_method instances, while the shipping method code is the same for all those instances!
Thus, in order to get the description, you need to get one of the rate_result_method instances and retrieve its methodTitle or carrierTitle.
After a small researching i've found how to retrieve all these rates:
Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress()->getShippingRatesCollection()
This will provide you with a collection of all rates for the selected shipping method. You can operate it with getItems() and get a hash. Or you could use getFirstItem() and use it as the template.
Anyway, let's assume u've retrieved some item of that collection and stored it within the $rate variable:
$rate->getCarrier(); // This will provide you with the carrier code
$rate->getCarrierTitle(); // This will give you the carrier title
$rate->getCode(); // This will give you **current shipping method** code
$rate->getMethod(); // This will provide you with the **shipping method** code
$rate->getMethodTitle(); // This will tell you current shipping method title
$rate->getMethodDescription(); // And this is the description of the current shipping method and **it could be NULL**
That's all, folks!
I am really sorry for my poor English and for my strange mind flow. Hope this will help you or someone else. Thanks!
Just in case you need it still. You can get shipping method from order by:
$order->getShippingMethod();
Of course how you get your $order depends on context.
Also you can get description by:
$order->getShippingDescription();
shipping method in magento
$methods = Mage::getSingleton('shipping/config')->getActiveCarriers();
$options = array();
foreach($methods as $_code => $_method)
{
if(!$_title = Mage::getStoreConfig("carriers/$_code/title"))
$_title = $_code;
$options[] = array('value' => $_code, 'label' => $_title . " ($_code)");
}
echo "<xmp>";
print_r($options);
echo "</xmp>";
In your checkout controller you need to add extra steps to save your quote if you want this information to be accessible to you.
I added a few '$quote->save();' entries to get this to work, however, I cannot definitively say which entry is the one that did the fix. I also cannot find the link on Magento forums, however, I hope I have given you a head start on what is going on.
You could override the saveShippingMethodAction() function in the Mage_Checkout_OnepageController, or extend upon it, and save the method into the registry by inserting:
Mage::register('blahShippingMethod', $this->getRequest()->getPost('shipping_method'));
and call upon it as you need it: Mage::registry('blahShippingMethod');
Don't forget to unset it when you no longer need it as you will run into an error if you try to reset when it's already been set.
Mage::unregister('blahShippingMethod');

Resources