Full functional in-browser testing, including javascript and AJAX. I'll be presenting a brainstorm on this at the Core Dev Summit and there will be a BoF on this topic at 4pm on Monday in room 200. We have to solve our lack of test coverage in this area. AJAX and javascript get essentially no real test coverage, so it's like the old days... somebody has to report that something is broken. Even with things as important as install.php.

Every feature should have a full, working example in the tests module. We create "mock modules" to write tests against... but sometimes features actually go in that nobody knows how to use. A simple remedy: Before commit, there needs to be a comprehensive example in the related mock module in the tests. The comprehensive example can be used as fodder for tests, but it's also there for people to see how to use something. Enable the mock module, try it out. Recently the fantastic #states feature went in with no documentation and essentially no usage examples. And it wasn't testable because we don't have Javascript testing. But if we had the requirement of a comprehensive example, we'd have been fine (and several bugs would have been avoided.)

What are your suggestions for software process improvements in D8? Let's talk about this at the Core Dev Summit on Saturday!

Alex Bronstein, (effulgentsia) one of the maintainers of the Form API, will be doing an off-Broadway session on D7 Advanced Form API tomorrow (Wednesday) at 4:15pm in room 252. This is an exciting chance to catch up on all the great simplifications (and changes) in D7 FAPI.

Edit 2012-11-12: If you're interested in the newer problem of running PHP 5.3 on Ubuntu 12.10 Quantal, try this recipe.

Edit 2012-09-21: Isn't it about time you moved to PHP 5.3? Even though these instructions seem to work even for Ubuntu 12.04, it's really time for people to move on to PHP 5.3. If you're a Drupal user on Drupal 6, Drupal core and nearly all contrib are now just fine with 5.3.

Edit 2011-11-23: Since Ubuntu 9.10 (Karmic) is now out of support, the repositories to use for it have changed to old-releases.ubuntu.com. I've changed the karmic.list files attached. Please be aware that although 10.04LTS is still supported for years still, 9.10 is out of the support window, meaning that security issues in these packages will not be fixed.

Drupal 6 and Drupal 7 Menu Example. These examples use nearly every feature of the Menu API, and provide easy-to-access examples of tabs, placeholders, and many of the other fairly obscure features of the Menu API. See the code on api.drupal.org or experience the examples at drupalexamples.info.

Examples for Developers is a community project. Contributions are encouraged (just use the issue queue). If you find a problem, please submit an issue. If you want to fix a problem you find, please submit a patch. It will never be perfect, but if we tend it as a community resource, it should get better all the time.

You may know that lots of delicious things have happened to Drupal's Form API in Drupal 7. (Only a geek can say "delicious" and "Form API" in the same sentence. Try it!) The finest minds in the business have been working on it, I can assure you. Give effulgentsia, fago, frando, and chx a big hug when you see them, because Form API is much improved. (Sorry to those of you I forgot to name, but THANKS!)

I'm going to do a series covering Form API changes, starting with this one. I won't attempt to cover the deep details, just the things that ordinary developers might use:

$form_state changes and form builder function signature changes

AJAX Forms changes

New properties (#attached and many friends)

Let me know if you have other topics to suggest.

OK, to business. This article is mostly parroted from the api.drupal.org topic: Form Generation. Thanks to Alex Bronstein (effulgentsia) for his reviews and contributions to that doc.

Don't forget that the form builder function signature changed!

In Drupal 6 the form builder function looked like this:

function my_module_funky_form(&$form_state) { ... }

but in Drupal 7 it's

function my_module_funky_form($form, &$form_state, ... ) { ... }

$form_state in Drupal 7

Mostly the members of the $form_state array are the same ones you know and love from Drupal 6:

$form_state['values']: An associative array of values that have been submitted to the form. The validation and submit functions use this array for nearly all their decisionmaking. (Note that #tree determines whether the values are a flat array or an array whose structure parallels the $form array.) This is nearly the same as it was in D6.

$form_state['rebuild']: If the submit handler sets $form_state['rebuild'] to TRUE, submission is not completed and instead the form is rebuilt using any information that the submit function has made available to the form builder function via $form_state. This is commonly used for wizard-style multi-step forms, add-more buttons, and the like. For further information see drupal_build_form(). This is the same as D6.

$form_state['redirect']: a URL that will be used to redirect the form on submission. See drupal_redirect_form() for complete information. This should always be used instead of drupal_goto() in a forms context. Note that $form['#redirect'] went away in Drupal 7 and no longer has any effect.

$form_state['storage']: $form_state['storage'] is no more! It used to be the place for application-specific values, but now it has no specific meaning. Now nearly all $form_state keys persist in a multi-step form, so the recommended approach is to use $form_state['your_module']['whatever']. ($form_state['storage'] still works for persistent storage, just like $form_state['timbuktu'] works.)

$form_state['triggering_element': (read-only) The form element that triggered submission. This is the same as the deprecated $form_state['clicked_button']. It is the element that caused submission, which may or may not be a button (in the case of AJAX forms.) This is often used to distinguish between various buttons in a submit handler, and is also used in AJAX handlers.

$form_state['cache']: The typical form workflow involves two page requests. During the first page request, a form is built and returned for the user to fill in. Then the user fills the form in and submits it, triggering a second page request in which the form must be built and processed. By default, $form and $form_state are built from scratch during each of these page requests. In some special use-cases, it is necessary or desired to persist the $form and $form_state variables from the initial page request to the one that processes the submission. A form builder function can set 'cache' to TRUE to do this. One example where this is needed is to handle AJAX submissions, so ajax_process_form() sets this for all forms that include an element with a #ajax property. (In AJAX, the handler has no way to build the form itself, so must rely on the cached version created on each page load, so it's a classic example of this use case.) Note that the persistence of $form and $form_state across successive submissions of a multi-step form happens automatically regardless of the value for 'cache'. You probably won't need to use $form_state['cache']. And note that $form['#cache'] is gone in D7 and now has no effect on anything.

$form_state['input']: The array of values as they were submitted by the user. These are raw and unvalidated, so should not be used without a thorough understanding of security implications. In almost all cases, code should use the data in the 'values' array exclusively. The most common use of this key is for multi-step forms that need to clear some of the user input when setting 'rebuild'.

That was the main news. But to make sure it actually worked I did a quick runthrough of installing Eclipse Galileo on Ubuntu 10.04 Lucid Lynx from scratch. This is essentially the same as what's in http://drupal.org/node/157609, but with less detail.

Bonus: Quick install of Eclipse Galileo with debugger on Debian/Ubuntu

Install the Zend debugging extension obtained above by downloading the correct package for your system and architecture. Follow the instructions in the installation file to install on your architecture. More details are at http://drupal.org/node/157609. Verify that phpinfo shows the "Zend Debugger".

apt-get install eclipse

In Eclipse, go to Help->Install New Software

Type "Galileo" and choose the Galileo update site

Expand "Web, XML, and Java EE development to get to "PHP Development Tools (PDT)" and install it.

If you use virtualhosts like I do, you need to create a new PHP server at this point. Click new, and give it the URL. For example, I created a new PHP server called d7git and used the URL http://d7git.l and pressed "Finish".

For the file, choose index.php

Uncheck "Auto Generate" for the URL and change the URL to http:/// (I changed it to http://d7git.l)

Click "Debug" and if you have succeeded, it will stop on the first line of index.php.

The Examples for Developers project is an open-source training initiative. I'm trying to get it used for developer training and to have books on Drupal development use it for examples instead of rolling their own (which invariably get out-of-date and can't be maintained.)

I encourage you in this (vast) initiative.

And what did I get?

Your submission has triggered the spam filter and will not be accepted.

That's about the fourth time I've taken the time to write a comment on a Drupal Mollom-enabled site, and gotten that kind of a response. How many comments are being rejected inappropriately on sites that use Mollom? Who will ever know?

At the same time, the only site that I have Mollom on, http://hobobiker.com, gets has spam comments approved daily. In fact, it never gets anything but spam comments, and Mollom seems OK with that.