Drupal
Drupal and e-commerce
I recently helped a friend setting up his new E-commerce site (http://www.weinerwraps.com/) using Drupal. We were considering a few modules, and finally decided on using UberCart. Now, our site isn't flashy, or have fancy graphics, but getting it functional was really easy. What we currently have working is
- Paypal payment option
- USPS shipping (with shipping calculations)
- Basic cart features, different products, checkout options etc.
We've had a few issues on the way, most notably (and very confusing) was that the shipping cost calculator stops working if you disable the country field from the user entry for the shipping address. This made absolutely no sense to me (since we only ship to the US), and there were no errors or indicators whatsoever. Clearly someone didn't think through a typical use case scenario here ... Other open issues include
- We have an optional addition to each order, for embroidery, where we'd like the price to be adjusted based on the length of the entered text.
- There's no way to make the product picture adjust to selected options. There are a few modules that claim to do this, but none that really works.
All in all, setting up an E-commerce site with Drupal and UberCart has been a pretty good experience.
Must-have Drupal modules
This collection of pages is my own personal experience with various 3rd party Drupal modules. I'm not really saying you must have these modules, but I personally find them incredibly useful. I'm not ranking these modules in any particular order, instead I'm trying to organize them by functionality. If you have suggestions for modules that I ought to include here, please let me know, and I'll be happy to add them (after I try 'em of course).
Content related modules
The modules in this section either create new content types, or let you manipulate or create content types.
CCK
The CCK module is probably the most important module here, it's a very flexible system that lets you create new content types, or add new custom fields to existing content types. This really is a must have, I actually don't understand why it's not part of core Drupal. There's a number of extra "plugins" for CCK, here are a few that I always add
- email - Add email fields
- phone - Add phone number fields (including international numbers!)
- drupal.org/project/filefieldfilefield - Add file fields
- imagefield - Add image fields
Date
The Date module is a combination of a complete Date related API, and various extensions for content types, and it integrates nicely with CCK for example.
Images and image manipulation
There's a large number of modules related to images, how to manage and display them, as well as manipulate them. Here's a small collection of must-have's.
Ogre is upgraded to Drupal6
I finally finished migrating http://www.ogre.com/ to Drupal v6. This was a pretty painful experience, as usual with Drupal, but not as bad as the Sharks site upgrade. The biggest pain is usually "complex" modules like Views and CCK. In particular, the Views module does a piss poor job of converting the old views to the new version... Expect to change a lot of configurations after the migration :-/.
The other pain right now is that the Node Relativity module is not functional for Drupal 6. This mean that some navigation of this site is currently broken, I hope to have it fixed as soon as possible.
Adventures in upgrading from Drupal v5.x to Drupal 6.x
Introduction
I've been using Drupal (v4.x and 5.x) for quite a while now. I've postponed the upgrades to 6.x to wait for stability, but more important, make sure all the additional modules I use become available for v6.x. Don't get me started with the annoyance that Drupal keeps breaking module compatibility between every major release, it'd be so nice to finalize these APIs at some point. In any case, I finally decided to go ahead and start migrating from v5.14 to the current Drupal 6.8 release. And this is an attempt to document the successes, failures and problems that I encoutered.
Before upgrade
Before you do anything else, make a backup of your database. Don't skip this step, you will most likely regret it.
One important thing to do before upgrading is to make sure the old Drupal system is completely up to date. Make sure you have installed the latest Drupal 5.x version (currently 5.15), and that all modules you use are up-to-date (using the Update Status tool would be a good idea now). You might also want to consider upgrading modules that have major updates for both v5.x and v6.x, so that you use the latest versions (APIs) etc. with Drupal 5 first. Also remember to re-run the /update.php script after you do all these upgrades, to assure the database is completely up to do. It might be a good idea to run it at least twice, to make sure all changes are taking effect (and obviously look for any errors and warnings).
After running all the upgrades, disable all third party modules that your site is doing. This is a critical step, as I found out several modules do not handle a massive upgrade at all (for example, CCK). Disabling these modules assures that during the first upgrade steps, you do not force Drupal to do all upgrade changes in one attempt. I don't know why this makes a difference, but trust me, it does.
Since I run multiple Drupal sites, I decided to install Drupal 6.x in parallel with my old installation, this allows me to migrate one site at a time. In order to make it even easier to do this safely, I actually duplicate each site first, making a mySQL copy of the entire database, and a new DNS entry. This will posibly require a small change in your site config (for the base-URL), but it's a small price to pay. In particular, this lets me see how the old configurations were done and compare that to the "new" site after the upgrade. In my case, I had a site, http://www.boot.org/, the new site was temporarily named http://www6.boot.org/. Once the migration is finished, this obviously goes away, and I deleted the old database.
Install the modules you need, either now, or one by one. Remember, Drupal 6 will need all new versions of all external modules. As long as you have them disabled in the site, it should be ok, but if you want to be extra careful, don't unpack these modules yet (just get the tar-balls in preparation). If you are using a third party theme, make sure to install the new version of it. If not, make sure you switch the default (and/or admin) theme to one that is included with the base Drupal 6 package.
Upgrading Drupal
This is the easiest part, and I had no problems with this step. Assuming you've got your Apache configured properly for the new Drupal system, just go to the base URL, and append /update.php. Note that this has to be done as the privileged user (the first account created), unless you modify the script (not recommended). After the upgrade, verify the modules settings, configurations, ACLs etc. that they are still correct.
There is one huge caveat: Even though you (hopefully) have disabled all the 3rd party modules in the prep stage, you must delete the modules from the doc root. This really, really sucks, but I've noticed that the upgrade will kick in for some modules even when disabled (for example, Image does this nonsense). Since I now have many Drupal 6 sites, this means I have to duplicate my Drupal installation into yet another docroot during the upgrade, so I can remove all the modules, and add them back one by one. This is extremely annoying...
Upgrading CCK
I use the CCK module extensively, and this part of the upgrade is what caused me most problems. My first attempt to upgrade failed, because I didn't follow the instructions to disable all external modules before doing the upgrade. This caused the CCK upgrade to partially fail, in particular three content field types did not get migrated properly. They all showed up with errors saying the module needed were not available or activated, but they for sure were. I could recreate new versions of the fields with no problems. After restoring the DB, and started over from scratch, I followed the instructions, and things worked a better. The content field based on the Fivestar module still shows up as inactive, because it claims some module is missing (which it isn't). I have not yet figured out how to solve this problem... Here's what I've tried so far, which at least lets me delete the field, and recreate it with the same name / configs (which preserves the data already stored in nodes):
thor $ mysql -u foo -p
mysql> update content_node_field_instance set widget_active=1 where widget_active=0;
Query OK, 2 rows affected (0.01 sec)
Rows matched: 2 Changed: 2 Warnings: 0
mysql> update content_node_field set active=1 where active=0;
Query OK, 2 rows affected (0.01 sec)
Rows matched: 2 Changed: 2 Warnings: 0
The CCK Validation module no longer works with Drupal 6, so I migrated to the Validation API module instead. Here are the changes I had to make:
Before (using CCK validation):
$dvd = $node->field_id_of_dvd[0]['nid'];
$checksum = crc32($dvd);
...
if (strval($checksum) !== $node->field_validation_code[0]['value']) {
form_set_error('field_validation_code','this is not the correct validation code for this DVD');
}
After (using Validation API):
$dvd = $form_state['values']['field_id_of_dvd'][0]['nid'];
$checksum = crc32($dvd);
....
if (strval($checksum) !== $value) {
return FALSE;
}
return TRUE;
Here's a short summary of things I had to fix, or had problems with:
- The Fivestar field did not make it through the migration. I had to recreate a new field, and modify all nodes with appropriate values. (See above).
- The Location based input fields lost (or is missing) all settings, so I had to reconfigure this completely.
- Migrated from CCK Validation module to the Validation API module. I'm still however unable to delete the old CCK field, since there is no module for it (even activating the field as above does not help).
Upgrading Views
This turned out to be even more of a pain in the ass, because the migration process from Views v1.x to Views 2.x is very poor. You'll have to go to the Tools area in the Views GUI, and select to migrate each individual View to the new system. This partially works, i.e. you get the proper View names etc., but you'll have to basically reconfigure all filters, and in some cases, display fields manually. At least that's what I had to do. Here's a short list of things I ended up having to "fix" after the upgrade (this is where having the old site available is a great idea, to see how the old configs were done):
- All Filter rules had to be examined, particularly where there are "errors" in the rules lists.
- All Argument settings had to be recreated (they were simply gone).
- I had a number of "Link" type fields, all of these had to be reconfigured.
- Many of the Field definitions lost various configuration settings, like, if the value should be a link or not. You'll have to verify each and everyone of them.
- Location based Views were completely messed up, and I ended up having to reconfigure most of them (for example, the Style shows up as "Unformatted", which obviously isn't right).
Upgrading the Image module
This upgrade is incredibly painful, and I had to try three times before I succeeded. The key tricks here are
- Make sure you upgrade to the 2.x version of the Image module. This is currently in alpha/dev release, but without this, you upgrade will fail, guaranteed.
- Definitely remove the Image module when doing the core Drupal code upgrade. Even without the Image module activated, something kicked in during upgrade and caused it to fail.
Missing / replaced modules
Here's a short list of modules that no longer seem to exist for Drupal 6, and what alternatives to use.
- The CCK Validation module is not supported, look into Validation API instead.
- TAPIr is not used by the new Ubercart, which uses Forms API instead.
- WorlflowNG is replaced with Rules module.
- The UberCart Coupon module is still not ported to v6, I don't know of any alternatives.
What's next?
Drupal Update Status module
Who needs CPAN with Drupal and the Update Status module (http://drupal.org/project/update_status). Using this module, it's really a no brainer to keep your site up to date with all the latest updates to the Drupal core and contributed modules you have installed. It'll tell you which modules needs an update, the severity (e.g. Security related), and if there are some optional (typically beta or "dev") versions available. To make things easy, you can even have it email you when there are updates available. And there is of course a GUI component as well, which lets you instantly view the status of all the modules.
It's a must have for any Drupal adminstrator.
Bar charts with Drupal's charts module
I started playing with the Drupal charts APIs a while ago, which uses Google's excellent charting APIs. This mostly worked well, except that the bar charts "class" did not support modifying the spacing between groups of bars. So, here's a small patch that solves this.
--- chart.module.orig 2008-12-23 09:53:48.000000000 -0800
+++ chart.module 2008-12-23 09:52:01.000000000 -0800
@@ -549,7 +549,7 @@
// Bar chart bar sizing
case 'chbh':
- $data[$attr] .= implode(',', array($value['#size'], $value['#spacing']));
+ $data[$attr] .= implode(',', array($value['#size'], $value['#spacing'], $value['#group_spacing']));
break;
// Mixed axis positions, labels and styles
@@ -1028,10 +1028,11 @@
*
* @return array
*/
-function chart_bar_size($size = 40, $spacing = 20) {
+function chart_bar_size($size = 40, $spacing = 20, $group_spacing = 30) {
return array(
'#size' => $size,
'#spacing' => $spacing,
+ '#group_spacing' => $group_spacing,
);
}
Drupal and SourceForge
SourceForge recently changed their site to put their Apache servers behind a "pool" of Nginx reverse proxies (accelerators). This is a good idea, but has negative impact on various Drupal features, like, logs, ACLs etc. I've made a small hack on my http://pysearch.sourceforg.net/ Drupal installation, like this:
--- includes/bootstrap.inc.5.10 2008-09-23 08:53:05.000000000 -0600
+++ includes/bootstrap.inc 2008-09-20 10:14:52.000000000 -0600
@@ -5,6 +5,9 @@
* @file
* Functions that need to be loaded on every Drupal request.
*/
+if ($_SERVER['HTTP_X_REMOTE_ADDR']) {
+ $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_REMOTE_ADDR'];
+}
/**
* Indicates that the item should never be removed unless explicitly told to
Granted, this needs to be configurable, I'm thinking a general Drupal setting where we can tell which Header to use to replace REMOTE_ADDR.
Breadcrumb trails with node relativity (Drupal)
I couldn't get the breadcrumb trails (menu) to work with my pages / stories that I structure with node relativity (a Drupal module). I don't know if I'm doing something wrong, but looking at the code, I couldn't see any support for it. So, here it is, a quick and dirty hack to add the breadcrumb trails to your node relativity structures:
--- relativity.module-2.4 2008-09-17 19:44:07.000000000 -0700
+++ relativity.module 2008-09-18 07:49:10.000000000 -0700
@@ -378,6 +378,14 @@
'#title' => t('Global Options'),
);
+ $group['global_options']['relativity_breadcrumb_trails'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Update the breadcrumb trails menu'),
+ '#return_value' => 1,
+ '#default_value' => variable_get('relativity_breadcrumb_trails', 0),
+ '#description' => t('If checked, the ancestor hiearchy of the page is used to create the breadcrumb trail menu.'),
+ );
+
$group['global_options']['relativity_allow_types'] = array(
'#type' => 'select',
'#title' => t('Node types that can be involved in relationships'),
@@ -1067,13 +1075,35 @@
break;
case 'view':
- if ($w = variable_get('relativity_'.$node->type.'_ancestor_weight', 0)) {
+ $do_breadcrumbs = variable_get('relativity_breadcrumb_trails', FALSE);
+ $ancestors_w = variable_get('relativity_'.$node->type.'_ancestor_weight', 0);
+
+ if ($do_breadcrumbs || $ancestors_w) {
$ancestors = relativity_load_ancestors($node);
+
if (is_array($ancestors) && count($ancestors) > 0) {
- $node->content['relativity_ancestors'] = array(
- '#value' => theme('relativity_show_ancestors', $node, $ancestors),
- '#weight' => $w,
- );
+ if ($do_breadcrumbs) {
+ $breadcrumb[] = l(t('Home'), NULL);
+ foreach($ancestors as $ancestor) {
+ if (!is_array($ancestor)) { // Only handle single ancestors here
+ if (array_key_exists("path", $ancestor)) {
+ $breadcrumb[] = l($ancestor->title, $ancestor->path);
+ } else {
+ $breadcrumb[] = l($ancestor->title, 'node/'. $ancestor->nid);
+ }
+ }
+ }
+ if (count($breadcrumb) > 1) {
+ drupal_set_breadcrumb($breadcrumb);
+ }
+ }
+
+ if ($ancestors_w) {
+ $node->content['relativity_ancestors'] = array(
+ '#value' => theme('relativity_show_ancestors', $node, $ancestors),
+ '#weight' => $ancestors_w,
+ );
+ }
}
}
And yes, I did file a "issue" for this, with the Drupal people, http://drupal.org/node/309982 .