Copyright © 2004–2010 OpenSourcery, LLC. This work is licensed under a Creative Commons Attribution 3.0 United States License.
I recently had the pleasure of attending my first Bay Area Drupal Camp, and enjoying some oddly-sunny late October days in Berkeley, CA. Rather than touch lightly on all my favorite BADCamp moments, I'd like to concentrate on two of the topics that inspired me: the Advanced Theming session and Beans.
Tim shared how to use a grid system and the Block Reference module to essentially implement a much simpler version of Panels. The Block Reference module provides a field that can be used to reference blocks in a node, and thus embed the block's content in the node display. Tim showed a content type with three block reference fields that are assigned grid classes; this allowed him to quickly construct a node type that displays present three columns of listings beneath the node's body content. In order to keep theming work consistent, Tim suggested using Views's Content row display format rather than the Fields format. The Content display format lets you choose which view mode. The view modes that come with Drupal don't provide enough different ways for you to format content (Default and Teaser), but you can create new view modes using code or using the Display Suite module. So you might end up with view modes like "Title only," "Title and teaser," "Thumbnail and title," "Thumbnail only," etc. For sites with similar enough content types, defining these view modes gives site editors a lot of flexibility; especially when you allow them to select which view mode to use when creating a new listing block. So how can we empower site editors to make use of these view modes without throwing them into the deep end of the Views ocean? Beans are the answer!
Beans are a new way of creating blocks. Beans are entities, so, like with nodes and content types, you can create different block types and add fields to those block types. Bean types can also use custom plugins; bean plugins use custom code to create a configuration form for the block type and generate the block's output. A great example use is for creating configurable listing blocks that site editors can readily add to pages. Rather than building out exactly the blocks you planned on and wireframed, you use Beans to build a blocksystem that the client can use with some flexibility; for example, let's say that two pages on the site need a "Featured Content" views block. One displays the latest 5 Articles, the other displays the latest 3 Products. But, weeks after the site goes live, the site editor wants to add a "Featured Content" block in the same format, but wants it to display the latest 2 Widgets instead. If you built the Featured Content function with normal Views blocks, the site editor would need to go into the Views UI and create a new Views block display on the Featured Content view. For a non-professional Drupal user, this is dangerous and tricky. However, if you built a custom "Featured Content" block type that is configurable (it lists the latest [X] entries of content type [Y] using view mode [Z]), then the site editor is in luck! They can simply create a new "Featured Content" block and configure the new block to do what they want. That's easierand safer.
So those were my two main sources of inspiration from my first BADCamp. I'm already incorporating Beans (with a couple of custom bean types) into a new Drupal 7 site we're building, and am looking forward to using Block Reference the next time a project calls for a lightweight block layout method. These are very powerful tools that can give clients lots of flexibility without adding lots of complexity. This is the perfect example of what I love about the Drupal community -- each gathering is like connecting to a hive mind with new ideas that not only end up improving the sites we build, but that keep working with Drupal fresh and exciting.
Tagged as: BADCamp, Beans, Drupal, Drupal Planet
When researchers at the Spatial History Project at Stanford University needed a team of smart, creative Drupal developers to build a new kind of website – a digital companion to a scholarly print publication – they chose OpenSourcery.
Thank you! We are super excited over here. You all have truly done an amazing job and even more importantly have been wonderful to work with. … I appreciate [OpenSourcery] welcoming the students into the process. It provided such a fun and unique experience for them and they certainly wouldn't have had the opportunity elsewhere.
- Kathy Harris, Director of the Spatial History Lab
Custom theme and graphic design by OpenSourcery, built in Drupal 7
A responsive layout system, with mobile-friendly navigation, makes it easy for readers to follow footnotes referenced in the book or browse through galleries of supplemental material on a smart phone, tablet, or netbook
Footnotes and supplemental materials can be added to the site and edited using a WYSIWYG editor and media upload system
A data migration system supports bulk importing of footnotes, tags and categories from a CSV file
A custom theme displays footnote search results in a card-catalog-like format
Images, illustrations, appendices and visualization materials are dynamically themed to resemble traditional photo slides and showcased by category on gallery pages
A footnote browser makes it easy for readers to follow cited sources chapter-by-chapter or explore the material by source type, overarching themes, source library/archive/collection, persons of interest, and helpful tags
A custom lightbox display encourages readers to delve into the detailed footnotes or explore gallery materials up-close, in an page-overlay display viewer, without leaving the current page
Materials can be shared instantly to Facebook, Twitter, or email; A smart permalink feature automatically constructs links which point directly to the lightbox display of the thing you wanted to share
Other scholars can use the underlying framework to deploy their own footnotes browser sites, for free, using Drupal Installation Profiles - please contact us if you would like to make use of this powerful system
The Spatial History Project (SHP) at Stanford University uses technology to examine and refine our understanding of history; Taking what we already know about the past, charting these clues in the context of place and time, and displaying the results visually in order uncover hidden historical trends and patterns. As the Railroaded website explains, “One of the ways this project operates outside of normal historical practice is by using visualization as a way not simply to illustrate conclusions, but a means of doing research.”
Stanford History Professor Richard White and the SHP team used visual analytical models to study the rise of transcontinental railroads, publishing the results in the book Railroaded. Railroaded includes over 2,000 footnotes- many of which could not be published in full due to space limitations - and an impressive collection of interactive visualization systems. To give history scholars and curious readers an all access pass to their research materials the Spatial History Project team needed to come up with a clever means of binding together print media and digital media. The SHP team turned to the Jasper Group for help.
In the case of Railroaded, we had the opportunity to craft what could be a new genre of website --a digital companion to a print monograph. Since the book's publisher gave Professor White a hard limit on the number and extensiveness of his footnotes we sought to give him the academic freedom he required to express his ideas more fully by co-publishing in a digital medium.
- Zachary Chandler, The Jasper Group
Academic Technology Specialists from The Jasper Group outlined the technical requirements for a Drupal-based web application which could serve as digital footnote companion and research portal for Railroaded. When it came time to choose a Drupal development firm to build the site The Jasper Group recommended OpenSourcery, “There's a number of things that really set OpenSourcery apart... The first and most important factor was that [they] clearly understood the project and were excited about it... [OpenSourcery] got what we were after, had very smart questions, and were ready to hit the ground running. ”
The footnotes browser, media galleries, and search pages for Railroaded are easy for readers to navigate on a mobile device with one hand, while holding the printed book in the other hand. OpenSourcery's Adam DiCarlo pulled out all the stops to deliver a mobile-friendly responsive layout, which rearranges how on-screen elements are positioned based on the width of the screen; With distinct layouts based on the widths of common mobile phones, tablets, and standard computer monitors.
What I think was important about Railroaded was not just that we solved one problem for one professor but the Spatial History Lab and OpenSourcery created something that can be built upon and reproduced.
- Zachary Chandler, The Jasper Group
OpenSourcery's experience developing and releasing Drupal Installation Profiles – which act like an inflatable website-in-a-box for deploying pre-configured Drupal sites which anyone is free to use – proved to be an important part of achieving the broad vision for Railroaded.
The Spatial History Project, The Jasper Group, and OpenSourcery are proud to make the infrastructure for the Railroaded companion site available for others in the open source and scholarly communities to use, for free. By doing so we hope that other authors – of monographs, dissertations, theses, and of purely digital publications – can implement this unique infrastructure of modules to present their own scholarship.
We're calling that project Discursive.
Tagged as: academic publishing, Discursive, Drupal, footnotes browser, history website, lightbox display, mobile friendly, responsive layout, Spatial History Project, Stanford University
I am happy to announce OpenSourcery's 2011 Drupal Training Tour. This year we'll be visiting eight cities in six states and offering up twenty expert Drupal training sessions.
In each workshop you'll learn the Drupal Way, working directly with Drupal alongside OpenSourcery's own Drupal rock stars, and take home useful reference materials outlining each activity with step-by-step instructions.
I'm also truly honored to add that OpenSourcery has been approved as an Acquia training partner. Meeting the high standards Acquia sets requires a rock-solid understanding of Drupal and years of practical experience building custom web applications.
If your city isn't on the tour this year and you'd like OpenSourcery to visit please let us know. We offer customized and private Drupal training as well.
In 2011 OpenSourcery's Drupal rock stars will tour the following cities in the Western United States to offer hands-on Drupal training workshops:
Portland, Oregon –
Site Building with Drupal 7 - June 21st & 22nd
Site Building with Drupal 7 – October 10th & 11th
Drupal 7 Module Development – October 12th & 13th
Drupal 7 in a Day – October 14th
Corvallis, Oregon -
Site Building with Drupal 7 – July 12th & 13th
Tucson, Arizona -
Seattle, Washington -
Drupal 7 in a Day – August 15th
Site Building with Drupal 7 – August 16th & 17th
Drupal 7 in a Day – October 24th
Site Building with Drupal 7 – October 25th & 26th
Boise, Idaho -
Drupal 7 in a Day – September 26th
Site Building with Drupal 7 - September 27th & 28th
Spokane, Washington -
Drupal 7 in a Day – November 7th
Site Building with Drupal 7 – November 8th & 9th
Salt Lake City, Utah -
Drupal 7 in a Day – November 21st
Site Building with Drupal 7 – November 22nd & 23rd
Las Vegas, Nevada -
Drupal 7 in a Day – December 5th
Site Building with Drupal 7 – December 6th & 7th
OpenSourcery is the largest and most established Drupal development shop in the Pacific Northwest. Based in Portland, Oregon, and founded in 2004, OpenSourcery has developed over a hundred Drupal websites. OpenSourcery provides expert Drupal development and training to non-profits, government agencies, academic institutions and other organizations furthering the common good.
Tagged as: acquia approved training, Arizona, Boise, Corvallis, Drupal, drupal 7, drupal in a day, drupal training, Idaho, Las Vegas, Nevada, Oregon, portland, Salt Lake City, Seattle, Spokane, Tuscon, Utah, Washington
I'm excited to be speaking at LinuxFest Northwest this year about how to get a job in the Free Open Source Software (FOSS) community as well as how to start your own FOSS company.
LinuxFest Northwest looks to be amazing this year with 99 different speakers over the weekend. Hope to see you there!
Tagged as: Drupal, FOSS, jobs, linuxfest northwest, startups

Today OpenSourcery announces the alpha release of our second Drupal distribution for nonprofits: Volunteer Rally, a web application that helps organization manage their volunteers.
Volunteer Rally allows you to publish a calendar of available volunteer shifts on the web. Your volunteers may browse through calendar dates, choose shifts that they're interested in, and sign-up for them. Once they've signed up they'll recieve an email reminder one day before the shift.
Site administrators are able to create shifts and specify a capacity for each shift. If you have an established, predictable schedule for your volunteer shifts, you'll be able to create re-occurring shifts that will save the the hassle of creating them one at a time.
Once a shift is complete you'll be able to take a rollcall and then adjust the actual number of volunteer attendees. Over time, Volunteer Rally will help give you a good idea of how your volunteer operations are performing and prepares you to share this information with your supporters.
It's released under an open source license and we welcome other Drupal developers to use it in their professional (and technical volunteer) work. (Developers, visit the project page on Drupal.org and follow us on GitHub.)
End users that are comfortable installing Drupal may download a tarball of this distribution on OpenSourcery's code page.

After you've installed Volunteer Rally, you'll want to begin by setting your date and time settings for the site. To do this, visit Site Configuration -> Date and time and then set the default time zone.

Next, you should create some shifts that your volunteers may sign-up for. First, login as the site administrator and click the "add shift" menu item.

To create the shift, fill out the Date, Start time, End time, Sign-up status, Total capacity, and (optionally) a Memo that will only be accessible to shift co-ordinators.

If this is a shift that re-occurs at a steady pace for your organization (say, every Friday, or every other day), Volunteer Rally will automate the creation of multiple shifts. To do this, navigate to the detail page for a shift by clicking on the header for the shift on the calendar then clicking the shift title in the pop-up.
On that detail page, you'll see a tab titled, "repeat." Click that tab and you'll be taken to the new sequence page. Fill out these forms to match your required calendar shift information.

Once that's done, users will be able to sign-up for shift by clicking on the calendar and then selcting "sign-up" from from the pop-up menu.

Site administrators may review all confirmed sign-ups by visiting the shifts detail page, as described above, and selecting the sign-ups tab.
There's more to explore, but that will get you started! From all of us at OpenSourcery, we hope this tool helps you connect to others that want to help you fulfill your mission.
Enjoy it.
Tagged as: code rally, Drupal, volunteer rally
I had a great time in Chicago, at my first-ever DrupalCon! Several sessions I attended confirmed to me that we’re using many cutting-edge development practices for Drupal development at OpenSourcery already; it’s nice to hear some of the brightest minds in the business tell you things you already know. Fortunately, I wasn’t able to get too full of myself, because every time I thought, “Yeah, that’s cool, but I already knew that,” there would be a few extra details mentioned that I hadn’t thought of on my own—the icing on the Drupal Best Practices cake. Three examples I’d like to share came from the Advanced Features session, a Design Secrets BOF, and the Advanced Drush session.
Tagged as: Drupal, Drupalcon, Drupalcon Chicago
Drupalcon Chicago introduced the core developer track (Core Conversations) as a parallel track to the normal, broader tracks. Because of this, and a series of compelling BOFs, I spent comparatively little time in the main session halls during the conference. Below I cover some of the topics and discussions that got me excited about Drupal 8 and the direction of our community.
There was a core conversation about Butler, but unfortunately, there is no video (oddly, no video from Copenhagen either), or slides from what I can find. The initiative was also mentioned by Dries during his keynote presentation as one of the goals for Drupal 8. The overarching idea is for core to provide a unified context system, coupled with a better plugin system. This will allow, among other things, better rendering of non-HTML pages, faster rendering for HTML (eg, small portions of a page can be rendered), and allow for better web-services support. The project can be followed on Drupal Groups, and there is code available for Drupal 7 in contrib.
The idea behind Snowman is to build something with Drupal core that does something. Whether the goal is a gateway drug, an on-ramp to contrib, or a canary for determining what can be axed from Drupal core, depends on who (and when) you talk to. Nonetheless, I think the idea is a good one. During the core conversation, it was mentioned that this could be dangerous, because something can always be built better using contrib. So if Drupal is packaged as the definitive Foodie Club site, for example, it could potentially do damage to Drupal's image since it wouldn't be as polished as a site that took advantage of contrib. The proposed solution to this concern would be to direct the new user, via content in the installation profile, towards groups or categories of modules that could quickly be used to further enhance the site.
My favorite session was a discussion between Moshe, Eaton and Irakli, moderated by Eric Gundersen. While the video isn't too exciting (no slides, but the audio is good), the discussion is fantastic. Moshe explained that his vision for Drupal core would be to follow something similar to the Ubuntu project, where core itself might be hidden away for developers ('drop' perhaps), and the Drupal.org homepage would direct users to any number of flavors (distributions with a purpose). These distributions would be free to move at an independent pace from core, always targeting the latest stable release. Related to this, Eaton explains his then-named Tsunami initiative (since renamed Snowman, and explained above) as a sort of canary that could be used to define what constitutes the core of Drupal.
With over 30 Portlanders in Chicago for the conference, this represented more than 1% of the total conference attendees. Additionally, during the git phase next presentation, 5 out of the 11 people thanked on-stage hail from Portland and the surrounding area. The Portland Drupal community is indeed flourishing!
Eaton comparing Drupal to platypodes and broader ecosystems was one of the best sessions I made it to, and is well worth watching if you missed it.
Tagged as: Drupal, Drupalcon, Drupalcon Chicago
Open source software grows up so fast these days. This entry marks this release of Donor Rally Alpha 1, which offers a host of improvements, a winsome new theme, and a few feature enhancements that will help nonprofit organizations use the devotion of their supporters to expand the reach of their fundraising operations.
Let's take a moment to explore how Donor Rally works. After installing Drupal and selecting the Donor Rally install profile, you'll be asked to choose a payment vendor (this version supports PayPal and Salsa) and set a total fundraising goal. If you're not sure about this yet, don't stress - you can always change it later. After installation you'll be taken to a welcome screen designed to help first time users.

After reading these instructions, you'll want to replace that text with some copy that will welcome your first visitors to the site. To change that text, click the small edit link in the lower right corner of the box.

Your fundraising campaign will consist of two major communication phases. The first phase will be targeted towards friends and fans of your organization who may want to help with your fundraiser. Once you've explained the goals of the fundraiser on the front page of your site, use email, Facebook, Twitter, and whatever other communication tools you have to energize this group of potential fundraising partners. You'll want to ask them to click the Manage Team link, which should direct users to http://yourdomain.com/user/login and then select "Create New Account." Donor Rally uses Profile to manage teams, so each new account will be a team. Teams can represent many participants (often a department at a company or a group of friends) or may consist of just a single person.

After the team is created, the team's donation page is published to a dedicated URL. You'll see a team thermometer on the right sidebar, and a donate now button right below it.

When users click the domate now button they'll be taken to the payment vendor that you chose during the installation process. After the payment is complete, your team's thermometer is automatically raised to reflect the new donation total.

On the front page of the website you'll find a dynamic leaderboard that lists all teams and the total amount of money that they've raised. You'll also see a "Per-capita" ranking that gives smaller teams who pull their weight appropriate consideration.

Now let's look at some things you can do to help get the word out about your campaign. First you'll want to encourage your fundraising teams to use their team page to write a blog post about the campaign. This is what all of their friends will see when visiting the site, so it's important that it communicate your mission in a personal way. To create a blog post, logged-in users can click the "Write a new blog post" link next to their team logo.

The site's administrator has the ability to publish a blog post across all team pages. This is a good way to notify all teams of looming fundraising deadlines or to congratulate them on hitting certain goals along the way. These posts are also displayed to the public, so be sure to stay on message. To write an admin blog post, click the wrench icon in the upper left corner, then Create Content, then Admin Blog Post.

Finally, be sure to use the built-in social networking features. Have your team leaders click the icons on their pages that that will help them spread the word on Facebook, Twitter, and will even use Drupal's mail system to send email to their personal lists.

Though stable and usable right out of the box, this release is targeted towards other Drupal developers who want to help nonprofit causes close to their heart. Our business strategy for Donor Rally begins and ends with: get it out there. So check out the code, follow us on Github, and certainly drop us a note if you are able to use this to stage any nonprofit social fundraising love-fests. That's our model. We do this because we love it.
Tagged as: donor rally, Drupal
I've recently returned from an amazing time at Drupalcon Copenhagen, and wanted to highlight some of my favorite sessions, events, and departing thoughts (this also serves as preparation for the impossible task of summarizing such an epic and comprehensive conference in 15 minutes for this week's Portland Drupal group). While I can't cover them all, the complete list of videos from Drupalcon Copenhagen can be found here.
Jeremy Keith, not only touched on the core functionality and concepts of HTML 5, but also spent a great deal of time focusing on the history and reasoning behind the design.
This session sets a new bar for presentations, not just at Drupalcons, but for conference presentations in general. Amitai Burstein managed to map the complexities of international relations to the new flexibility of groups in Drupal 7, in a witty and hilarious manner.
UPDATE: Amitaibu has an alternate version of the presentation video that shows his introduction a bit better.
If you haven't been following the development of this Drupal mapping solution, this session is a good place to catch up. The presentation did an excellent job of detailing the creation of complex maps, that are based on views and are fully exportable.
Find out how using Drush make to build sites encourages developers to contribute back patches, rather than running monolithic and duplicative code repositories. Unfortunately, as of this writing, the video is not available on archive.org. Once it is, it is well worth a watch. In the meantime, Jeff Miccolis has this related blog post.
Angie Byron's session provides a nice, friendly overview of some of the major, user-facing changes that Drupal 7 will bring. For a more behind-the-scenes view, Damien Tournoud highlights some of the lesser-known features (video) such as job queues and the fine-grained caching options available. Larry Garfield covers some goals for Drupal 8 (but first, of course, let's get Drupal 7 done).
Speaking of which, the 2 code sprints (the first after the Core Developer Summit, the second after the conference), saw the critical issue queue drop to 13 at one point, but then, with the additional attention of developers, it bounced back up to around 25, and is currently hovering at 29. There's even a site to see what these numbers might mean for a release date for Drupal 7.
Thanks to Morten DK and Mikkeller, this Drupalcon had its very own beer, known as Awesomesauce. It was quite delicious, and free most every night at the Foobar.
Today OpenSourcery announces the release of Donor Rally, an open source Drupal distribution that nonprofit organizations can use to raise money on the web. This is a developer release, and Drupal geeks can begin the tire-kicking process by downloading the project's source code on GitHub now.
This project has allowed OpenSourcery another chance to follow through on one of our central goals as a company: to share open source software developed for one nonprofit organization with the rest of the nonprofit community. Today, on the day of Donor Rally's birth as a public open source project, I'd like to take a moment a moment to relate the story about how it came to be.
In early 2009 we were contacted by the San Francisco Food Bank to discuss the possibility of attempting something truly radical: using Drupal to move a mission-critical fundraising campaign completely to the web.
The Food From the Bar campaign website was launched in February of 2010. It allowed the San Francisco Food Bank to utilize their social networks, both physical and virtual, to spread the word about their mission. And by June of this year, it had collected over $300,000.00 in web-based donations.
OpenSourcery licenses all of our client projects under the terms of the GPL, and it wasn't long before we started contemplating how this software could be used to benefit other organizations. Then a personal connection at one of our favorite organizations, 826 Seattle, gave us our first chance to spread the Donor Rally love. (Huge thanks to Sarah B., who was instrumental in this leg of the project.) 826 Seattle is a division of a parent organization co-founded by Dave Eggers to give underprivileged youths access to creative writing programs of the sort that had been previously reserved for only the most privileged private academies.
826 Seattle was planning an ambitious, grassroots fundraising campaign called Dance Your Cash Off that invited participants to raise money for the organization on the condition that they would enter a dance marathon hosted by 826. This proved to be a perfect opportunity to re-tool the codebase originally developed for the San Francisco Food Bank to help 826 Seattle bring their efforts to the social web. Because we developed the original codebase using Features, abstracting out functionality unique to the food bank (such as food donation) was a nearly trivial task. After less than 20 hours of labor, we launched DanceYourCashOff.org.
Staff members and fans of 826 Seattle were then able to use the website to raise $17,000, more than 70% of their original fundraising goal. And thanks to Drupal's administration capabilities, they spent only a few hours of staff time to co-ordinate the entire campaign.

Since then, employees of OpenSourcery have spent every Thursday afternoon sitting around a table out in the sun over a company-subsidized pitcher (or 2) of beer, working together to improve the Donor Rally codebase. Which brings us to today's developer release. Donor Rally has now been packaged into a free, general-purpose application to help any nonprofit organize a social fundraising campaign of their own. The theme is a subtheme of Zen, and hasn't yet been given a polish coat. But this should be a good starting place for a developer to use to help out his or her favorite nonprofit. To learn more, visit the Donor Rally project page on OpenSourcery.
Tagged as: Drupal, Drupal distribution, nonprofit
I have just returned from DrupalCon San Francisco 2010, the largest DrupalCon ever. With over 3000 attending, and $72,000 worth of coffee consumed, it was a very lively event. Thanks to the awesome work of those organizing, nearly all of the sessions now have high quality video available on the DrupalCon site, and on Archive.org. Below are the sessions that really left an impression on me regarding the future direction of Drupal.
While there is no video for this as of this writing, the highlight here was the sudo drush make-me-a-sandwich moment (as well as the Drush core-cli command).

While we've been using context on most projects for quite some time, the work presented here around the spaces presets has me itching to try integrating them into some upcoming projects.
The page rendering system in Drupal 7 waits much later in the process to transform structured data into the relevant output format (which is typically HTML). Practically speaking, what this allows for is hook_page_alter, which has access to the contents of the entire page, in a structured array. Two highlights:
This talk wasn't specific to Drupal (yet anyway), but rather, provides a sort of roadmap to the future of Drupal and the social web. By combining 4 rather new protocols (PubSubHubbub, WebFinger, ActivityStreams and Salmon), Brett Slatkin of Google walks through the potential for realtime feeds being used to contect people like never before.
It would be very powerful if any Drupal site out there were capable of sharing, in real time, at the level Brett outlines in this talk. The Feeds module is already capable of consuming PubSubHubbub, and support for ActivityStreams have a little momentum. Salmon and WebFinger, as well as publishing to hubs for PubSubHubbub are the pieces that need to be filled in.
At Dries' keynote, he showed a best case scenario (June 2010), a worst case scenario (October 2010), and an ideal scenario (lock the 3000 attendees in until it was released at the conference) for the Drupal 7 release.
While we already missed the ideal scenario, the progress made on critical bugs at the conference has the community working at a velocity that should come in closer to the best case scenario. Over the course of the week, thanks to the awesome gatherings at the chx coder lounge, the number of critical bugs dropped from 114 to 94 as of this writing.
Tagged as: Drupal, Drupalcon, DrupalCon San Francisco
We've just published a write-up of our work for Mercy Corps, where we enabled hundreds of youth organizers worldwide to join together in a global community, including multilingual support in Drupal. Read all about it here:
http://www.opensourcery.com/portfolio/projects/mercy-corps-globalcitizen...
Tagged as: Drupal, global community forums, Mercy corps, multi-lingual, multilingual, right-to-left, RTL
The context module provides great flexibility in terms of the available ways to set a context, but it's also remarkably straightforward to define custom conditions.
In order to set arbitrary contexts, hook_context_conditions() is implemented to define values and such. This example will use the value of a CCK field, called field_foo:
/** * Implementation of hook_context_conditions(). */ function mymodule_context_conditions() { $items = array(); // The key used here will be used below when setting the context. $items['mymodule_foo'] = array( '#title' => t('Field Foo Value'), '#description' => t('Set this when field_foo has a certain value.'), '#options' => array( // Note, these are hardcoded here for simplicity, but could // easily use something like CCK's content_allowed_values() api // function for more dynamic population. 'value1' => t('Label 1'), 'value2' => t('Label 2'), ), '#type' => 'checkboxes', ); return $items; }
The only other step is to actually fire the code that sets the context somewhere. In the example of setting a context based on the value of a CCK field, this can be done in hook_nodeapi(). But something like hook_init() can also be used.
function mymodule_nodeapi(&$node, $op, $teaser, $page) { if (isset($node->field_foo[0]['value']) && $op == 'view' && $page && menu_get_object() === $node) { // Use the same key here as used to define the context condition // above. Note, this logic would need some re-working if // field_foo allowed multiple values. context_set_by_condition('mymodule_foo', check_plain($node->field_foo[0]['value'])); } }
That's it. Contexts can now be added through the UI or through code that react to the value of field_foo.
The workflow module allows a piece of content to be transitioned through arbitrary states. It is most commonly used (as I've seen it) as a replacement to the core node workflow of published/unpublished. Recently I was working on a pair of sites that required a very simple workflow of draft/published (if you're wondering why core couldn't be used in this case, it has to do with the very high level of permissions required to toggle the published/unpublished bit). The sites also made extensive use of node reference, views and context for positioning various parts of the node. Not having visual indicators within those views for the end user to determine which nodes were in a draft state, and which ones were published quickly became an obvious usability issue.
The first step in the improvements applied was to add the workflow state field to every view in question.

However, as packaged with workflow, it doesn't provide a very nice output, and only nodes in the Draft state needed a visual indicator.
Using the following preprocess function, the fields for undesired workflow states are removed, and a key CSS class is added (in this case, Published content didn't need to be highlighted in such a manner).
/** * Preprocess function for template_preprocess_views_view_fields(). * * - Adds workflow class for rows in the 'Draft' state, while * removing results in 'Published state'. */ function os_custom_preprocess_views_view_fields(&$vars) { foreach ($vars['fields'] as $name => &$field) { if ($name == 'sid' && $field->handler->table == 'workflow_node') { // Get complete workflow state. $state = workflow_get_state($field->raw); if ($state['state'] != t('Draft')) { // Hide workflow if not in draft mode. unset($vars['fields'][$name]); } else { // Add workflow-{state} class. $field->class .= ' workflow-' . strtolower($state['state']); // Replace default 'Worfklow name: workflow state' formatting with // only the workflow state. $field->content = $state['state']; } } } }
Then, by borrowing some CSS that has been hanging around in the Zen theme for the core workflow, the content in draft state is easily brought to the attention of those working on the site:
The same is then done for nodes by a different preprocess function,
/** * Preprocess function for template_preprocess_node(). */ function os_custom_preprocess_node(&$vars) { $state = workflow_get_state($vars['node']->_workflow); if ($state['state'] == t('Draft')) { $workflow_class = 'node-workflow-' . strtolower($state['state']); // Prepend content with workflow state information. $vars['content'] = '<div class="' . $workflow_class . '">' . $state['state'] . '</div>' . "\n\n" . $vars['content']; } }
and and using the aforementioned, and slightly-modified, Zen CSS:
.node-workflow-draft, .workflow-draft, .node-unpublished div.unpublished, /* The word "Unpublished" displayed beneath the content. */ .comment-unpublished div.unpublished { height: 0; overflow: visible; color: #f77; font-size: 75px; line-height: 1; font-family: Impact, "Arial Narrow", Helvetica, sans-serif; font-weight: bold; text-transform: uppercase; text-align: center; word-wrap: break-word; /* A very nice CSS3 property */ } .workflow-draft { font-size: 42px; /* Smaller font for workflow display within views. */ }
the result is again obvious to people staging content:

hook_cron() is widely implemented in the Drupal ecosystem – but what if your modules have varying frequency needs? For example, perhaps you'd like your aggregator feeds to update every fifteen minutes, and notifications should fire every minute to keep emails timely. But system_cron() should run as infrequently as practicable, because it calls cache_clear_all()!
Here is a small cron.php replacement that accomplishes this task. Just plunk the file in your drupal root directory. (You could move it to your sites folder if you modified the include path.) Different cron jobs for each module or set of modules can now be configured.
<?php // $Id$ /** * @file * Handles incoming requests to fire off regularly-scheduled tasks (cron jobs). * * The file executes cron hooks selectively, instead of all-or-nothing. * This allows cron jobs to be configured with variable frequency. * Example usage: * * * * * * curl example.com/cron_selective.php?modules=notifications * *∕15 * * * * curl example.com/cron_selective.php?modules=aggregator * 0 0 * * * curl example.com/cron_selective.php?modules=system,dblog * */ include_once './includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); $modules = array_intersect(module_list(), explode(',', $_GET['modules'])); drupal_cron_run_selective($modules); /** * Executes a cron run when called * @return * Returns TRUE if ran successfully */ function drupal_cron_run_selective($modules) { // If not in 'safe mode', increase the maximum execution time: if (!ini_get('safe_mode')) { set_time_limit(240); } // Fetch the cron semaphore $semaphore = variable_get('cron_semaphore', FALSE); if ($semaphore) { if (time() - $semaphore > 3600) { // Either cron has been running for more than an hour or the semaphore // was not reset due to a database error. watchdog('cron', 'Cron has been running for more than an hour and is most likely stuck.', array(), WATCHDOG_ERROR); // Release cron semaphore variable_del('cron_semaphore'); } else { // Cron is still running normally. watchdog('cron', 'Attempting to re-run cron while it is already running.', array(), WATCHDOG_WARNING); } } else { // Register shutdown callback register_shutdown_function('drupal_cron_cleanup'); // Lock cron semaphore variable_set('cron_semaphore', time()); // Iterate through the modules calling their cron handlers (if any): foreach ($modules as $module) { module_invoke($module, 'cron'); watchdog('cron', 'Selective cron run completed for %module.', array('%module' => $module), WATCHDOG_NOTICE); } // Release cron semaphore variable_del('cron_semaphore'); } }
Portland's Drupal users group has announced the schedule for its June meetup, and 'tis a thing of beauty. Lightning rounds bolstered by the July Drupal challenge, with a little Modules 101 for good measure.
It's been a while since the Portland group organized Lightning Rounds, so the time draws nigh. They're fast, informative, and fun. Who's lined up so far, you ask?
The group will vote on a task or challenge that can be solved by Drupal in any number of ways. The July meeting will then focus on solutions people come up with. More information here.
Iif there's time left, and anybody wants to talk for a few minutes about a module no Drupal user should be without, we'll do this too.
We meet at the OpenSourcery office at 1636 NW Lovejoy St in Portland, Oregon. NOTE Please be aware that the developers at OpenSourcery will be working right up to event time. We ask that you arrive no earlier than 5:50pm. Thank you!
After the presentation finishes we'll walk over to the Lucky Lab for food and drink.
As always, the event is free and open to the public. We hope to see you here.
Tagged as: Drupal, lightning rounds, user group meetup
A while ago I wrote about a method we'd been using internally here at OpenSourcery for testing existing Drupal configurations. There are currently a few issues in the works that would get this functionality into core-SimpleTest:
In the meantime, however, since this functionality has immediate benefits to making more robust Drupal sites, I've decided to release the module we're using internally until this is part of core-SimpleTest, and gets back-ported to Drupal 6.x. I've placed the module on GitHub rather than on Drupal.org so as not to clog things up with placeholder modules. I've also attached a tar-ball to this post for those without Git.
Update: This module has also been released on Drupal.org in order to allow people to track updates.
To use the module, it must be enabled, and then included at the top of any test file that extend the class:
// Include SimpleTest Clone module_load_include('test', 'simpletest_clone');
class CustomTestCase extends SimpleTestCloneTestCase { ... }
Occasionally, on a given site or set of tests, it may not be desirable to clone every table because this can make tests run for a very long time. Because of this, there is a method in place for excluding tables from being cloned:
/** * When testing data-intensive sites, if the tests will still run correctly, * tables can be excluded here. The structure will still be cloned, but the * data will not be copied over. */ function __construct($testId = NULL) { parent::__construct($testId); $this->excludeTables = array( // List of tables to exclude goes here. 'example_table_foo', 'example_table_bar', ); }
Tagged as: Drupal, SimpleTest, Test-driven development
Like many Drupal developers, at any particular time I'm running dozens of Apache virtual hosts on my workstation. This allows access to each project under a friendly url. We frequently create sites that employ SSL, which creates a wrinkle: officially, it's not possible to used name-based virtual hosting with SSL.
Simply disabling the SSL features on a development copy isn't the best option, because we need to test this functionality as we're developing.
It turns out that you can use SSL and vhosts together, sort of. Name-based virtual hosts can be configured on port 443 just like any other port. Apache won't stop you, though it will throw a stern warning when it starts up:
Tagged as: Apache, Drupal, SSL, Virtual Hosts
The Linux Foundation serves a worldwide community of developers and users. Their stated mission is to Promote, Protect, and Standardize the Linux ecosystem by providing unified resources and services needed for open source to successfully compete with closed platforms. More than ever, LinuxFoundation.org helps further that mission with web-based tools and vital user-generated content.
Story
The Linux Foundation and OpenSourcery began working together in the summer of 2008, with the goal of transforming the Linux Foundation's corporate site to reflect the vibrant community it supports. Their existing site was informative and, in some ways, well loved. Long-time users knew how to access the information they needed and were familiar with the site's architecture. But in the final analysis their site architecture was not tenable. The Foundation had accumulated a number of web properties, including the Linux OpenPrinting site and a number of Programs sub-domains, which had been cobbled together to serve immediate needs. Moving forward, the combined properties needed to coalesce under a single, forward-thinking architecture. Enter OpenSourcery.
Developing a new Linux Foundation site presented several challenges, which can largely be grouped into two buckets: 1) unifying deep and diverse content into a well-architected site and 2) developing a clean interface that doesn't overwhelm visitors with options.
Solving the primary challenge required open communication between OpenSourcery and the Linux Foundation. We had to ask the right questions, consider the variety of use cases, and design the site accordingly. The discovery process is well suited to our development process, which you can read about in more detail below.
Perhaps the most creative solutions employed during the development have to do with the second challenge: Linux Foundation's user interface. We realized that visitors could easily get overwhelmed by an overabundance of tabs and conflicting images. On the other hand, we wanted to avoid Flash and non-accessible JavaScript so the site could remain accessible and easily indexed by search engines. We solved both of these problems with a combination of contributed and custom modules, details of which can be found below. The result is an attractive site that makes it easy for each user to quickly access what she needs, without sacrificing the Linux Foundation's goals of completeness and accessibility. OpenSourcery is proud to have collaborated with such a talented team, and we look forward to supporting the Linux Foundation's mission in the future.
Development Process
OpenSourcery had assembled a Linux Foundation team during the development of a previous project: the Linux Foundation Video Site. From the start of their corporate site refactor, we were familiar with the Linux Foundation's project team and goals. We employed our development process from the project's beginning. We maintained close contact throughout, iterated in short bursts, and frequently pushed code so the Linux Foundation would know where their project stood at all times. Our process also allowed them to guide development by prioritizing tasks, which kept the complex project on budget and on time.
Technical Details
Tagged as: custom theme development, Drupal, Drupal 6, panels, Views
I have been working on a Drupal project here at OpenSourcery that involves a dynamic form which updates via ajax whenever a radio button or checkbox is modified. Drupal has built-in ajax/ahah, making this task much simpler. It lets you specify which type of event you want to trigger the ajax, as well as many other options.
For this specifically the requirement was that it occur with the 'OnChange' event. This works great in firefox, but not so great in IE. IE does not register an 'OnChange' event until the mouse is clicked somewhere else on the page after having changed your radio/checkbox selection. This is of course not the desired behavior.
Drupal offers other choices for events that trigger the ajax. The next obvious candidate was 'click'. Click provided consistant behavior between IE and FF. When you click the new button the form would update. However, it resulted in some undesirable behavior in both browsers. The radio button selection would not update. The correct option was sent to post for ajax, but the actual radio button selection did not change.
At this point it became obvious that I was going to need to hand-code some javascript to work around this issue. At first I attempted to write javascript that would update the radio selection after the ajax fired. This was an exercise in futility. I encountered many difficulties, most of which were probably due to inexperience.
Before pounding my head too long on my first attempted solution, a better solution reached my brain. Instead of using 'Click' and trying to re-write default radio and checkbox functionality, I would use 'OnChange' and work around IE's problem. The solution was simple, if the browser is IE, add an 'OnClick' event to all the ajax elements that triggers the 'OnChange' event.
This solution worked perfectly, and was very easy to write, even for someone with little js experience. My first time through I failed to follow proper Drupal convention, and as such I had to implement my own logic to update all the element triggers whenever ajax was used. Fortunately Jonathan reviewed my JS and pointed out the proper way to achieve this (see note 2).
Here is the final version of the javascript
Drupal.behaviors.nexusForm = function (context) { if (jQuery.browser.msie) { trig_bind() } //Hide the botton we only want to see if the browser does not support js $("#edit-continue").hide() } //IE waits until another event to send the 'change' events on radios and checkboxes //This bind a trigger for those events on click. function trig_bind() { //unbind old events $("input[type='checkbox']").unbind( 'click' ) $("input[type='radio']").unbind( 'click' ) //bind the events $("input[type='checkbox']").bind( 'click', function() { $(this).trigger( 'change' ) }) $("input[type='radio']").bind( 'click', function() { $(this).trigger( 'change' ) }) }
Notes: