We need UC Addresses to store the user's address data from the order billing info that the user puts in. This is not happening, nothing is saved in uc_addresses table.
The user's address data, however, is available on the order form, in a drop down menu. I have attempted the following:
1. A new user with no addresses in UC_addresses table, places an order. Checked the uc_addresses table after order returned completed, and see no entry in table. Also checked the /user/userid/addresses, and no addresses displayed.
2. Used the same user to place an order with a different address on the new order and saw no change.
3. Defined an address in uc_address for the above user, this address was seen in the UC_addresses table. However, once an order was placed with a different address, this new address did not appear in the uc_addresses table.
The settings we are using for uc_addresses have been attached in the files.
Deeper look reveals that compareAddress() compares the addresses in the user's addressbook with the addresses supplied by the order. Now, for a new user who has not created any orders, we were expecting the addressbook to be empty, however, it contains an entry. The second entry in the user's addressbook->addresses array is exactly the same as in the order. This causes the comparison to return TRUE and the order address is not added to the user's address book.
The user's addressbook object is a singleton, which first gets instantiated upon order:checkout (hook_uc_order in the module) and then it is also instanced by the uc_addresses_uc_checkout_complete function. Now, since the object is a singleton, it seems it is comparing itself to itself, returning TRUE and causing the address to not be saved.
Are there any known solutions to it?
Appreciate help.
| Comment | File | Size | Author |
|---|---|---|---|
| #3 | ucAddressesAddressBook.class_.patch | 2.38 KB | pjindent |
| #2 | uc_addresses.patch | 912 bytes | pjindent |
| SnipImage2.JPG | 54.95 KB | pjindent | |
| SnipImage.JPG | 52.49 KB | pjindent |
Comments
Comment #1
megachrizThanks for filing a bug report, especially one with useful details provided! This bug probably got in due to recent changes, as addresses were saved in the address book after completing checkout before. Not sure if you were implying this in step 1, but addresses entered by an admin when editing an order (admin/store/orders/%uc_order/edit) are not automatically saved to the address book, but it should save addresses automatically to the address book when completing checkout.
I hope to look at this issue soon as possible, but there is a lot of other work for me left to be done.
If you would like to help with coding, you could write an automated test for this case. This helps to make the code more stable and prevents the issue for coming back (after it's been solved). Do this only if you are familiar with writing tests, as it takes some time to learn how to write tests.
Comment #1.0
megachrizreworded
Comment #1.1
pjindent commentedReworded item 1 based on comment 1
Comment #2
pjindent commentedincorrect patch. Will post an updated patch soon.
Comment #3
pjindent commentedAttached is patch for the fix.
Changed UCAddressesAddressBook.class compareAddress() method to implement the following approach:
- All addresses in UcAddressesAddressBook for a user contain addresses with negative and positive address id ($aid).
- Ignore all $aid < 0, because these addresses are not from uc_addresses table, instead they are from current order or created by default
Comment #4
megachrizThanks for your efforts to work on this! I don't think the changes you propose in your patch from #3 is the ideal way of fixing this issue. You make changes to the behavior of the API to fix a specific case. The
compareAddress()-method should do what it suggests to do: check if the given address looks like any of the other addresses in the address book, saved or not. Also, by addingglobal $user;the API method will be unusable if addresses are compared for an user that's not logged in.I like the approach of your first patch better (from #2), that implies to do a compare only against the addresses that are saved.
There is a better way of checking if an address is saved or not. Instead of checking if the address contains a "created" value or a negative address ID, you can call the method
isNew()on an UcAddressesAddress object:By the way, if you post a patch for review, the right issue status to set it to, is "needs review". This way, the patch will go through the automated tests process (if supported by the project) which helps to reveal if the modules get's broken elsewhere.
See also this article about automated patch testing: http://drupal.org/node/1058140
"patch (to be ported)" is used when a patch has been committed for one version, but needs to be adopted for another version. See also this article about the issue status: http://drupal.org/node/156119.
Well, I will first try to reproduce your issue. With me, addresses are saved to the address book with the default settings. I will going to try it with your settings.
Setting to "needs work", because the issue should be fixed in an other way.
Comment #5
megachrizHm, unfortunately, I'm not able to reproduce your issue so far. I've tried to reproduce the issue several times under these circumstances (not all at once):
I've used the settings you provided and followed these steps:
I repeated the steps above as a logged in user with no previous orders and no addresses in the address book. Thus with step 2 replaced with this:
- Logged in as an existing user (that has no orders or addresses).
I got the same result.
Used versions
While I think that the bug is in Ubercart Addresses, I'm not able yet to reproduce it. Maybe the bug only comes to life when Ubercart Addresses is used in combination with an other module?
Could you try either one of these?:
And try if you encounter the same issue.
If you do get the same issue, then try to explain the steps you took in more detail (inclusive Ubercart checkout configurations).
If you do not get the same issue, then it's likely the bug only exists when Ubercart Addresses is used in combination with an other module. The trick is then to find out which one. The first modules to look for are the modules that influence the checkout process.
Comment #6
megachrizMy bad, I noticed I had been testing with a version that already included a fix for #1735678: Autofill doesn't work, which "hided" the problem. I've been able to reproduce the issue now. The issue occurs when the address forms at checkout are not prefilled with the default addresses. This is an option that can be turned on or off, but there had been bug where the address forms where never got prefilled, no matter what option was set (see #1735678: Autofill doesn't work for details).
I've been busy debugging today and I found that the root of the problem lies much deeper: at some point during PHP runtime there are two address objects with the same address ID, but different PHP object ID's. That's why UcAddressesAddressBook compares the two addresses, it only skips addresses in comparison that are 100% equal (having the exact same PHP object ID):
So the solution (or at least a part of the solution) would be to prevent having two address objects with the same address ID. How is this possible in the first place? Well, when unserializing a PHP object, it get's a new PHP object ID assigned. I think the solution would be to check if an address object with same ID already exists when an address object get's unserialized. If this is the case, then overwrite the "new" unserialized address object with the one that's already available.
I have the following code so far in the UcAddressesAddress class:
I'm working on it.
Comment #7
megachrizMy ideas posted in #6 didn't work at all. I can't find a way to overwrite an address object immediately after it's being unserialized. The only way I see for preventing having two address objects with the same ID at runtime is disallowing serializing. As that would have a huge impact on the existing code, I decide to not fix that weak spot (I might as well rewrite the whole module, which I'm not going to do if I look at the amount of my free time).
Instead, I've worked on an acceptable workaround that fixes this issue. A change is made in the UcAddressesAddressBook class so that addresses are only compared to saved addresses. I've written some automated tests to ensure saving addresses to address book will work with or without the autofill option on. This revealed some other small issues, such as:
So for one fix several other small fixes were also needed in order to let all automated tests pass.
I've made the change in both 6.x-2.x and 7.x-1.x:
Comment #8.0
(not verified) commentedminor