Showing posts with label drupal. Show all posts
Showing posts with label drupal. Show all posts

Installing Modules in Drupal without using FTP

Let's make a quick note about installing modules in Drupal7. Usually when moving your site from your localhost to your production server, you will notice several problems in moving your site.

One of those problems is when you're installing  new modules in your site using the url in  the Drupal modules page and then this wild pokemon appear:

Drupal FTP Installation
This is not the normal way that Drupal7 use to install modules. you are going to see this interface when the file owning and permission in Drupal dont work.

So, how do I fix this?

Easy, well this depend on what Linux are you using (please use Linux). You can always see the Linux version using version in the command line.In my case, I use Ubuntu and to fix this you must go to var/www/html7yoursite/sites and then exec this litle gem:  sudo chown -R www-data *.

There, fixed :)

What kind of Magic is this?

Well, usually in Drupal, you must give permission to the Apache user (if youre using Nginx, I assume is the same) so Drupal can work as usual. In this case we do a chown with -R (recursivity) putting www-data (the Apache user usually in Ubuntu)  as the owner of all files inside sites. You welcome ;)

Installing Modules in Drupal without using FTP

Let's make a quick note about installing modules in Drupal7. Usually when moving your site from your localhost to your production server, you will notice several problems in moving your site.

One of those problems is when you're installing  new modules in your site using the url in  the Drupal modules page and then this wild pokemon appear:

Drupal FTP Installation
This is not the normal way that Drupal7 use to install modules. you are going to see this interface when the file owning and permission in Drupal dont work.

So, how do I fix this?

Easy, well this depend on what Linux are you using (please use Linux). You can always see the Linux version using version in the command line.In my case, I use Ubuntu and to fix this you must go to var/www/html7yoursite/sites and then exec this litle gem:  sudo chown -R www-data *.

There, fixed :)

What kind of Magic is this?

Well, usually in Drupal, you must give permission to the Apache user (if youre using Nginx, I assume is the same) so Drupal can work as usual. In this case we do a chown with -R (recursivity) putting www-data (the Apache user usually in Ubuntu)  as the owner of all files inside sites. You welcome ;)

Correct Way to Translate Content in Drupal

Ok, this will be a small post about keeping a multilanguage web page in Drupal7. As you know  Drupal is powerfull, but a bit complicate when configuring it. This WILL NOT be a tutorial, but a general map of instruction to translate your website. So let's see howto do it.

How Drupal knows what is the current language on your page.

There's a lot of ways of how drupal can recognise the current language. In fact you choose one when configuring the languages that are going to be on Drupal. But I really recommend using the URL method. This work as follow. Suppose you have a domain www.domain.com. When using URL for internationalization, your webpage in spanish are going to be on www.domain.com/es. So your node1 should be www.domain.com/es/node/1, in english it will be www.domain.com/en/node/2 (node2 because that's your translated module). There are other ways like having a global variable, but it will mess up your SEO, because google really hates having the same URL with different content (ok, its the same content but in a different language).


Translating Content

For translating content, you have to install the i18n module. When installed, a new tab called translate will appear when editing your node. The way you translate a content is creating a new node that is related to the original node. 

Translating WebForms

This will be the same as content. You create a clon of the original webform and relate it to the original.


Translating Blocks

You are going to need to activate the block Language Module. Works the same as Content.

Translating things in Views

So, lets say you create your awesome view and have put some global text button, or put a main title on it. the way you have to translate that is using the Content Translation module that comes with core of Drupal. After that you have to search for the string you want to translate, include the HTML if your title or global text have that, or else it will not appear in your search list. But!, and this is a very big but, when translating string, make sure youre currently on the language the translate string is. For example is you create a title in Spanish, let's say "Hola Mundo" (yes with the span tags to separe Hola from Mundo), you have to search that string using the admin in spanish, like www.domain.com/es/admin/translateblahblah or else your string will appear in the wrong language.

Menus and URL

This is the last thing you want to translate. For me its easy to create a new menu item in a different language. And why do it last? Because the URL of your content will exist only after your content is created. 

So, what thing's cannot be done easily?

My only problem right now is looking  for a way to translate the URL of a View in Page form. If you know, please tell me in the comment. Good luck!


Improving the Performance of BigDump

BigDump its my favorite way to move a Drupal Database from one server to another. Lately I had a "feeling" that this migration was becoming slower and slower. I really dont know if it is because of the way Drupal7 store the data, or because the new WAMP versions just come with a bad default configuration.

Anyway I was decided to confront this problem and find some interesting things that we can use to improve BigDump. So I made some experiments in my CoreI5 with 8GB of Ram and here is what i found:

About Drupal 7 and WAMP Mysql

Well this entry is mainly for Drupal7 users with Mysql as their main database in a WAMP server, I guess a lot of people have that configuration as a developing server. well seems like Drupal7 change their storage engine, instead of MyISAM, the default storage engine of Drupal6, its now use InnoDB. There are a lot of opinions about what is better but Seems like InnoDB can get you more performance if you give it an adequate quantity of RAM memory.  Now a simple site in Drupal, lets say a Blog, will usually weight between 5 to 10 MB in database data. That quantity of data doesn't work with the default configuration  of a Mysql WAMP installation, you will surely have a Server Gone Away error or Time Limit error, that's why we need to use BigDump for such quantity of data.

First: Configuring Mysql

Ok open your my.ini (in Linux it should be my.cfg but I not quite sure where it is)  file to start modifying it, Don't know where to find it? Follow this simple image and do it baby:



After some trial an error messing up this file , here are some configuration that you should try in order of importance:
  • innodb_flush_log_at_trx_commit = 2, by default it is set on 1, putting it on 2 means that your log will be stored temporaly in RAM instead of saving it on the HD every time you do an insert delete or update. This configuration have a side effect that it may corrupt the Log if crazy stuff happens to your RAM but you will not loose too much if your server is not your web hosting. Changing this variable makes my BigDump script run from 190 seconds to only 90 seconds, almost doubling the speed of this. If by any reason you cannot change this variable, maybe you can put your SQL exported script inside a transaction:

This is the export tool of PhpMyAdmin, check that option in Green and all your Data will be inside a Transaction
  • innodb_buffer_pool_size = 1024M, Ok I put 1024MB of RAM but you can put more according to the quantity of RAM in your rig. The default I think it is 1M or 16M, just changing this variable improve the speed from 90 seconds to only 50! 
  • Moar!!!: This blog gave me some more good ideas about other variables that we can tweak, but just with these two you can get an improvement of quad the speed.
Dont forget to remove the # on the start of the line, # is used for code comments. Yes you know that, but you already forget to delete it, check it again ;)

Second: Configuring PHP

This is optional really, but giving more memory to PHP improve the efficiency of the BigDump Script in 2 to 3 seconds, its not really too much but it will really help when you have Drupal installed

  • memory_limit 1024M :Play with it if you have more RAM, but 1024 worked fine for me.

 
PHP.ini after modifying it.





So to recap, change those 3 values showed to you and your BigDump script will fly!. Have fun

THIRD: Host File (update Jul2014):

After a hard drive format on my main disk, I installed again WAMP, and discovered that is was slow as hell, in a CoreI7 machine with 16GB of RAM, so I follow some advice to improve the general Wamp performance. One of those tricks is to modify the hosts file of windows, configure my.ini (of mysql) to listen to 127.0.0.1 and to disable IP6. Please take a look at those tricks here.

FOUR: Mysql Bind parameter (update Jul2014):

In  my.ini use the following under the [wampmysqld] tag.

bind-address = ::

Find this information in stack overflow

Drupal: From localhost to your domainsite in five steps



The designer in you, has finished to create the plus ultra of web pages, the only problem is that your web pages is in localhost, or worse yet, it is in a subdirectory in another domain. No problem, with this five step guide step you are going to have our web page ready to be truly Online

Step 1
Backup your database and webpage and put it in your new domain. This mean you have to enter your cpanel ( or other web manager , if you have plesk, may Odin be with you) and go to PhpMyAdmin ( you can install it if you dont have one, its free!) and export your database.

Now import it to your new domain. There may be a problem while importing the backup to your new site, If your database backup file is more than 5 mb, then you probably need BigDump. Its an Ajax uploader of databases. So when exporting your sql, mak sure to uncheck the Extended Insert option, it juss mess up BigDump.

In BigDump, make sure to use UTF-8 (or the schema youre using) in his config, this will make you very happy latter.

Exporting your database so bigdump can use it

Step2: Domain URL
So far so good, you need to modify the sites/default/settings.php
. Change the new database access, and the base_url variable (read the instructions there, nothing fancy really). Make sure that you have the right permission of modifyng that file. Usually it will not come with write permission (or chmod 555) . Make it chmod 777 (change is permission to write) and start modifyng. Then change it back to 555 for security sake.

Step3: htaccess
Did you change the permission for settings.php back to 555? Good, then there's a hidden file called .htaccess (notice the dot at the start) that you may need to modifyng. Search for this string # RewriteBase / and remove that # , so it is umcommented. If for some reason you are still at an subdomain you may need to chage it to # RewriteBase /subdomainname

Step 4: Refresh Cache
Now you need to go to http://www.yournewdomainname.com/oldsubdirectory/admin_menu/flush-cache?destination=admin%2Fsettings%2Fsite-information. Notice the red part is your old subdomain. Maybe you will need to remove it, remember that is the name of your old subdirectory (if you used one).

Ste 5: Run Cron
Now go to http://www..yournewdomainname.com/oldsubdirectory/admin/reports/status/run-cron?destination=admin%2Fsettings%2Fsite-information and enter. You are going to run cron. Again maybe you are not going to need that oldsubdirectory part but, just in case it is there.

Then enjoy, Happy New Year from Jeeba!


Quick tips on Drupal hook user



So as you see, Im playing a lot with the hook_user function in Drupal. It has a lot of power, but unfortunately,theres not too much documentation to play with itl. I am going to post some random tips that i learn using the hook user function so this will be an article that would be updated frequently. The tips are for the Drupal 6.X version. Lets begin!

About the hook user function
This is an useful hook function when you need to play around with the users in Drupal, particulary registering users, updating users, validating the info of user and the deletion of user. This function receive four parameters:
  • $op: The operation to perform. Refer to the api to know all the variables
  • &$edit: The values returned from the login/register form. This is a reference to the variable, so be carufull changing values here
  • &$account: The user object on which the operation is being performed. This variable is not always the current active user!, so the global $user is not always equals to $account. For example if you are the superuser and you are registering manually a user called Michael, the $account should be Michael and $user should be the superuser
  • $category The active category of user information being edited. This works only for updating user info.

Tip A: The account variable in $op = validate
I have some problems with this. I was trying to access the name of the account like this $account->name, but it gave me an error saying that the object dont have that field.

When debbuging the variable, I could see the field name with the corresponding value.So what was the problem? Well it appears than when validating the form, the $account variable is an stdClass object, and with those object you cant use the -> operator, you can only access their fields using a sintaxis like associative arrays, so the correct sintaxis in this case is $account['name'] instead of $account->name. Have some fun with this

Tip B: Help, i cant debug hook_user using Drupal for Firebug, or drupal_set_message

The thing with hook_user and many hook in Drupal is that they are called over and over again across different pages.

Drupal for Firebug works putting some hidden html to your footer, so if you try to use it , it will not work. I dont know exactly why this happen but, for example, using firep in the validate $op just wont work.

drupal_set_message is an useful function to send messages to your current Drupal user. But I couldnt make it show a print_r($account) or a var_dump($account), for some strange reason , it just dont work.

The best way to debug your code , appart from using xcode, or Zend debugger, or other professional debug tools, is using the firephp extesion of Firefox. Theres a magic option called persist that save every data ouptputed to firephp, until you delete it manually.


The only problem with firephp is that you have to somehow, integrate it with Drupal. Its not so hard and this useful article will help you install it in a generic PHP program. But remember my word, that Persist Button IS your only friend in Drupal debugging, forget devel or Drupal for firebug module, they just dont have the power!

UPDATE 21 September 2010: Actually Drupal for firebug is an awesome module. After writing this article, as some sort of poetic justice, Firephp started to fail, an in exchange, Drupal for Firebug started to work!. So, i would recommend to use both, just in case, first plug-in Drupal for Firebug, and if it fails then launch Firephp and catch your bug.

Also the devel module as some nice functions for development. And lets not forget the dblog module (formally watchdog, you can found him here admin/reports/dblog). If you see some blank pages maybe going here can help you solve your problems.

Nobody says that being an PyroEntomologist was fun.

Redirect user after login in Drupal

Redirecting users in Drupal is not easy as it seems to be. In this 6.19 version of Drupal, there are some gotchas to have in mind to make a succesfull redirection

The Direct Path : Hooking form_alter
Like the title say, what we need to do is create a hook for the form_alter hook. This hook is usefull for modifyng the form before rendering it (and for a lot of other interesting stuff), and because Mr. login block and Ms. login page (sitemap.com/user) are also forms, we are going to have fun with the hook(er) (bazinga? well, thats a sick joke). Here are the steps for ultimate redirection control:
  1. Create a module: Create two files yeah.info and yeah.module (change yeah for whatever you wish but make sure to remember that key word) and put them inside sites/all/modules/yeah.
  2. Fill yeah.info with this generic code:
    ;
    $Id$
    name = Yeah Redirect
    description = "Redirect your users at login"
    core = 6.x
    package = "Yeah"

    This is just a required file the module need to exist.

  3. Fill yeah.module with this code

    function yeah_form_alter(&$form, $form_state, $form_id){
    if ($form_id == 'user_login' || $form_id == 'user_login_block') {
    $form['#redirect']=array('thepath/you/want.php');}
    }

    Now, let me explain how this works:
    • The first line tell you that you're hooking the hook_form_alter hook (sic). What does this means is that before any form is rendered this function is being called. Notice the three parameters, first one is the variable that hold the form, its an reference (& anyone?) so the changes you make to &form will exist outside this function. Dont worry too much about $form_state. The third one is the id of the form.
    • The second line is an if that we use to capture only the user_login page form (user_login) and the user_login block form.
    • If the form currently on form_alter is a login form, then we are going to modified it, giving the #redirect property the url that we want to go. If you need to pass parameters then use an array, the first one is the path, and the next ones are the parameters



This code should work for all the user login pages. But it will not work for user login blocks...

What the..

Yes, that code will not work for the login block of Drupal. Why? well because, redirect calls the function drupal_goto($url) an that function is going to ignore you if $_REQUEST['destination'] and/or $_REQUEST['edit']['destination'] exist. Why? I dont have a clue, maybe someone in Drupal wants us to be slapped in the face as a price for using this awesome piece of framework ( no sarcasm here, really!, i luuuuuuuuuve Drupal, well except the drupal_goto function).

The Solution
unset($_REQUEST['destination'], $_REQUEST['edit']['destination']);
Insert this after form redirect and youre ready to go!.

Dude, its not working
Well here are some hints if you need more help:
  1. Make sure you activate the module . Duh!
  2. Check that others noncore modules are not using drupal_goto. Drupal_goto is like a header('Location:....) , it will redirect you to another page, and if there is more code to process after calling drupal_goto, it would not be use.
  3. Clear your theme_cache. Even if you have the 'Rebuild the theme registry on every page load.' on, hell just clear all the cache just in case.
Maybe im missing something here but with this easy explanation i think i have covered all that is need to know for redirecting users at login state. Happy Hooking

Drupal Subtheming nightmare with a happy ending

Im modifying the user login form of a normal Drupal installation using the adaptative theme. so far so good, until i started to create some template suggestion files for my subtheme.

The tpl in question is named block-user.tpl.php. So i create my .tpl file and put all the needed stuff inside it. Then I put it in the template directory of my subtheme and .. it didnt work.

  • For now the file was in /sites/all/themes/adaptativetheme/subtheme/template/block-user.tpl

The second thing I did to make it work was copying that file on the template directory of the adaptative theme ( the father of my subtheme), and it works!. But why it didnt work on my subtheme?
  • The copied file was in /sites/all/themes/adaptativetheme/adaptative/template/block-user.tpl and also in:
  • /sites/all/themes/adaptativetheme/subthemename/template/block-user.tpl

The Fix
Apparently you have to had a copy of all the parent templates in your template directory. So the parent .tpl file of block-user.tpl.php is block.tpl.php. Its a bug in Drupal6, live with it because it wont be fixed. Why it works on the theme instead of the subtheme, because the Adaptative theme has that file by default. So I copy that file on my subtheme.. to no avail.

Clearing the Cache
I had the Rebuild the theme registry on every page load option on, so i wonder why it didnt work. I cleared all the cache ( Its an options that appears in the module Administration Menu, a must have module ), and Voila!, it worked in my subtheme!, so you must clear the cache when seeing funny stuff happening with your tpl files.

Optional Life Savier Info
Also they must be in the same directory as the parents of your subtheme. So if your main theme saves all our .tpl files in the templateyeah carpet, you need to create the same carpet in your subtheme.

Hope this little article help someone drupaling. Happy coding!

IE6 and Ubertcart

There's a problem with Ubercart and any modules that use a great quantity of CSS files in Drupal. It doesnt seem to work in IE (any version).

Sympthoms
You install Ubercart or any other big module in Drupal. you test it and seems fine in all the browsers , except IE (again, any version). Seems like some CSS files are missing.


WTF happened to my CSS! yelling is another sympthom of this IE induced disease

Cause:
IE6 was created to support only 31 stylesheets if you use the link tag to insert them. So when you install ubercart, theres a big possibility that youre excedding that nonsense limit. Have a good day with that.

Remedy:
There are two ways to work this in Drupal without feelin like youre kicked in the nuts with an iron spiked shoe:
  • Im too young to die way (Easy Way): Just use unlimited css module, install it an forget about it. This module will call all the CSS files via an @import rule , you can have more thant 31 @import rules in IE, that why it work. Just as a side note, as a good web developer youre not supposed to use the @import rule because its mean trouble.
  • Hurt me plenty way (Medium Way): Activate the Css File Optimizer in Drupal. Go to admin/settings/performance and you will find the option Optimize the Css Files (duh!). This will mix all the css files in your web page to just one file. I couldnt make it work in my server, this option need a beefy machine to run so make sure you have a really reaaaaally fresh backup of your site before activating this.
You can also activate the Optimize the Javascript Code option, jsut remember to make a backup

So at least in Drupal there are ways to deal with it. Hey dont blame IE for teaching you about web server performance and making you lost 4 hours of your life yelling like a crazy schoolgirl before a Jonas Brothers concert.

Hate the Computers Gnomes, yeah thoses little rascals causing trouble again.




Drupal Lightbox2 and Paging

So I had a strange problem with an ecommerce site Im developing. The site shows in the front page some products. The Owner told me to put a button with the magnifying glass over there, and when clicked, make it appear a modal box that shows more info of the product.

The Magnifying Glass in all it splendor

So hands at work, i use the lightbox2 and views module to make something like the owners command. The frontpage must show 8 products and if we have more, use a pager to navigate between products.

This is the pager, just in case youre asking what is a pager.

The problem? The view use paging so i show only the first eight products in the first page but if we go to the second page, problems occurs. The lightbox show all the modal boxes with the information of the first page. Oh god i smell some bug induced headache soon


The Solution
So after an entire day of debuging I found the problem: Lightbox2 is not taking in account the page you are when it retrieve the data. Basically lightbox2 use the load() function of jquery to get the WHOLE page it need to extract the info. The url of the page is inserted by lightbox2 usign the template in the file lightbox2_handler_field_lightbox2.inc

You have to change the line 124 like this:
Before:

// We don't actually use the link, but we need it there for lightbox to function.
if (empty($link)) {
// Get the path name.
$path = isset($_GET['q']) ? $_GET['q'] : '';
//Created By Carlos
}

After:

// We don't actually use the link, but we need it there for lightbox to function.
if (empty($link)) {
// Get the path name.
$path = isset($_GET['q']) ? $_GET['q'] : '';
//Created By Carlos
if(isset($_GET['page'])){
$path = $path .'?page='.$_GET['page'];
}
$link = url($path, array('absolute' => TRUE));
}


I just get the GET value of the current page and if it have a variable called page, append ?page= and the number of the page to the path that will be inserted in the lightbox trigger. Question anyone?

Adding new fields to the Ubercart Checkout module

So, you are using Ubercart and Drupal, but the checkout address fields isnt enough for you. Lets say, you need to add some more fields like a cellphone number or a district field. Well you have come to the right place, but before this, let me give you some advice.

Before the hack/slash
  • There is a module called Extra Fields, that give you the ability to input some extra fields to your checkout page. But you can't insert your fields to the billing and delivery panel. It just create a new panel to put that extra info. Maybe with some CSS and JS you can move the extrafields to the biling and/or delivery panel.
  • There is a webform to ubercart checkout module, its in beta stage, if you need more thant text boxes maybe this is the module you are looking for.

Into the Abyss
This tutorial is not for beginners, but with a little know of copy and paste you can do the magic. User with a cpanel hosting can use the file manager and phpmyadmin to easily modified the required files and tables.

Also remember that hacking your Drupal Files is not something that i recommend, but in some cases, its the only way to do things here. I didnt know too much about hooks in Drupal, but for what can i see in the code, i think it isnt possible for this Ubercart version to create hooks to modify the delivery and billing panels.

Step o : Requisites:
Obviously you will need to install
Ubercart 2.X with all the required modules. I used Drupal 6.15 for this tutorial, but I think it will work well with any Drupal 6 version.

Then, fill your Drupal+ Ubercart installation with some products and the info of your store. Make sure you install the checkout module of Ubercart.

Next step is creating a backup of your files and your database. You are not going to advance to the next step until you make your lifesaver backup. Seriously dont go ahead without your backup.

Also, before we going any further, theres something strange i need to explain first. The checkout panel contains two important panels, the delivery panel and the billing panel. Essencially those panels share the same fields, and, for some strange reason in ubercart, if you only need a field in one panel, you are going to create it in both panels and save that info in your database of both fields.You can hide one of them if you dont need it anyway.

In this example I'm going to create a new cellphone field for the billing and delivery address.

Step 1 : The database

First we need an identifier name for our new field. It should be a word in lower case. In my example I will just call it cellphone. Next thing is insert that variable in our database.
  1. Use any DB manager (here im using phpMyAdmin) to update the table called variable and search for the row with the name uc_address_fields. This row contain the list of all the variables used in the checkout panel. Dont be scare, the text here is just a serialized php array. Now add a line containing something like this: s:9:"cellphone";s:9:"cellphone" (sic) somewhere between two semicolons, just like my image. Notice that you are going to repeat twice your new field. And for the curious s:9 means [s]tring of nine spaces. cellphone is a word with 9 letters. Just look how the other fields are stored here.
s:9:"cellphone";s:9:"cellphone";

2. Add the fields billing_identifiername and delivery_identifiername. to the uc_orders table. In this example im going to create billing_cellphone and delivery_cellphone. Its doesn't matters if you are going to use only one of them, you will need to create both.

The new fields on the uc_orders table

And thats its for the database. The next step is modifiendo the uc_store.module file.

Step 2 : Playing with ubercart/uc_store/uc_store.module file
Here is where the copy&paste party begin:
  1. Search for the function uc_store_address_fields_form() that should be around the line 702. Now you see that big array? just add a field that identify your new field. I suggest using your identifiername for the array.

$fields = array(
'first_name' => array(t('First name'), TRUE),
'last_name' => array(t('Last name'), TRUE),
'phone' => array(t('Phone number'), TRUE),
'cellphone' => array(t('Cellphone number'), TRUE),
'company' => array(t('Company'), TRUE),
'street1' => array(t('Street address 1'), TRUE),
'street2' => array(t('Street address 2'), TRUE),
'city' => array(t('City'), TRUE),
'zone' => array(t('State/Province'), TRUE),
'country' => array(t('Country'), TRUE),
'postal_code' => array(t('Postal code'), TRUE),
'address' => array(t('Address'), FALSE),
'street' => array(t('Street address'), FALSE),
);

What is that t() function surrounding the text? It just a drupal functions that allow that text to be translated. Just
copy it as you see here.

2.- Now, next to that big array you just modified, there is a line under it,with a function called variable_get, it could be the line 728 but in any case it should be nearby. Add your identifier name inside single quotes as a parameter of the drupal_map_assoc function, like this:
$current = variable_get('uc_address_fields', drupal_map_assoc(array('first_name', 'last_name', 'phone', 'company', 'street1', 'street2', 'city', 'zone', 'postal_code', 'country','cellphone')));
3. Now go to the function uc_get_field_name that should be near the line 1177 and you will see another array. Just copy and item of the array and paste it and change it using your identifier name like this: 'cellphone' => t('Cellphone number'),

4.Next, go to the function uc_address_field_enabled near the line 1207 and you will find something like step two. Just add your identifier name as the last parameter of the drupal_map_assoc function.

5. This is the most important step on store.module, coz this is where you tell the database to obtain the address values. Go to the function uc_get_addresses near the line 1442 and you will see two database queries one for Mysql and the other one for Postgres. Modified the sql that you use, should be like this using the mysql select:

$result = db_query("SELECT DISTINCT ". $type ."_first_name AS first_name, "
. $type ."_last_name AS last_name, ". $type ."_phone AS phone, "
. $type ."_company AS company, ". $type ."_street1 AS street1, "
. $type ."_street2 AS street2, ". $type ."_city AS city, "
. $type ."_zone AS zone, ". $type ."_postal_code AS postal_code, "
. $type ."_country AS country, "
. $type ."_cellphone AS cellphone FROM {uc_orders} WHERE uid = %d "
."AND order_status IN ". uc_order_status_list('general', TRUE)
." ORDER BY created DESC", $uid);

6. Now lets get back to line 336, here we are going to copy and paste one of those lines below, copy it and change it. With the cellphone example it should be like this:
  $conf['i18n_variables'][] = 'uc_field_cellphone';  

Step 3 : Playing with ubercart/uc_order/uc_order_order_pane.inc
This is easiest. There are two modifications, one for the delivery and one for the billing:

1. For Delivery: Go to the function uc_order_pane_ship_to and you will see a switch case. Look for the 'edit_form' case in line 27, this is where you have to copy&paste one of the if, and make 4 changes. Heres an example of before (phone) and after (cellphone).

    Before:
if (uc_address_field_enabled('phone')) {
$form['ship_to']['delivery_phone'] = uc_textfield(uc_get_field_name('phone'), $arg1->delivery_phone, FALSE, NULL, 32, 16);
}
After:
if (uc_address_field_enabled('cellphone')) {
$form['ship_to']['delivery_cellphone'] = uc_textfield(uc_get_field_name('cellphone'), $arg1->delivery_cellphone, FALSE, NULL, 32, 16);
}
Once you have done this, you can modified the line 24 (the view case) if you want that the info fo your field appears in the Orders options of ubercart, the page where you see the data of your order as an admin. This is an example with the line 24 modified for cellphone

$output = uc_order_address($arg1, 'delivery') .'
'. check_plain($arg1->delivery_phone) .'
'. check_plain($arg1->delivery_cellphone);


2. For Billing, just repeat this step but look out in the line 122. if you want the billing data to show in your Order page, just modified the line 112 like in the delivery example.

Step 4 : Playing with ubercart/uc_order/uc_order.module file

1. (Optional) Add our field as a token. go to the line 407 inside the function uc_order_token_values. Here you should copy one of those lines, paste and modified it. Create one line for the billing and one for the delivery. In my example it should be like this (the red part is the new):

$values['order-shipping-phone'] = check_plain($order->delivery_phone);
$values['order-shipping-cellphone'] = check_plain($order->delivery_cellphone);
$values['order-billing-cellphone'] = check_plain($order->billing_cellphone);
$values['order-shipping-method'] = is_null($ship_method) ? t('Standard delivery') : $ship_method;


2. (Optional) Give a description of that token. Go to the function uc_order_token_list, near line 441 copy an paste one of those lines. Heres an example for the billing an delivery description:

$tokens['order']['order-shipping-cellphone'] = t('The cellphone number for the shipping address.');
$tokens['order']['order-billing-address'] = t('The order billing address.');
$tokens['order']['order-billing-phone'] = t('The phone number for the billing address.');
$tokens['order']['order-billing-cellphone'] = t('The cellphone number for the billing address.');


3.The code that save your field in the db. Go to the function uc_order_new near line 1013 and search inside it for an sql with the insert command. Modified it so it insert data into the rows create in step1. Remenber one for the delivery and one for the billing field. The sql would look like ( the ... is a resume, dont take it literally!!!)

db_query("INSERT INTO {uc_orders} (..., created, modified,billing_cellphone,delivery_cellphone) VALUES " ."(..., %d, '', '')",

4. The code that update your field in the db. go to the function uc_order_save near the line 1046 and look for the sql that update your data. Modified it so it update your field.

Step 5 : Playing with ubercart/uc_cart/uc_cart_checkout_pane.inc file
1. Modifing the checkout_pane_delivery hook. This hook is called to interact in the checkout module of Ubercart. Go to the function uc_checkout_pane_delivery near the line 224, copy and paste one of those if statement inside it and modified it according to your identifier word, like this:

if (uc_address_field_enabled('cellphone')) {
$contents['delivery_cellphone'] = uc_textfield(uc_get_field_name('cellphone'), $arg1->delivery_cellphone,uc_address_field_required('cellphone'), NULL, 32, 16);
}


2. Go to the case 'process' near line 292 and copy and paste one of those $arg1, modified it accordly:
$arg1->delivery_phone = $arg2['delivery_phone'];
$arg1->delivery_cellphone = $arg2['delivery_cellphone'];


3. Reviewing your field (optional). Go to the case 'review' near line 293. This line is called to review the data of your field when a client make an order.I just copy and paste some text there but maybe you would need some more exotic validations here.

if (uc_address_field_enabled('cellphone') && !empty($arg1->delivery_cellphone)) {
$review[] = array('title' => t('Cellphone'), 'data' => check_plain($arg1->delivery_cellphone));
}

4,5,6 This is the same as 1,2,3 but is for the billing panel. Go to the function uc_checkout_pane_billing in line 371 and modified it if you wish to have an field in the billing pane.

NOTE: you can choose here to do only a field in the delvery or the billing panel, or maybe both. Just follow instruction 1,2,3 for the delivery panel and/or 4,5,6 for the billing panel.


Step 6 : Some js in ubercart/uc_cart/cart.js file
Have you seen that checkbox that copy the billing field to the delivery field? Well you can modified it if you want to copy your new billing_field into your delivery_field. Go to the line 129 and see some repetitive code of the fields. Heres the code i create for copying my new cellphone field.

$('#edit-panes-' + temp + '-phone').val(address.phone).trigger('change');
$('#edit-panes-' + temp + '-cellphone').val(address.cellphone).trigger('change');
$('#edit-panes-' + temp + '-company').val(address.company).trigger('change');



Thats it folks, its not easy but with this we are covering all the step to create a new checkout field in ubertcart. Enjoy

Directoy Problems with Drupal

So im testing Drupal, the uber CMS. Its so great to have a tool like Drupal to create webpages. But well im new into this and i had an interesting problem.

I create a site called Akami*, and made the mistake of creating it in a subdirectory called Amaki, notice the 'm' and the 'k'. In my localhost the page works as it should, but then i deployed it on a real server, in his REAL subdirectory "Akami", so i was having problems because all the routes where pointing at Amaki instead of Akami.

The Solution:
Flush the cache. For this I recommend to install the Admin Menu Module, it will make you life easy, and well if you use Drupal 6.14 (the last version) use the Alpha.3 version of the AdminMenu, or the latest alpha. Anyway in orden to recreate the menu you have to flush it. In this case you have to go to the url pointing that is pointing to the Flush button in the admin menu:


And the go to that site, of course here amaki is wrong so you have to manually change the wrong name to the true name. In this case from amaki to akami.Then press the flush all caches and youre done. Hope this will be helpfull for someone.

* The true site name is hidden for security reasons ^^