After reading A successful Git branching model [nvie.com], which I consider one of the best graphical/textual depictions of the ideal Git model for development teams (and most large projects), I simply wanted to adapt a similar (but way less complex) model for some of my smaller sites and multisite Drupal installs.

Since I'm (almost always) the only developer, and I develop locally, I don't want the complexity of working on many branches at once (master, hotfixes, develop, release, staging, etc...), but I do want to have a clean separation between what I'm working on and the actual live master branch that I deploy to the server.

master - the live/production code. Only touch when merging in a feature or simply fixing little bugs or really pressing problems.

[issue-number]-feature-branches - Where I work on stuff.

Graphically:

Any time I work on something more complicated than a simple styling tweak, or a fix for a WSOD or something like that, I simply create a feature branch (usually with an issue number that matches up to my internal tracking system). Something like 374-add-node-wizard:

While I'm working on the node wizard (which could take a week or two), I might make a couple little fixes on the master branch. After I make the fixes on master (switch to it using $ git checkout master), I switch back to my feature branch and rebase my feature branch:

$ git checkout 374-add-node-wizard # switch back to the feature branch$ git rebase master # pull in all the latest code from the master branch

I can also create simple .patch files off a branch to pass my work to another server or a friend if I want (I like using patches instead of pushing around branches, simply because patch files are easier for people to grok than more complicated git maneuvers):

Finally, I test everything to make sure it's working fine in master, and then push the code changes up to the server.

Since I'm developing alone, this is a lot easier than a more complicated branching setup, and it allows me to work on as many features as I want, without fear of messing things up on master, or having merge conflicts (I rebase early and often).

(Note: I usually work in the command line, because I'm more comfortable knowing what git is doing that way... but I often open up Tower (imo, the best application for visual Git) to inspect branches, commits, and merges/rebases... some people would probably rather just use Tower for everything).

(Note 2: When creating patches to send to someone that include binary files (like a png or a gif, jpeg, whatever), make sure you use $ git diff --full-index --binary [old]..[new] > patchfile.patch so git doesn't barf when you try applying the patch on someone else's end...).

Update: See comments below, and completely ignore this post. Nothing to see here...

module_load_include() is a great way to add code from other module's include files, but it doesn't always work as you'd expect. Recently, I was building a form in one module that pulled up a validation function from another module when a particular submit button was pressed:

I thought just adding in the module_load_include() would work, but alas, there was more to it than that. Instead of going about it this way, I had to call a local form validation function, and in that function, I could load the include from another module and call it's validation function:

This helps me uphold DRY principles, and reuse specific form validation functions from other module's include files. (Typically, though, if I were going to be validating a particular element, or a bunch of different forms, using the same validation function, I would include that validation in the .module file itself so I could call it anywhere without a module_load_include()... but in this case, I didn't want that particular validation function to have to be in memory on every Drupal page request :).

This morning, I was presented with quite the conundrum: one of my servers suddently started having about 4x the normal MySQL traffic it would have in a morning, and I had no indication as to why this was happening; traffic to the sites on the server was steady (no spikes), and I couldn't find any problems with any of the sites.

However, after inspecting the Apache (httpd) error logs for the Drupal 6 sites, I found a ton of PHP warnings on almost all the sites. Something like the following:

[Tue Nov 08 11:25:51 2011] [error] [client IP] PHP Warning: date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Chicago' for 'CST/-6.0/no DST' instead in /path/to/drupal6/sites/opensourcecatholic.com/settings.php on line 149

As it turns out, the fix for date.timezone problems with PHP 5.3.x and Drupal 6.x mentioned in http://drupal.org/node/325827 (namely, adding ini_set('date.timezone', date_default_timezone_get()); to the other ini_set() functions in settings.php) doesn't work that well for daylight savings time.

So, I've changed all those ini_set() functions in my Drupal 6 sites' settings.php files to explicitly set the default server timezone (in my case, ini_set('date.timezone','America/Chicago');), and now the error logs and watchdog errors written to the database are much more compact :)

I always leave watchdog database logging on for one or two of the sites on a server for precisely this reason: if something goes haywire, I can quickly notice something's awry in my server's munin stats. Then I hop over to the apache error logs and see exactly what's up.

I've had a nice go at making private messaging capabilities for flockNote work a lot nicer than the out-of-the-box Privatemsg module experience, by simplifying everything to the point that it's closer to the Facebook Direct Message system than the normal Privatemsg UX. (Privatemsg is the premiere way of handling private messaging in Drupal. It's already awesome out of the box... just needed a bit more help for our particular site ;-).

One thing I had wanted to do for a while is prefill the subject field of certain messages. I already have the new private message page appear inside an overlay popup after a user clicks on a link to send a private message to another user on the site.

I wanted users sending direct messages regarding certain comments or nodes to have a subject line of 'RE: [node title]' or 'RE: [comment title]' in them so they didn't have to write out a subject on their own. I was prepared to implement a hook_form_alter for the privatemsg form, send a query fragment containing the private message subject in the URL to the new private message page, and then check for it in my form alter to fill it in as the subject... but it turns out the Privatemsg module already has this capability built in!

All you need to do is throw in the subject as an extra argument in the url like so: messages/new/[uid]/[subject]. (You can still throw on query fragments to the end if you need to. In my case, I put a destination on the end so the overlay closes after a message is sent).

Email is such a pain (I should know, as I'm currently working on a site that's sending 10-20,000 emails per day to 40,000+ users. Spam prevention, SPF records, bounce handling, abuse reports, deliverability, send rates, etc. are all huge hassles that must be dealt with when handling more than a few hundred emails a day.

For testing, I often like throwing in a quick bit of code to send me or someone else a simple email with a few bits of information when something happens on the site, or to test email addresses or formatting. Therefore I like having a quick one-line function call to send an email. In Drupal 6, there was a handy drupal_mail_send() function that would use some default settings and allow you to quickly shoot off a simple email (not translated, not pluggable, etc., but easy to implement).

Drupal 7 did away with that function, and instead, the simplest way to send an email in Drupal 7 requires some 20+ lines of code. Not fun when I'm trying to set up a few quick one-off emails that just need a 'from', 'to', 'subject', and 'message'. For these emails, I don't care about message translation, mail altering, etc. I just want an email shot off as quickly and simply as possible.

So, I wrote a quick wrapper function that I've placed in a custom.module that lets me just throw in the four default parameters, and sends an email. It doesn't hook into any of the system's mail handling capabilities, and isn't super-robust, but it lets me develop much faster:

I haven't seen much about this feature yet, so I figured I'd put it through its paces and share what I found. WYSIWYG editing on iOS devices is finally here! For a long time, contentEditable support has been lacking on iPads, iPhones, and iPod Touches, and it's been slightly annoying, as the only way to add richly-formatted text on these devices was doing a two-step through finding the carat characters and writing the HTML yourself.

Plus, some WYSIWYG editors (like TinyMCE) simply disabled the WYSIWYG from attaching to a textarea if it detected an iOS device. No longer, however: I've tested CKEditor (latest nightly) and TinyMCE (latest nightly), and both work perfectly (surprisingly well, in fact!) on the iPad running iOS 5 beta 6:

The above screenshot was taken while editing a page on a Drupal site (flockNote) using the WYSIWYG module and the latest nightly build of TinyMCE. You can get nightly builds under TinyMCE's 'Develop' section.

Demonstration:

Here's a video of me using TinyMCE on my iPad (it's fast, and works great!):

Some notes on WYSIWYG usage in iOS 5:

To solve the problem of scrolling in WYSIWYG-enabled textareas, it looks like Apple decided to just expand the area to fit all the contents. So no scrolling whatsoever inside the body field.

TinyMCE's resize widget doesn't work - it would be klunky if it did anyways, and the note above resolves any issues that would cause anyways.

All the buttons I tested (image, link, bold/italic/underline, alignment, font color, style, table, etc.) worked perfectly, just as they would on a desktop computer.

The only major annoyance is that the full onscreen keyboard pushes everything up, and a lot of scrolling up and down in the narrow viewport is required to format text. (However, if editing with an external keyboard, the onscreen keyboard doesn't hinder anything).

The popover bubble that appears when you select text in the top couple of lines hides the WYSIWYG toolbar, so you might have to add a few carriage returns at the top of your post before making selections to the top few lines of text.

Other Wishes:

Now that iOS 5 seems to support rich text editing in the browser (a HUGE boon for online publishing in Drupal, Wordpress, Joomla, etc.), the only major flaw remaining is the inability to upload files (using the file select field). There's a workaround for this (at least, for Drupal: Post Photos/Images to Your Drupal Site from the iPad), but it's too cumbersome. I really want to just be able to select a photo from my camera roll and attach it to a post from time to time.

I think the IE development and marketing team at Microsoft 'gets' the situation, and is being very creative about it's efforts in promoting IE9 (case in point: IE6 Countdown). As to how far IE9 will ultimately go towards stemming web developers' collective hatred toward Explorer as a platform... that remains to be seen.

The ad above reads:

Dear Web Developer,

We are so very sorry about IE6.

Come have a drink on us at the Opening Night Party. Also, stop by our booth #67 and we will show you why IE9 is way better.

In my own testing of IE9, I've found it to be about on par with FireFox in how much I'd recommend it to users over any other browsers... that is to say, Chrome/Safari is still better, but I no longer need to tell people they should switch—IE9 is good enough for regular Internet users.

The only thing I really, really hope Microsoft starts doing is taking a more Chrome-like approach to adding in little bits of HTML5 and CSS3 goodness (and fixing some bugs) with point releases, rather than waiting 3-5 years for another IE release! (Of course, IE9 isn't released yet...).

One question I'm often asked by many other diocesan web development teams/individuals is how we put together our online Mass Time search (also used for searching adoration and reconciliation times). We also get questions about how we do our online mapping—but I've already covered that (see: Beautiful, Easy Maps in Drupal using Views and Mapstraction).

We already have a database provided by the Archdiocesan IT department (they maintain it with the help of our diocesan Parish Support staff, and parish secretaries who can update their own schedules and information), so we needed to do the following on the web:

Import all the Sacrament time information and attach it to a parish node (so times/days could be affiliated with parishes).

Display the time information on parish node pages, in a meaningful way.

Allow users to search by Sacrament times, showing parishes on a map, and showing the Sacrament times in a list under the map.

I'll cover each of these important aspects of our website's functionality below.

Preliminary note: much of this code was provided originally by the great folks at Palantir, who helped us set up this and many other features on the Archdiocesan website...

Importing time information, attaching it to Parish nodes

The first step in the process is importing some 3,000+ parish event nodes (which contain data for each 'event' - the event time, the event type (Mass/Reconciliation/Adoration), whether the event is a 'Normal Service' or a special kind of Mass, the location of the event (often in a side chapel or somewhere else), the event day, and the reference for the parish to which the event is attached.

Our site uses the Migrate module to import all the data, and we have the module set up to import all the events first, then import the Parishes, attaching the events to parishes (through custom code) using a node reference.

The CSV file containing the parish event data contains over 3,000 lines of information like the following:

29,"362",1,37,48,"07:30","",0,"","English"

Our migrate import takes that line, creates a new node with the information, then later, while importing parish nodes, attaches all event nodes affiliated with that parish to the parish node itself. Then, as they say, the magic happens (via a nodereference field).

Here's the code we use to prepare our parish event node via the migrate import process:

These two functions just tell Drupal that we're defining a custom display formatter for parish event times (that can be used in Views, on node teasers, and in full node displays), and then defines a theme function in which we'll tell drupal how to format everything for display.

This next function is a doozy - it basically does all the display dirtywork, and causes a performance burden on the site—if we tried displaying the mass time information for all 200 parish nodes on the site at once, the queries/processing would probably take 20-30 seconds! Therefore, we cache everything aggressively so people don't have to wait for the following theme function to do its work—after it's been done once in a day, it doesn't have to go again, as we cache the resulting page for 18 hours.

What we basically do here is load each referenced node, then grab all the metadata for that parish event from the parish event node. Then, we display all the metadata in a nice definition list, which gets themed to look like the following:

Allow Users to Search by Time/Day using Views

The final step in the process was to allow users to search on the website by Mass Time (or other Sacrament times), and since we were using Views for all our other search/filtering needs, we decided to use Views to do the time search as well.

Inside our dir_migrate.module (though this could live just as easily in our custom.module), we added a views handler, "dir_migrate_views_handler_filter_inttime."

Some Things Could Be Improved...

Well, actually, a lot of things could be improved. For instance, we could avoid a lot of this custom code if there were a way to create Date fields without a month or year attached—basically, a timestamp without a fully-compliant 'date' attached to it—but this is currently not possible.

Right now, I'm focusing on a few other projects, but someday I really want to tackle issue #499 on the Archdiocesan Development website: Create timefield module for Time CCK/Field. I envision a module that allows you to add time information to a node like "Saturday, from 4 p.m. to 5 p.m.," and then be able to filter Views results by time values alone... but I don't know if/when I'll get the time to do this :(

I've been asked about the Archdiocese of St. Louis's online parish search mapping functionality enough times that I finally made a quick video walkthrough of how it was done. The video below explains it all—basically, we use the Location module to attach addresses to nodes and geocode (get lat/lon) the addresses, and we use Views + Mapstraction to make the spiffy maps all over the site.

The functionality was originally set up by the kind folks at Palantir, and tweaked a bit over time by me to make what you see today.

You can watch the video in HD on Vimeo, to see fine details. (Recorded with iShowU HD).

Today, January 5, Drupal version 7.0 was released (download Drupal here). Drupal 7 release parties will be held worldwide on January 7 (which also happens to be my birthday - yay!).

I'll be posting my experiences in upgrading to and extending Drupal 7 both here and on my blog at Midwestern Mac, LLC (see D7 stories).

Congratulations to the team of almost 1,000 developers who helped make Drupal 7 a reality, and congratulations to Dries Buytaert, the founder of Drupal, and webchick, the person who shepherded (and continues herding) the community as the Drupal 7 core maintainer!

This website is still running on Drupal 6 (on a multi-site installation with about 5 other sites), but I'm slowly beginning the process of redesigning and upgrading the rest of my sites (notably, so far, Midwestern Mac, LLC) to Drupal 7. The Archdiocesan website and St. Louis Review will take a bit longer, since there's a lot of custom code that needs to be refactored.

If you run a website, have you checked out Drupal before? It's a lot more extensible (in my experience) than Joomla or Wordpress, the two other top contenders. If it's good enough for large sites like the White House and Examiner.com, it's good enough for you ;-)

MM is my first HTML5 theme, and my first for Drupal 7 (which, by the way, is awesome!). I have been working on refreshing my LLC website, Midwestern Mac, for the past few months since I scrapped my first hacked-together theme from about 2.5 years ago, and I finally decided to take the plunge and go Drupal 7 for the redesign.

MM is based on Boron, an HTML5 base theme that is still in beta for Drupal 7 (thus, I can't have a final release of my subtheme until Boron is final as well).

The theme has a few nice features:

No images whatsoever (cuts down on page load times, since there are less resources to load).

HTML5 markup (tested in IE7-9, FF 3+, Safari 4+, Chrome)

Progressive enhancement - we're using box-shadow, border radius, and some other CSS3 elements that only work in newer browsers at this point.

I figured I'd like to help get more themes on the docket for Drupal 7's release—right now there are very few, and I think it would be nice if people downloading D7 and wanting to tinker could have more than two or three themes to play with.

Plus, it's just a nice thing to do for an open source project that has given me a career.

In my always-continuing quest to find the perfect online calendar display/management solution, I have found the next level of calendar display/management bliss.

Previously, I was pinning all my hopes on Drupal's very robust, but often complex and confusing, Calendar.module (in use by almost 50,000 websites—and for good reason—it's extremely adaptable). The module provides many different displays, and gives you the ability to link directly to a specific day/month/week... but it (a) is relatively slow to allow switching from month to month, (b) requires a rather complex view, with arguments, which can be confusing for first-time users, and (c) it takes patience to theme it well.

I love the Calendar module, and I still use it on a few sites where necessary, but I've found a new contender that has nothing to do but improve; that condender is the FullCalendar module, which is based on the great fullcalendar.js jQuery-based calendar library by Adam Shaw.

This is IE. It's easy enough, though, to add better styling to a fullcalendar.

FullCalendar is simply a views display that takes a list of event nodes (as long as your node has a date/time attached, it will work), and displays them in a beautiful calendar display that works across all modern browsers, and even most mobile browsers (I've tested Android, iOS 4, FF, Chrome, Safari, and IE so far).

One thing I have yet to test is the performance of fullcalendar when displaying large batches of calendar items (in this case, calendar.module might be better—if you need to show thousands of events on a calendar from many years prior). The biggest calendar I have right now displays about 200 items. As time goes on, I could either simply let the list build to the point where fullcalendar slows a bit, or limit the date range so events from only the past few months show.

Many of my favorite websites offer a nice little feature, immediately following the body of the page, that highlights 3-5 "possibly related" stories or blog posts. I wanted to do this on OSC and some other sites, but found that it's difficult to add regions inside of nodes—the closest I could get with the default theme/block behavior is to have it appear after comment section, which is too far down the page to be relevant.

I decided to use the Featured Content module to create my blocks, as it offers a good amount of customization as to what kind of algorithms it uses to find related nodes... performance considerations aside. There are other ways to go about creating lists of related nodes, but this was quick and easy.

Adapting a solution I found here, I created a simple function inside my template.php file that allowed me to print a block from inside my node.tpl.php template.

After having created a fewdifferentpodcasts on different Drupal sites for different purposes, using a variety of methods, I can speak with a little authority on which methods are the best, easiest, etc. There is an Audio module, and an iTunes module, which help with more advanced podcasting needs... but most people just want a podcast which will allow visitors to either listen while on the website, or to be able to subscribe to the podcast in iTunes or another media player.

If your needs are relatively simple, it's quite easy to get a podcast up and running on your Drupal website:

Step 1 - Make a Podcast-ready Content Type

In one of your content types, add a filefield that allows the uploading of MP3 and/or M4A files, and create a podcast episode or two. Make sure you set the filefield's display to 'Generic Files' for the RSS display settings (at admin/content/node-type/[your-node-type]/display/rss).

(You can also use something like SWF Tools to display a player for the file for regular ("Basic") node views—so people can play the audio file without having to open your feed in iTunes. Otherwise files will just display as links to the downloadable file).

Step 2 - Make a View with a Page and Feed Display

Now, create a view, and in that view, create a list of all your podcast nodes (nodes that have the MP3/M4A files attached) on a Page display, then create a Feed display that shows a few episodes, and attach that Feed display to the Page display.

Step 3 - Avoid a Hassle by Burning Your Feed

Many would recommend trying to get the feed working properly with iTunes by using the aforementioned iTunes module or some other hackery, but there's a much easier option: FeedBurner. You need to set up an account with FeedBurner. Then use FeedBurner to 'burn' one of your feeds—be sure to check the 'I am a podcaster!' checkbox. Fill out all the relevant details, and then look at what your FeedBurner URL is (mine, for example, is http://feeds.feedburner.com/reviewcast-podcast - this is for the ReviewCast).

Install the FeedBurner module on your Drupal site, and then go to its settings page. Click the 'Burn feed' tab to add your new feed - you'll need to know the path to the Feed display that you configured in your View earlier, and the FeedBurner URL (just use the part that's bolded above).

Step 4 - Profit?

Now, clear all your caches (in case the feed you had in your views was cached already), and you should have a podcast page which not only allows site visitors to play files directly, but also offers iTunes (or other service) subscriptions. You can submit your FeedBurner URL to iTunes' Podcast directory if you'd like to be included.

At a recent St. Louis area Drupal meetup (details here), I presented a quick session on how to build a drupal module, geared towards beginning Drupal developers (I don't consider myself too advanced, but I have found that my experiences can often help others).

I have attached to this post the custom module (a .zip) file that I included for examples in the presentation, and I also uploaded the slideshow (quick and easy - just 12 slides!) to slideshare. I've embedded the slideshow below: