pingVision

Syndicate content
Updated: 2 min 30 sec ago

Paul Taylor Dance Company website dances in Drupal

November 2, 2009 - 15:41

Paul Taylor Dance Company website

Over this past weekend, Paul Taylor Dance Company, the much respected and highly touted contemporary dance company, relaunched its website in Drupal.
<!--break-->
This gorgeous new website features an unusual design that breaks away from the conventional columnar layouts, yet benefits from semantic page structures and modern best practices in user interface interactivity. No Flash was used on the site, for example; the carousels are powered by JavaScript, leveraging the fabulous jQuery library.

For decades, the Paul Taylor Dance Company has been a leader in contemporary dance. We are proud to have helped create a website that reflects the beauty and innovation of their art.

Paul Taylor Dance Company website

Paul Taylor Dance Company website

Categories: Planet Drupal

WhiteHouse.gov goes Drupal: can open source lead to open government?

October 25, 2009 - 22:24

The news had Twitter abuzz yesterday. The official White House site has migrated from a proprietary software to open source Drupal.

"We now have a technology platform to get more and more voices on the site," White House new media director Macon Phillips told The Associated Press hours before the new site went live on Saturday. "This is state-of-the-art technology and the government is a participant in it....

"We want to improve the tools used by thousands of people who come to WhiteHouse.gov to engage with White House officials, and each other, in meaningful ways," Phillips said.

As a web developer with five years' experience working with Drupal, watching it growing up over the years, this is very exciting news.

Deborah Bryant puts in a note of caution.

Let’s be clear that this constitutes a change in plumbing – important plumbing – and not policy – but is a significant and of course highly visible sign that open source software has gone main stream.

Her skepticism is well taken. After all, what difference does a change in back-end code bring to the end-user experience of citizens? But the Post article does point to hints at policy changes.

It's also a nod to Obama's pledge to make government more open and transparent. Aides joked that it doesn't get more transparent than showing the world a code that their Web site is based on.

Maybe there's something to that. Given Drupal's strengths as software to connect people through the Internet, this is potentially exciting news for how our government works as well.

Open Source Government?

Drupal is not brochureware, it's community software that is extensible, flexible and modular. Jamie writes on Intoxination:

Given the extensibility of Drupal and existing modules that can provide anything from a full social network site to a major campaign site, including email letters, I say we can expect to see a much more user oriented whitehouse.gov.

Can we read that much into the choice of a web platform? Nancy Scola writes on TechPresident:

Let's really try to extract the last drop of possible meaning from a choice over a CMS. Squint a bit, and it's possible to see the White House's move to open-source software as a move towards the idea that collaborative programming can inspire -- or at least, support -- a more distributed politics. That idea bubbled up in 2004, when young programmers experimented with using Drupal itself to turn the Howard Dean campaign into the Howard Dean network. This idea, that a politics crafted by the people could be a powerful thing indeed, emerged in a slightly mutated way during the Obama presidential campaign, but has arguably receded below the surface during the first nine months of the Obama Administration. First the WhiteHouse.gov CMS gets more open, then the White House OS? Perhaps.

For the lay user, the White House website looks much the same as it has since inauguration day (though search should work noticeably better). But by being open source, the White House is opening itself up to all the bright ideas, powerful plug-ins, and innovative tools that the considerable community of Drupal aficionados come up with. It's a community that the White House says it is eager to tap into. "Open source is a great form of civic participation," the White House's Phillips told me this afternoon. "We're looking forward to getting the benefit of their energy and innovation."

Tim O'Reilly recently offered a vision:

Too often, we think of government as a kind of vending machine. We put in our taxes, and get out services: roads, bridges, hospitals, fire brigades, police protection… And when the vending machine doesn’t give us what we want, we protest. Our idea of citizen engagement has somehow been reduced to shaking the vending machine. But what meetup teaches us is that engagement may mean lending our hands, not just our voices.

In this regard, there’s a CNN story from last April that I like to tell: a road into a state park in Kauai was washed out, and the state government said it didn’t have the money to fix it. The park would be closed. Understanding the impact on the local economy, a group of businesses chipped in, organized a group of volunteers, and fixed the road themselves. I called this DIY on a civic scale. Scott Heiferman corrected me: “It’s DIO: Not ‘Do it Yourself’ but ‘Do it Ourselves.’” Imagine if the state government were to reimagine itself not as a vending machine but an organizing engine for civic action. Might DIO help us tackle other problems that bedevil us? Can we imagine a new compact between government and the public, in which government puts in place mechanisms for services that are delivered not by government, but by private citizens? In other words, can government become a platform?

Heady stuff. But impossible? Business is getting involved as well. On NextGov, Jill R. Aitoro wrote this Summer about Open Source for America,

More than 50 companies, academic institutions, communities and individuals formed Open Source for America to promote its use in the federal government. Open source generally refers to software code that is provided to the public to modify and download for free. Its supporters argue the method lowers the cost of software development and can provide better applications because an unlimited number of programmers are free to improve the underlying code.

"This is the right time, with the administration and the economy and the direction that open source is moving" all supporting greater adoption, said John Scott III, director of open-source software and open integration at federal consulting firm Mercury Federal. "If you read between the lines and look at what the White House is doing, they're leading by doing. The sole purpose of this organization is to answer the president's call for technologies that help government be more participatory, more collaborative and more transparent."

The coalition, which counts Red Hat, Google, Sun Microsystems, Novell and Oracle among its members, will form working groups to focus on specific areas, such as health care, cybersecurity and defense.

But let's back up a second from the do-ocracy vision of politics, and look at the pragmatic world where open source software adoption could yield immediate results....

Open Source Elections

One obvious pragmatic use case for open source software in government functions is tallying votes in our democratic elections. This is especially true considering the problems of the last decade with electronic voting machines. For example....

Initiatives behind the adoption of open source software in our elections seem to be gaining momentum. Last week, Kim Zetter writes in Wired:

The Open Source Digital Voting Foundation (OSDV) announced the availability of source code for its prototype election system Wednesday night at a panel discussion that included Mitch Kapor, creator of Lotus 1-2-3 and co-founder of the Electronic Frontier Foundation; California Secretary of State Debra Bowen; Los Angeles County Registrar-Recorder Dean Logan; and Heather Smith, director of Rock the Vote.

The OSDV, co-founded by Gregory Miller and John Sebes, launched its Trust the Vote Project in 2006 and has an eight-year roadmap to produce a comprehensive, publicly owned, open source electronic election system. The system would be available for licensing to manufacturers or election districts, and would include a voter registration component; firmware for casting ballots on voting devices (either touch-screen systems with a paper trail, optical-scan machines or ballot-marking devices); and an election management system for creating ballots, administering elections and counting votes....

Miller said the foundation wasn’t looking to put voting system companies out of business but to assume the heavy burden and costs of research and development to create a trustworthy system that will meet the needs of election officials for reliability and the needs of the voting public for accessibility, transparency, security and integrity.

“We believe we’re catalyzing a re-birth of the industry … by making the blueprint available to anyone who wants to use it,” Miller said.

The post is titled, "Nation’s First Open Source Election Software Released," which is perhaps misleading, considering previous efforts that have not received so much attention over the years. The Open Voting Consortium (which apparently has just moved its website to Drupal as well) has been working this field for years now, and is already providing software for regional and party elections.

And a little Googling reveals first-page results for OpenSTV, open-source software for implementing the single transferable vote and other voting methods such as instant runoff voting, Condorcet voting, and approval voting, and PVote, prototype software for electronic voting machines.

But getting away from the who was first question, it seems that the Open Source Digital Voting Foundation and The Open Voting Consortium have very similar missions. As I write this, I don't know how much they work together or collaborate. In the open source world, collaboration on code is pretty much a given, but politics is a different animal. But it's good to see both organizations making strides in this area.

Participating in The Commons

In a blog post today, Tim O'Reilly comments on the adoption of open source — and Drupal in particular — by the federal government:

The net-net is that I suspect that simply using open source software won't slash government IT budgets, at least not right away. What it will do is increase the amount of value we get for our money and the speed with which new technology can be adopted. Features that would have cost millions of dollars and years of development to add will now be rolled into the scope of current contracts.

It's also important to realize that using open source is very different from contributing to open source. Despite the exaggerated claims in the AP story, that "the programming language is written in public view, available for public use and able for people to edit", the White House has not yet released any of the modifications they made to Drupal or its operating environment back to the open source community. The source code for Drupal (and the rest of the LAMP stack) is indeed available, but the modifications that were made to meet government security, scalability, and hosting requirements have not yet been shared. In my conversations with the new media team at the White House, it is clear that they are exploring this option.

Giving modifications back to the Drupal community is the next breakthrough announcement that I'll be looking for.

Indeed.

Update: I came across this video series just after posting this post. It'a a well produced, well put-together video, and quite interesting.

[This post is also posted on BlogHer.com.]

Categories: Planet Drupal

DrupalCon thoughts (and Functional Interaction Design slides)

September 10, 2009 - 21:21

Last week was something of a whirlwind for me, flying into Paris on Monday morning, barely recovering from jet lag by Tuesday when DrupalCon Paris 2009 started, and racing through the week.

DrupalCon Paris Photos
Ah the memories ... trying to sleep in United coach and landing in Paris red-eyed and disoriented ... fighting Snow Leopard technical problems ... windows blowing open, dousing me in hot coffee ...

DrupalCon Paris group photo(s)
The group photo (outside and then inside)....

...and before I knew it, I was back on the plane Saturday morning heading back to Colorado. In between was full-on Drupal. (My Paris sightseeing was limited to the walk every day between the hotel and the venue, and the 2 or 3 evening excursions for dinner.)

interaction design
For me, everything built up towards Friday, when I had two presentations — one on Functional Interaction Design and one on "Agile" is not "Cowboy" spelled backwards (on estimating techniques and project management experiences. I greatly appreciated the folks who turned up for both.

The latter session was rather last-minute on my part, after Kate, who was going to lead the session, had to stay behind at the last minute to attend to business matters, but we ended up having a great discussion. (Because of the ad hoc nature of my presentation, I don't have any slides worthy of sharing.)

The design session was drawn largely off of a presentation I made at DrupalCamp Colorado this summer. Again, I'm thankful for those who came, especially since it was at 9am — awfully early for people surrounded by Paris nightlife. I was bummed, though, because I had to miss other great sessions that hour, including our own Al Steffen's presentation on Drupal theming techniques.

In fact, I feel I missed much of the conference. I tallied up my mistakes so I don't do it again!

Everything was videotaped. Videos should be posted soon, I understand. I will update this post with a link to the videos of my sessions when they're posted.

Meanwhile here are the slides for:

Functional Interaction Design

View more documents from Laura Scott.
Categories: Planet Drupal

Open Atrium presentation at DBUG Meetup at pingVision

September 9, 2009 - 21:06

This is video we shot of a Boulder Drupal User Group Meetup presentation by Ian Cairns of Development Seed and Matt Tucker of pingVision on Open Atrium, the open source intranet system currently in beta release, and the fascinating new potential arising from the new Features Module, which is used to great effect in Open Atrium.

A higher-definition, embeddable version of the video is available on our Blip.tv channel. If anyone wants to help translate this, we posted the video on DotSub as well.

Hope you like it!

--

Update: Uploaded a lighter weight version to speed up load times.

Video No.:  2 See also:  Open Atrium as our Client Support Site
Categories: Planet Drupal

Drupal 7 theme changes

August 26, 2009 - 23:20

When we made the move from Drupal 5 to 6, there were some nice improvements to the theme system. Preprocess functions, better sub-theming and the theme registry were all great of additions to the system. These and others helped extend what could be done with themes and made the Drupal system as a whole more powerful. How could it get any better? With the fast approaching Drupal 7 code freeze this September, it is a good time to get a sneek peek.

.info file changes

Blocks and regions have been a integral part of Drupal. Being able to configure and place content via an administration interface allows for a very flexible system. The Drupal developers have taken notice of this and expanded the scope of what can be done with these elements. To compliment this change the theme has gained more configurable content placement, more default regions and a new ability.

To start, $content is now a block and there needs to be a place for it in any theme. This means that Drupal 7 now has it's first ever required region called, appropriately, "content". If you decide to declare any regions in your theme's .info file, this one must be included in order for your theme to be selectable.

There are two more recommended regions to add to your custom themes: "help" and "highlight". The "help" region is to accommodate help now being a block element. This also means your help content will be contained in a block.tpl.php template. By default, a theme will output the help text to this region, but that can be changed in blocks administration. The "highlight" region is a replacement for the former mission statement functionality in prior versions of Drupal. Now if someone wants to place a mission statement on the page, a new block will need to be created. Eliminating either of these regions will not cause your site to break, but it will certainly decrease it's default functionality.

With this expanded use of the block system, a site can have a lot of regions available. A lot of these regions are only used for very specific modules and do not need to be muddying up the blocks administration. The solution to this is the new hidden region designation.

Implementing a hidden region is pretty simple. You declare a new region just as any other (ex. regions[secret] = Super secret region). You then need to add it to the list of hidden regions with hidden_region (ex. regions_hidden[] = secret). All together, you should have something like the following:

regions[content] = Content
regions[help] = Help
regions[page_top] = Page top
regions[page_bottom] = Page bottom
regions[secret] = Super secret region
regions_hidden[] = secret

Now that you know what a hidden region is, it is time to mention two new predefined hidden regions that you may notice in the example above: "page_top" and "page_bottom". If you have to redefine these regions, there is no need to add these to regions_hidden[] since they are predesignated in the system. These are in place to accommodate some new core blocks that are non-configurable. "page_top" is for placement of the new Administration toolbar. In your template, it should be output just inside the <body> tag, above all other markup. "page_bottom" is a replacement for the former $closure variable and functions the same.

In Drupal 6, themes that do not have any stylesheets or javascript files defined automatically get assigned a style.css stylesheet and script.css javascript file. This seems all well and good, but it really caused problems when creating a subtheme based on one that used the same files. If the subtheme also is not define any of these files, it would be assigned the same defaults. This caused another feature of Drupal to activate intended to make style and javascript overrides simpler: any style and javascript files of the same name would be removed in favor of the current theme's. For that reason, in Drupal 7 all stylesheets and script files now must be defined in the theme's .info file.

Template changes

There are now wildcard template files. As an example, if you wanted to override the page template when displaying a user, you simply add a page-user.tpl.php to your theme. The problem here is that this override also overrides the user login page. Something more specific is needed, but generalized so that it applies to all user pages.

For this reason, Drupal 7 introduces wildcard templates to solve this issue. For example, to solve the above conundrum, simply add a page-user-%.tpl.php file to the theme. The "%" is a placeholder for any Drupal system id (ex. node, profile, term, etc) and is based on the default url for the element. So a page template for any node, but not the default Drupal front page of /node, is page-node-%.tpl.php. This function expands beyond the page template and can be very useful.

box.tpl.php is now gone. This template file was used to wrap the comment for for nodes. Retheming the form itself is the proper approach now.

There are also a significant amount of changes to the variables available to page.tpl.php. These changes will compliment additional functionality and change in how a page is structured.

It has been talked about for a while and it is finally coming to fruition: RDFa support for Drupal is in version 7. Since this technology requires elements in the markup of the site, there are some pieces that will need added. A big change is the default doctype for Drupal will be changing. In Drupal 6, the recommended doctype was as follows:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

To comply with the RDFa specification, it will need to be a bit different.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
  "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">

To further compliment the document type, there are changes to the html and head tags also. First, the lang attribute is to be replaced by xml:lang. The same $language->language gets placed in the value. Namespaces are a crucial part of this change, and they are added with the new $rdf_namespaces variable. Simply place this at the end of the html tag. Finally, the head tag needs GRDDL information added to the profile attribute. This is done with another new variable, $grddl_profile.

When all of that is added, you will have this:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php print $language->language ?>" dir="<?php print $language->dir ?>"
  <?php print $rdf_namespaces ?>>
  <head profile="<?php print $grddl_profile ?>">

There are some changes to familiar variables too. The $footer_message variable are no longer needed for one. Other changes are purely in name only and functionality is the same:

  • $left is now $sidebar_first.
  • $right is now $sidebar_second.
  • $primary_links is now $main_menu.
  • $secondary_links is now $secondary_menu.
  • $picture is now $user_picture.

Granular theming of content

One of the big changes in Drupal 7 is the addition of fields in core. This not only brings much of the power of CCK, but also allows the system more control over how the fields get displayed. With CCK in drupal 6, getting granular output involved long strings of text to output a portion of an array. There were even security risks involved due to uncleaned data. This is now simplified and secured with the render(), show() and hide() functions.

An example is the easiest way to show how the system works. Previously, node content was output with a simple <?php print $content; ?>. Now $content is an array containing all fields related to the node. The render() function takes all of this data and renders it to a proper string for output. So if all you wanted to do is show a simple, complete dump of the node fields, you would use <?php print render($content); ?> instead. This would be missing the real advantage, though.

How is this "granular"? There is another facet to this function and that is that individual elements can be output. For example, if you wanted to output just the links in a node template you would add <?php print render($content['links']); ?> to it. As a bonus, this small piece of content will be flagged as already printed. This means you can use <?php print render($content); ?> afterwards and it will output everything but the links portion.

The show() and hide() functions are simple helpers. show() is used to flag already printed content as unprinted. This will be handy for when you want an element printed a second time. hide() is just the opposite. It is used to prevent a specific element from being output when render() is run on a more generic element.

The new node.tpl.php gives a good example how this can be used. Here is an excerpt of the important part:

<div class="content">
  <?php
    // We hide the comments and links now so that we can render them later.
    hide($content['comments']);
    hide($content['links']);
    print render($content);
  ?>
</div>

<?php print render($content['links']); ?>

<?php print render($content['comments']); ?>

If there wasn't enough fun to be had with this new system, you now have the ability to include special styling or javascript with individual elements. In the variable containing the content, simply add a value to the #attached_css or #attached_js arrays.

Currently attached styles and scripts cannot be used in a page template. This is because that drupal_add_css() and drupal_add_js() are used in this process and these functions do not work properly in the template either. There is work going on to attempt to fix this, but as of this writing, the fix has not been committed.

Granular theming is actively being used in node, comment and profile templates. We will most likely see an expansion of the implementation before the code freeze in September. The process is not limited to these areas though and can be used in other facets of Drupal as long as the data is structured properly. For instance, elements of a simple theme function could be assembled into an array and output in the same manner.

Id and Class changes

One change comes in the form of a class array. Previously, the accepted way to add dynamic classes was to embed messy logic to the template file. For example, here is how the old Drupal 6 Garland theme node.tpl.php added classes:

<div id="node-<?php print $node->nid; ?>" class="node<?php if ($sticky) { print ' sticky'; } ?><?php if (!$status) { print ' node-unpublished'; } ?>">

  <?php // Extra markup removed for brevity. ?>

</div>

The new Drupal 7 version is noticeably much cleaner:

<div id="node-<?php print $node->nid; ?>" class="<?php print $classes ?>">

  <?php // Extra markup removed for brevity. ?>

</div>

To add more classes to the template, you could just add them after <?php print $classes ?>, but it is now recommended to add them to the classes array in a preprocess function like so:

<?php
function mytheme_preprocess_node(&$vars) {
  // Add a striping class.
  $vars['classes_array'][] = 'node-' . $vars['zebra'];
}
?>

This becomes especially nice for keeping a theme tidy, as there is less of a need for extra template files whose sole purpose is to add a new class. (Studio theme pack users will possibly find this method somewhat familiar.)

The class formerly known as .clear-block is now known as .clearfix. This is the more common name for the method introduced by Position is Everything. This is a simple change that will make the Drupal theme layer more inviting to newcomers familiar with the tactic.

New to Drupal and joining .clearfix in the predefined style toolbox are .element-hidden and .element-invisible. These provide ways to hide content on a site in an accessible fashion. Each is made to handle a different situation when it comes to omitting content from view. The .element-hidden class is intended for immediately hiding an element on page load, but still allowing for javascript effects to open it. This class is best added with javascript and not hard-code it into your templates. The .element-invisible is intended to hide the content on full-featured browsers, but still keep it accessible to screen readers.

There are also changes to some of the typical block ids as outlined here on the upgrade handbook page. This is in and of itself not a big deal since this sort of thing is subjective and easily overridden with a template override. The thing to take note of here is that these ids are primarily derived from the $delta variable. This means that the information contained within is more semantic and less cryptic. This is a good thing to come to core.

Advanced theming changes

In order to fix some inheritance issues and confusions, all function names in the theme must match the theme name. Previously we could declare a new theme function of the name phptemplate_preprocess_node(). This was the recommended method for base themes, but it was discovered that this led to functions being run twice and other oddities. The recommendation then changed to naming all functions after the theme. This is now a must in Drupal 7.

Preprocess was a great addition in Drupal 6 and led to much cleaner template files. Now those functions get a sibling call process functions. These functions work in much the same way. They are fired after it's complimentary preprocess function and are intended to finalize any data changes that happened earlier. As an example, if you add a class to the $vars['classes'] in mytheme_preprocess_node($vars), it will get rendered into a single string for node.tpl.php in a later process function.

People liked preprocess so much with their template files, the same has also been brought to the simple theme functions. This is complete with the new process function functionality. This will hopefully bring more abstraction of logic and display to the theme function and make them easier to understand for PHP novices. This is a very recent addition at the time of this post, so the effect has yet to be seen completely.

The drupal_add_js() and drupal_add_css() functions have gained some extra kick. The option for adding an external file has been added to both. Now instead of adding a commonly used library to your own file system, you can take advantage of services like Google's AJAX libraries for remote hosting.

These two functions have also gained weight support. This will be especially handy for creating a theme that used a CSS framework or reset stylesheet. It normally best to have this type of styling loaded before any other styles, and adding a weight to the stylesheet will make that process much easier. The final addition is for drupal_add_css() only: the ability to add inline styles. drupal_add_js() has had this functionality for some time, and now it can be used for styles. This will come into play when attempting to style an element that has a dynamic size.

The final change is that jQuery UI is now part of the core distribution. It is a welcome inclusion since it allows more graphical sheen without extra modules. There are more tools for a themer to reliably take advantage of and will allow for some more interesting effects.

Getting involved

This is just a summary of what is currently done. There is a lot more items that need work and it is not hard to get involved. Do not fear the issue queue. Even if all you can give is input, please give it. There are tags available for both design review and themer review in addition to the theme system component. There are definitely more issues if you dig deeper, but these are good places to start.

Related:  Introducing the Studio Theme Pack
Categories: Planet Drupal

Open Atrium as our Client Support Site

August 7, 2009 - 20:41

The widely anticipated release of Open Atrium, created by the fantastic team at Development Seed, attempts to bring Drupal into the world of intranets, allowing different teams to have their own conversations. As soon as it was released, I, along with other pingVision developers began evaluating it as a potential tool for communicating with our clients.

Open Atrium

Previously, we were using a custom-built, organic group-based system to communicate with our clients. We developed most of the functionality using common contributed modules and added a few custom features as well. But overall, it was lacking. The design itself was minimalist, the feature set was small, and we, along with our clients, found it hard to use on a day to day basis. Sure, it functioned, and got the job done, but we have been too busy with work to dedicate time to improving it - sad, I know :)

Installing Open Atrium was a breeze, because after all, it's just Drupal with an install profile. On first glance, Open Atrium is stunning. A simple to use navigation structure and intuitive controls for adding groups, users, and features makes it a fantastic out of the box system. But what is under the hood is almost prettier than what is immediately apparent.

Open Atrium is built around context, features and spaces. These three modules, which also have been put together by the Development Seed team, are incredible. They each serve a distinct purpose in building the intranet functionality that is Open Atrium.

Context allows you to create "sections" of a site based on a number of conditions, such as the types of nodes being displayed, or the specific views being accessed. Based on these conditions, context allows you to specify certain reactions such as which links are active, which blocks are visible, and even add css classes for more robust theming. An example of a context in Open Atrium, is the blog. This is a pretty simple context which becomes active when either viewing a blog node or the "atrium_blog" view. Given these conditions, the "blog" menu is made active and the "Recent Comments" block is placed in the right side bar. All blocks in Open Atrium are positioned via context which makes the normal Drupal blocks administration interface extremely clean as there appears to be no blocks in any of the available regions.

Features is an amazing concept. Drupal is like a bunch of lego blocks, that you stack together in different ways to build distinct features. For example, as mentioned above, the "blog" features is comprised of the blog node type (which contains several CCK fields), the blog view (which contains a page and a block display). There are also various permissions associated with creating, viewing, and deleting blog posts. Using export functionality already built into CCK, Views, and other modules, Features attempts to encapsulate all of these configuration items into a single downloadable module. This allows for ease of transport. The Open Atrium team has big plans to create a "Distributed Feature Server" which will allow the community to quickly and easily share created features. For example: a generous Drupal developer, might create an image gallery feature comprised of an image node type, a few specialized and themed views, which maybe integrates with lightbox for a slick overlay display. This feature could be contributed in its entirety and downloaded and installed on any Open Atrium installation.

So this, by itself, is already amazing, but features takes it one step further. Because all of the configuration tasks associated with building out content types and views and other requirements of a fully-functional feature are exported into code, modifications can be tracked, merged, and even version controlled. Although we have yet to fully explore all of the possibilities associated with this fantastic aspect of the features module, it has the potential to solve the major issue of pushing configuration tasks from a development environment to live. We will definitely be evaluating this aspect more in the future.

Spaces is the perfect companion to features. It allows certain features to be enabled and customizable in various sections on your site. It provides a way to specify how spaces are designated. The "spaces_og" module, included in the spaces download, allows you to define a space per organic group. This essentially allows you to enable and customize features on a per group basis. So while one group might have an image gallery, blog, and calendar of events, another organic group might have a shoutbox, blog, and case tracker. This allows you to customize each organic group ("space") to include only the functionality needed. In Open Atrium terms, this allows each group to have a different set of features customized specifically for that group's interaction.

As Laura Scott, one pingVision's co-founders said:

Our main interest is in having a client support infrastructure that doesn't take a lot of our time to maintain. Our legacy intranet was built in Drupal 6, and in many ways similar to Open Atrium. But the launch of the Open Atrium distro offered the opportunity to join a commons even more focused on the particular needs of this site. As an open source design and development shop, changing over to Open Atrium was a no-brainer.

We immediately began work on creating and customizing an Open Atrium installation to fit our needs. Our client support site serves as a focal point for all client communication. Information about the status of the project, the hours spent and remaining, notes from our daily scrum calls, use cases, and the ability to prioritize tasks were all needed. We created a new context, feature and menu item associated with all of these tools:
pingVision Open Atrium menu example

We have a fairly sophisticated workflow associated with various node types which controls access and visibility based on workflow state. Our lead developer, John Fiala, also built a robust email notification system which reminds clients and pingVision staff of items in need of their attention. It is completely configurable by case tracker and workflow state and will be contributed at some point in the future. The process of creating the needed content types, workflows, and views was no different than any other site. Adding the content types and views to a context and creating a new menu item was simple following the guide on the Open Atrium site. All in all, the experience was pleasant, and our needed enhancements to Open Atrium were simple to implement.

Over the coming weeks, we will be adding new and returning clients to our Open Atrium site. It has been an absolutely fantastic experience working with Open Atrium, and all of us at pingVision look forward to using it, along with the knowledge we have learned regarding Context, Features, and Spaces in the coming months.

Categories: Planet Drupal

pingVision Heading to DrupalCampLA this Weekend

August 4, 2009 - 20:59

This weekend is DrupalCamp LA and five of us here at pingVision are flying out to the left coast to join in on the fun!

We're all looking forward to seeing the sun in LA - Boulder's been an unusually cloudy place to be this summer - as well as soak up the Drupal fever with the other 400+ attendees.

Categories: Planet Drupal

Using a theme's .info file to add order, conditions to stylesheets

July 28, 2009 - 18:51

The one required file in any Drupal 6 theme is the .info file. It was a great addition to the theme layer and makes defining functionality almost dead simple. Documented features of the .info file allow for adding descriptive information, features, stylesheets and javascript files to the theme. This has made constructing a custom theme much easier compared to Drupal 5 since there is no mucking about in PHP necessary.

The system is not perfect and there are limitations to this set of supported definitions. For instance, all stylesheets added via the theme are always ordered after all the system and module stylesheets. This is less than optimal for reset CSS files and CSS frameworks like 960 grid system. Another common practice is conditional stylesheets for Internet Explorer browsers. The only option to use this method is to hard code the stylesheets into the page.tpl.php or install a module. It would be so nice to define these files in the theme's .info file and keep the themes flexible.

Thankfully, this is fully possible with the help of a couple variables. As a warning for those not versed in PHP, implementing any of this functionality requires it's use.

A little example

Anything that is added to the .info file is available for use. This is not restricted to the supported features. As an example, let's construct a simple theme called "jim".

Since this is purely an example, our theme is only going to consist of 3 files: jim.info, reset.css and ie6.css. It will not be necessary to add anything to the CSS files since this is only an example, but it will be necessary to add something to the .info file to get it recognized by Drupal.

name = Jim
core = 6.x
engine = phptemplate

This is only the required information for a Drupal theme. It will not win any beauty contests, but now we can now select the theme as our default in themes administration. Since that is done, let's add our stylesheets in an unconventional way by adding the following lines to our jim.info.

top stylesheets[all][] = reset.css
ie stylesheets[ie 6][all][] = ie6.css

The standard practice is to clear the theme registry cache when adding to a theme's .info file, but there will not be any noticeable effect. To get access to this information we will need to delve into some PHP. The proper place for that would be the template.php, so add one to the theme's folder.

Dig into $theme_info

We will be adding our extra styles to the $styles variable in page.tpl.php. This will be done via hook_preprocess_page() in template.php. In order to use this preprocess function, a page.tpl.php will needed in our theme. I simply copied the core Drupal version at modules -> system -> page.tpl.php to our theme.

To get at our new stylesheets in jim.info, we will need access to the $theme_info variable in the hook_preprocess_page() function. Since it is not immediately available, we will have to load it as a global variable. With all of this in mind, you should have something like this in your template.php:

<?php
function jim_preprocess_page(&$vars) {
  global $theme_info;
}
?>

If you have the Devel module installed, you can place to a dpm($theme_info); in that function to display the contents of the variable. If you look in $theme_info->info, you will see your new stylesheet definitions. Now to put them to work for us.

Put stylesheets at the top of the stack

Our first task will be to add the top styles to the top of the stylesheet stack. To take advantage of CSS compression in Drupal, we will want to put it in with the rest of the accounted for stylesheets and then run them through drupal_get_css(). There will be a bit of sorting needed to accommodate for the media types. In the end you will have something that looks like the following.

<?php
function jim_preprocess_page(&$vars) {
  global $theme_info;

  // Get the path to the theme to make the code more
  // efficient and simple.
  $path = drupal_get_path('theme', $theme_info->info['name']);

  // Check if there are stylesheets to be placed at the
  // top of the stack.
  if (isset($theme_info->info['top stylesheets'])) {
    $top_css = array();
    // Format the stylesheets to work with
    // drupal_get_css().
    foreach ($theme_info->info['top stylesheets'] as $media => $styles) {
      foreach ($styles as $style){
        $top_css[$media][$path . '/' . $style] = TRUE;
      }
      // Add the stylesheets to the top of the proper
      // media type.
      array_unshift($vars['css'][$media], $top_css[$media]);
    }
    // Replace $styles with the new string.
    $vars['styles'] = drupal_get_css($vars['css']);
  }
}
?>

With this code in place, you can now add new stylesheets at will to the jim.info file. Nice, neat and flexible.

Adding conditions for Internet Explorer

For something a little more complicated, we will now add the support for the conditional stylesheets that only Internet Explorer will see. It will be good to pass these through the drupal_get_css() to take advantage of CSS compression, but the final output can be tacked onto the end of the existing $styles variable.

With only the conditional stylesheets, your function will look like this:

<?php
function jim_preprocess_page(&$vars) {
  global $theme_info;

  // Get the path to the theme to make the code more
  // efficient and simple.
  $path = drupal_get_path('theme', $theme_info->info['name']);

  // Check for IE conditional stylesheets.
  if (isset($theme_info->info['ie stylesheets'])) {
    $ie_css = array();
    // Format the array to be compatible with
    // drupal_get_css().
    foreach ($theme_info->info['ie stylesheets'] as $version => $media) {
      foreach ($media as $type => $styles) {
        foreach ($styles as $style) {
          $ie_css[$version][$type]['theme'][$path . '/' . $style] = TRUE;
        }
      }
    }
    // Append the stylesheets to $styles, grouping by IE
    // version and applying the proper wrapper.
    foreach ($ie_css as $version => $styles) {
      $vars['styles'] .= '<!--[if ' . $version . ']>' . "\n" . drupal_get_css($styles) . '<![endif]-->' . "\n";
    }
  }
}
?>

As with the top stylesheets, you can now add new IE conditional stylesheets via the jim.info file. Each line for a CSS file to add would need to be formatted like so: ie stylesheets[conditional logic][media type][] = filename.

Bringing it all together and base themes

By now, your template.php should look like the following:

<?php
function jim_preprocess_page(&$vars) {
  global $theme_info;

  // Get the path to the theme to make the code more
  // efficient and simple.
  $path = drupal_get_path('theme', $theme_info->info['name']);

  // Check if there are stylesheets to be placed at the
  // top of the stack.
  if (isset($theme_info->info['top stylesheets'])) {
    $top_css = array();
    // Format the stylesheets to work with
    // drupal_get_css().
    foreach ($theme_info->info['top stylesheets'] as $media => $styles) {
      foreach ($styles as $style){
        $top_css[$media][$path . '/' . $style] = TRUE;
      }
      // Add the stylesheets to the top of the proper
      // media type.
      array_unshift($vars['css'][$media], $top_css[$media]);
    }
    // Replace $styles with the new string.
    $vars['styles'] = drupal_get_css($vars['css']);
  }

  // Check for IE conditional stylesheets.
  if (isset($theme_info->info['ie stylesheets'])) {
    $ie_css = array();
    // Format the array to be compatible with
    // drupal_get_css().
    foreach ($theme_info->info['ie stylesheets'] as $version => $media) {
      foreach ($media as $type => $styles) {
        foreach ($styles as $style) {
          $ie_css[$version][$type]['theme'][$path . '/' . $style] = TRUE;
        }
      }
    }
    // Append the stylesheets to $styles, grouping by IE
    // version and applying the proper wrapper.
    foreach ($ie_css as $version => $styles) {
      $vars['styles'] .= '<!--[if ' . $version . ']>' . "\n" . drupal_get_css($styles) . '<![endif]-->' . "\n";
    }
  }
}
?>

This bit of code will work great for a standalone theme. Problems will arise when used in a base theme as stylesheet inheritance will be broken. Thankfully, there is a second variable to help with that: $base_theme_info.

This variable has all information on the current theme's base theme, and all base themes of those base themes. Instead of going through all of the explanation, I will simply post the code that takes advantage of it.

<?php
function gaffigan_preprocess_page(&$vars) {
  // Collect all information for the active theme.
  $themes_active = array();
  global $theme_info;

  // If there is a base theme, collect the names of all
  // themes that may have data files to load.
  if(isset($theme_info->base_theme)) {
    global $base_theme_info;
    foreach($base_theme_info as $base){
      $themes_active[] = $base->name;
    }
  }

  // Add the active theme to the list of themes that may
  // have data files.
  $themes_active[] = $theme_info->name;

  // Check for stylesheets to be placed at the top of the
  // stack or conditional Internet Explorer styles in the
  // .info file and add them to the $styles variable.
  $top_styles = array();
  $ie_styles = array();

  // If there is more than one active theme, check all
  // base themes for stylesheets.
  if (count($themes_active) > 1) {
    foreach ($base_theme_info as $name => $info) {
      if (isset($info->info['top stylesheets'])) {
        $top_styles[$name] = $info->info['top stylesheets'];
      }
      if (isset($info->info['ie stylesheets'])) {
        $ie_styles[$name] = $info->info['ie stylesheets'];
      }
    }
  }

  // Check the current theme for stylesheets.
  if (isset($theme_info->info['top stylesheets'])) {
    $top_styles[$theme_info->name] = $theme_info->info['top stylesheets'];
  }
  if (isset($theme_info->info['ie stylesheets'])) {
    $ie_styles[$theme_info->name] = $theme_info->info['ie stylesheets'];
  }

  // If there is at least one entry in the $top_styles
  // array, process it.
  if (count($top_styles) >= 1) {
    // Format the array into a format readable by
    // drupal_get_css().
    $vars['top_css'] = array();
    foreach ($top_styles as $name => $theme_styles) {
      $path = drupal_get_path('theme', $name);
      foreach ($theme_styles as $media => $styles) {
        foreach ($styles as $style){
          $vars['top_css'][$media]['featured'][$path . '/' . $style] = TRUE;
        }
        // Add the new styles to the top of the
        // $vars['css'] array.
        array_unshift($vars['css'][$media], $vars['top_css'][$media]['featured']);
      }
    }
    // Run $vars['css'] through drupal_get_css and
    // replace the $styles variable.
    $vars['styles'] = drupal_get_css($vars['css']);
  }

  // If there is at least one entry in the $ie_styles array,
  // process it.
  if (count($ie_styles) >= 1) {
    // Format the array into a format readable by
    // drupal_get_css().
    $vars['ie_css'] = array();
    foreach ($ie_styles as $name => $theme_styles) {
      $path = drupal_get_path('theme', $name);
      foreach ($theme_styles as $version => $media) {
        foreach ($media as $type => $styles) {
          foreach ($styles as $style) {
            $vars['ie_css'][$version][$type]['theme'][$path . '/' . $style] = TRUE;
          }
        }
      }
    }
    // Append the stylesheets to $styles, grouped by IE
    // conditional.
    foreach ($vars['ie_css'] as $version => $styles) {
      $vars['styles'] .= '<!--[if ' . $version . ']>' . "\n" . drupal_get_css($styles) . '<![endif]-->' . "\n";
    }
  }
}
?>

As expected, this ends up being more complicated. The gist of what is going on here is that we have to add an extra level to check what theme is associated with which content. From that point a lot of the process is the same.

Conclusion

For reference, the above themes are attached to this post.

There is a lot of untapped power available in the .info files. I focused on stylesheets in this instance, but there is certainly more that can be accomplished. Placing javascript files in the footer is just one example. I am sure more imaginative people than I can come up with even more.

For those of you wondering, this functionality will be in an upcoming 2.0 version of the Studio theme pack. This will be one of a few changes and others will most like be highlighted at a later date.

Categories: Planet Drupal
 
 

Drupal is a registered trademark of Dries Buytaert.