CitizenSpeak Colophon

CitizenSpeak: your campaign
There were two projects in getting CitizenSpeak up and running: Developing the CitizenSpeak module and creating the CitizenSpeak site. While they were intertwined, they also provided distinct educations.

I found that the I18n module can serve dual purposes; it provides the Spanish language interface to the site as well as allowing us to customize standard English language messages. This is handy if you want customized labels for things, or your site isn’t as averse to capital letters as the Drupal project.

As an aside, only recently did I learn that name “I18n” is an abbreviation for the “Internationalization,” since “nternationalizatio” is 18 letters. I guess I just never bothered to count.

I was also happy to learn how to customize the output of other modules. The PHPTemplate and Smarty engines allow designers to customize how specific node types are displayed, what information is available to templates, and override any theme() call.

There are some lessons learned from what I did wrong, too. The first was choosing Smarty as the theme engine. While I’ve had good luck with Smarty in my own projects, the majority of work being done with Drupal seems to use PHPTemplate.

There’s nothing wrong with Smarty, the PHP library. For Drupal, however, there is a lot more support available for PHPTemplate, and PHPTemplate more likely to be kept up to date. Drupal’s PHP functions are more than adequate for theming, which negates Smarty’s advantage of having view-centric functions available to it.

I also wish I had created a site-specific module. A module is a great place to create custom pages and blocks, to use callback hooks like hook_nodeapi() and hook_user(), and to collect helper functions. A lot of things I did by customizing the display interface and variables could have been more elegantly handled by simply creating a module for the CitizenSpeak site and stashing everything there.

That about wraps up my posts on building CitizenSpeak. Please visit the site (maybe even click that donate button on the right), and thanks for reading.

Developing the CitizenSpeak Module

CitizenSpeak: your campaign
Yes, another CitizenSpeak post. I’ll probably do one more after this about how the site is configured, and then updates as events warrant. This time I want to talk about developing the module.

I’ll admit that it’s been a while since I started working on the CitizenSpeak module. Part of it was that I was donating a lot of the development effort and only getting paid for implementing the site. That means that keep-George-off-the-streets programming took priority over this.

Another part was that I hit a mental wall with Drupal’s module format. Having a monolithic .module file was not working for me, but I found that when I split it into several topical files it got much easier to deal with. If you look at the source code you’ll see that I’ve split functions into files by topic.

I even went one step further. A lot of Drupal hooks send an operation as the first parameter, take a look at hook_user() for an example. If you look at the CitizenSpeak implementation of hook_user(), it’s just a stub that calls other functions:

function citizenspeak_user($op, &$edit, &$user, $category = false) {
$function = "citizenspeak_user_" . $op;
if (function_exists($function)) {
return call_user_func_array($function, array($edit, $user, $category));

I then moved all the functionality out of giant switch() statement suggested by the docs and into individual functions in citizenspeak.user.php. The function arguments are redundant, but the manageable code is worth the repetition.

By moving everything out of the core file, I found it a lot easier to deal with the development and get into the groove. If I had one thing to tell someone getting started with Drupal module development, it would be that.

Looking ahead at the development, there are two big tasks. The CitizenSpeak module needs an API that will allow other modules to interact with it. The goal is to allow other modules to hook into the forms, campaign sending and reporting. One of the big things that everyone wants is CiviCRM integration and the CitizenSpeak API hook will allow that to happen. The other big task is to update the module for 4.7, which features new email and form APIs.

More About the CitizenSpeak Update

CitizenSpeak: your campaign
In the announcement yesterday I wrote that I would be blogging more about CitizenSpeak, and with this post the prophesy has come to pass.

Organizations have had tools like Capitol Advantage to create advocacy campaigns for quite some time. Those tools aren’t necessarily accessible for small or ad-hoc efforts due to the cost involved. CitizenSpeak offers a subset of their features — email-only campaigns and reporting — for free.

Now, when a blogger gets a bug up their butt about something that needs public outcry to fix (i.e. a proposed porch-couch ban in Ann Arbor, MI) they have a tool that will let them create a campaign and send all their readers to join in.

Even better, since its a GPL licensed module, anyone with a Drupal or CivicSpace can create their own campaign center. It can also build on things we chose to leave out of the site; things like categories, comments or any of the add-on modules that Drupal supports.

I can’t wait to see what other sites do with the module.

CitizenSpeak Re-launches!

CitizenSpeak: your campaign
Remember when I begged for money months ago? Well it payed off, and now the new CitizenSpeak has re-launched.

Briefly, CitizenSpeak is a site that allows people to create and host email campaigns. It allows ad-hoc organizing around any issue that puts a bug up someone’s butt. I’ll probably blog more about it later this week. In the meantime, check out the site or the open source Drupal module that I built for the site.

Big thanks to Jo Lee for being CitizenSpeak, Eric Gundersen at Development Seed for his fantastic design work and Embolden Design for providing hosting!

Drupal modules in RSS

One of the hard things about searching the web by keyword is that sometimes you want to find things with a specific relationship. Take Drupal’s module list for example. I want to know when there are new modules available, which is perfect for RSS.

There’s plenty of information about Drupal modules that make RSS, but it’s hard to find something about getting the module list in RSS. I’m sure the capitalized Semantic Web will make that easy, but until that happens I guess I’ll just have to roll my own.

So I set up an RSS feed at I scrape the page once a day (technically once a night in EDT, once an early morning in UTC, once a…) and make a fresh new RSS feed. If you know of any Drupal users/developers, you might want to let them know.

Drupal Atom Aggregator

One of the big problems with using the Drupal Aggregator for ArborBlogs was that it doesn’t support Atom out of the box. My initial fix was to create an Atom -> RSS converter using Magpie but this weekend I was able to set up Drupal to use Magpie for RSS and Atom parsing without the need for a mediator.
I don’t know how the Drupal community deals with contributions, I’ll investigate that when I have a chance, but if you’ve got a Drupal site and want to try out my modifications, you can try out my modified aggregator module. It creates modules/aggregator/aggregator.module so you’ll need to move modules/aggregator.module out of modules for it to work.