Fieldsets and Drupal settings forms

Blame my lack of experience with Drupal. This week I was held up on a weird problem, and for once the online documentation didn’t seem to be helping.

I was coding a module, with a number of parameters. To keep things tidy, I decided to group them in fieldsets. And, not being too clear on the consequences, I set those fieldsets’ #tree parameter to TRUE. Here’s what it looked like:

Blame my lack of experience with Drupal. This week I was held up on a weird problem, and for once the online documentation didn’t seem to be helping.

I was coding a module, with a number of parameters. To keep things tidy, I decided to group them in fieldsets. And, not being too clear on the consequences, I set those fieldsets’ #tree parameter to TRUE. Here’s what it looked like (simplified example):

function foomodule_admin_settings() {
  $form['foo'] = array('#type' => 'fieldset', '#title' => t('Foo'), '#tree' => TRUE);

  $form['foo']['testmodule_bar'] = array('#type' => 'checkbox',
    '#title' => t('Bar'),
    '#description' => 'Bar',
  );

  $form['foo']['testmodule_baz'] = array('#type' => 'textfield',
    '#title' => t('Baz'),
    '#size' => 20,
    '#description' => t('Baz'));
    

  return system_settings_form($form);
}

What I found then was that the settings wouldn’t save. There were no errors, I got the normal message that “The configuration options have been saved.” but the values in the form were not updated.

After a bit of experimentation and reading up on how Drupal saves these settings, I figured out that the message was correct: my options really were saved, but not in the way I expected.

First, Drupal saves persistent variables in a table, named variable. Each record in this table has two fields: name and value. This field doesn’t exactly hold the value: for some reason Drupal also stores its type and (if it’s a string or array) its length. So (ignoring fieldsets for the moment) the value field for variable “bar” might be

b:1;

(“b” for “boolean”)

—while the value for “baz” could be

s:8:"whatever";

(“s” for “string”)

Apparently, if you’re editing these fields manually, you have to be really careful to make the stored length match the value’s actual length, or Bad Things will happen.

So here’s what it looks like is happening: if a form element is set to '#tree' => TRUE, its child elements’ values will not be stored in the database. Instead, it will get its own line in the variable table, with the value being an array of its child elements’ values. Which here, would look something like this:

a:2:{s:3:"bar";b:1;s:3:"baz";s:8:"whatever";}

This behaviour makes sense, but it seems to break everything about persistent variables. Fortunately there’s a simple solution. Just don’t set ‘#tree’ to TRUE, and the form elements’ values will store correctly. There we go, easy-peasy.

I Overdosed Twice

This Saturday I took part in Vancouver’s 10:23 Challenge (“Homeopathy – There’s Nothing In It”) A bunch of CFI people on the steps of the Art Gallery, doing a homeopathy demonstration (complete with whacking the magic elixir against a leather-bound Bible, which is what Hahnemann apparently preferred), and some of us overdosing on homeopathic medicine. Or I should say, “medicine,” with sarcastic quote marks.

This Saturday I took part in Vancouver’s 10:23 Challenge (“Homeopathy – There’s Nothing In It”) A bunch of CFI people on the steps of the Art Gallery, doing a homeopathy demonstration (complete with whacking the magic elixir against a leather-bound Bible, which is what Hahnemann apparently preferred), and some of us overdosing on homeopathic medicine. Or I should say, “medicine,” with sarcastic quote marks.

Arnica Montana (30C dilution)

I was told this was a muscle relaxant, but according to homeopathic web sites I consulted later (emphasis theirs):

Produces conditions upon the system quite similar to those resulting from injuries, falls, blows, contusions. Tinnitus aurium. Putrid phenomena. Septic conditions; prophylactic of pus infection. Apoplexy, red, full face.
It is especially suited to cases when any injury, however remote, seems to have caused the present trouble. After traumatic injuries, overuse of any organ, strains. Arnica Montana is disposed to cerebral congestion. Acts best in plethoric, feebly in debilitated with impoverished blood, cardiac dropsy with dyspnoea. A muscular tonic. Traumatism of grief, remorse or sudden realization of financial loss.(source)

Apparently Hahnemann “found it helped heal everything from baldness and impotence to incontinence, cramps, bruises, general soreness, forgetfulness, travel sickness, sleeping problems, gout, rheumatism and emotional problems”(source)

The directions on the bottle were “5 pellets, 3 times per day or as directed by your health care practicioner.” I took around 80 in one shot, and sadly didn’t develop a Wolverine-like healing factor.

Silicea (200C dilution)

Imperfect assimilation and consequent defective nutrition. It goes further and produces neurasthenic states in consequence, and increased susceptibility to nervous stimuli and exaggerated reflexes. Diseases of bones, caries and necrosis. Silicea can stimulate the organism to re-absorb fibrotic conditions and scar-tissue.

[…]

Ill effects of vaccination. suppurative processes. It is related to all pustulous burrowings. Ripens abscesses since it promotes suppuration. Silica patient is cold, chilly, hugs the fire, wants plenty warm clothing, hates drafts, hands and feet cold, worse in winter. Lack of vital heat. Prostration of mind and body. Great sensitiveness to taking cold. Intolerance of alcoholic stimulants. Ailments attended with Pus formation. Epilepsy. Want of grit, moral or physical.(source)

An abundant mineral in the earth’s crust, silicia has a profound cleansing effect on the body. Long neglected and persistent ailments respond well to silicea therapy.

Silicea, derived from quartz or flint and an essential structural component of cartilage and bone, is used to treat chronic conditions that progress slowly over time. It is also very effective against seasonal ailments, such as colds. Like other homeopathic remedies, silicea is typically prescribed to relieve symptoms associated with particular personality types. Those most likely to benefit from silicea show such character traits as lack of direction, pliability, weakness, confusion, fear of failure and the kind of mental burnout seen in those who overwork to the point of exhaustion. Silicea is said to impart qualities that reflect its rock hard origins, structure in one’s life, clarity, steadfastness and reliability. Also referred to as silica, silicea has a powerful restorative and stabilizing effect on the human body.(source)

The directions on the bottle were also “5 pellets, 3 times per day or as directed by the physician.” Again, I scarfed down 80 of the little buggers, and didn’t start looking like The Thing. Just as well, old Ben Grimm acts like he’s Blessed with Suck most of the time.

So that was kind of fun. What really struck me looking up these medicines is how vague their effects are supposed to be. Seriously, sudden realization of financial loss? baldness? forgetfulness? Want of grit, moral or physical? Still, that’s par for the course for faith healing.

The Joy of Drupal, The Agony of Magento

I’ve been working for a small web development shop for the past few months. It’s interesting work, all open-source, all PHP-based. My first project was with Magento, and it was frakking painful.

I’ve been working for a small web development shop for the past few months. It’s interesting work, all open-source, all PHP-based. My first project was with Magento, and it was frakking painful.

I’m not just talking about the inevitable learning curve of tackling a new code base, and a (to me) whole new kind of CMS. The pain comes from an incredibly unintuitive code architecture that I keep having to wrap my brain around over and over.

From working with WordPress I was used to files for a given theme or plugin sitting together in one directory; this makes sense because they are all part of one module. Not so in Magento. Code, templates and other config elements are spread all across the system. From a design point of view I can sort of see why you’d want your business logic separate from your page templates, and both separate from your javascript, CSS, images and whatnot. You’d think it seems tidier, right? But in practice it makes extensions much harder to code than they should. To enhance or override core functionality, I have to know the exact names of these core classes and where they sit in the code directories, with no tidy hooks or API around which to build my functions.

And that’s not even counting the unholy tag soups in configuration XML files, with weird rules and redundancies that I haven’t been able to grok so far, so I just copy from existing samples and hope it eventually works. For example, according to A book to cook with Magento, config parameters defaults are set in the file config.xml, but if you want to view and modify them in the Web interface, that form is defined in another file, system.xml. My jaw literally dropped when I read up on this. How does it make any sense?

Mind-boggling or not, I’m grateful to blogs like A book to cook because there a serious dearth of online Magento documentation, official or otherwise. As often as not, googling particular issues led me to forum threads asking the same question I was researching… and nothing else, except maybe others chiming in to say they’ve got the same problem, or the same guy posting again a few months later to ask “What, nobody can help me?” Magento just doesn’t seem to have the same kind of active online community as, say, WordPress.

So what you end up with is a system that is way harder than it should be to enhance in any substantial way. Magento is open-source, sure, but if the source is a scary and confusing jungle of code, that doesn’t really help. No wonder people are willing to shell out megabucks for what you’d think are pretty minor extensions, instead of working it out themselves. Case in point:

The Backorder Button extension gives you the ability to display to your customers which of your products are currently on backorder.

If one of your products are on backorder, the Backorder Button extension will change the text’s of your “Add to Cart” buttons to “Backorder” (both in the product list, and on the product details pages), and the “Availability: In Stock” text’s (displayed on the product details pages) to “Availability: Available on Backorder.”. You can of course rewrite / customize the replacement text’s from the System Configuration.

$29 for this? Really? It took my coworker a couple of hours to figure out how to do it. But Magento’s deceptive: what looks simple and obvious isn’t always so. For instance, I had to abandon one extension that I thought at first would take me a few days, but later looked like many weeks of tedious hacking. It’s still on my to-do list, though: it’s useful functionality that should be present in an e-commerce system, but as far as I can tell nobody’s done in Magento yet. I tell you, if I ever make it work I’m going to be a fucking millionaire.

And then there’s Drupal

Now, I only have a few weeks’ actual experience with Drupal. I’d started playing with it a few months ago in preparation for a large volunteer web design project—that will end up using another CMS, but that’s another story. Then last month at work I finally got to do some actual Drupal development.

And it’s true, there’s a steep learning curve, which I’m only starting on. But unlike Magento, the learning process really isn’t frustrating. There are plenty of resources to help me with issues, and at the end of the day I just feel productive: Drupal development is way more straightforward—no mucking around with core classes, no having to create a dozen files in five different directories just for a simple “Hello World” module. Drupal is complex, but not overly complicated. It feels elegant. It makes sense, and I like that. Drupal is, frankly, a joy to work with.