pingVision

Syndicate content
pingVision provides interactive design and development services for all media. Our specialties include Drupal web design and development, graphic design, and DVD/broadcast design. We're located in Boulder, Colorado.
Updated: 1 year 12 hours ago

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

Tue, 07/28/2009 - 13: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: Drupal blogs

"What is Drupal?" wins six Telly Awards

Fri, 07/17/2009 - 21:18

Last week we learned that our video What is Drupal? (in 57 seconds) won six Telly Awards.

It's a little embarrassing, winning six awards for one video. When we submitted our entry, we weren't quite sure what category to put it under. So we just threw it into a few different categories, hoping that it might win in one or two. We didn't expect to win an award in all categories entered. (We hoped, though!)

I wish we had more videos already posted. Soon! Meanwhile, our thanks to the Telly Awards committees who gave us the props!

Related:  What is Drupal? ... in 57 seconds
Categories: Drupal blogs

Drupalcamp Colorado - Looking Back

Thu, 07/02/2009 - 16:52

Drupalcamp Colorado 2009 has come and gone. The event garnered over 200 participants - at least half of which came from out of State. Over 40 sessions (if you include BOFs and the opening and closing sessions) occurred over the two days ranging from pure business to the highly technical. Ubercart was heavily presented with Ubercamp partnering with Drupalcamp. The camp was followed by a media sprint.

pingVision presented in quite a few sessions:

I personally took photos and video in and out of sessions and drafted notes at the panels I attended. Poring over them this last week for posting online had me thinking how extraordinarily good the sessions were this year. The Flickr feed is filling up with photos from several of the participants as well. If you have photos from the event on Flickr, please tag them drupalcolorado!

The event has re-energized me, encouraging me to reengage my community projects head on. It has me getting excited for Drupalcon Paris and the opportunity to interface with a larger segment of our community. Finally it makes me think about where this event will be next year. Perhaps it will have 400 participants with worldwide attendance?

Thank you to the organizers and thanks to everyone that came. It was a great event that pingVision was delighted to sponsor.

Categories: Drupal blogs

We're doing several presentations at DrupalCamp Colorado 2009 this weekend

Tue, 06/23/2009 - 12:50

DrupalCamp Colorado 2009 is happening this weekend in Denver. (Registration is still open!)

And we at pingVision have been preparing several presentations.

For programmers and developers wanting to get into Drupal development but are unfamiliar where to start, Lead Developer John Fiala is presenting the basics of Drupal Module Development:

Views, Panels, CCK, token, and the rest are great for getting most of any project done, but sometimes you need a little custom work to get the last 4% of your needs covered. When that happens, it's time to break out a code editor and write your own module.

[This session covers] how to set up a blank module, the usual basic hooks that you will implement, what to watch out for for security, and ideas on how to nudge and override Drupal to do what you need without having to kill a kitten, aka hack core.

If the Drupal API is new to you, this will be a session not to miss!

That's not all we're covering regarding the Drupal API. Senior Developer Ben Jeavons will be presenting on Drupal Web Services:

In this session I'll talk about how you can use Drupal as a web service for providing and communicating data for third-party consumption. I'll talk about some of the available solutions such as XML-RPC and RESTful applications. This won't be an overview of the properties of web services but rather a discussion and demo on implementing web service endpoints and clients with Drupal.

Ben will also be on a panel on Drupal Security.

For themers and front-end developers, Lead Themer Al Steffen and Senior Developer and Themer Matt Tucker are presenting on the Studio theme, which generated much attention last week at Design4Drupal:

Studio base theme gives a whole new array (pun intended) of capabilities for themers. By re-structuring some of the key aspects of the theme system such as preprocess functions, and keeping attributes as arrays until output, Studio provides a sustainable theme, making it easier to make incremental changes without the need to create additional template files.

People wanting a deeper understanding of the Drupal theming layer will want to see Matt Tucker's other session, Preprocess functions: what, why and how:

Template files are meant to be simple, with simple php conditional logic, and minimal code. As a general rule of thumb, logic should be placed within preprocess functions and the output assigned to variables which are then printed within the template file....

...Preprocess functions simplify a theme drastically by greatly reducing the number of needed template files.

This session will be highly focussed on samples, providing 'real-world' examples of how preprocess functions can be utilized to save time and energy while theming.

On the project management side, COO and Co-Founder Katherine Lawrence will be presenting Project Management: 'Agile' is not 'cowboy' spelled backwards. In it, she'll be sharing some of the things we learned as a company over the past four years handling dozens and dozens of projects.

In Project Management, what elements are critical? How is success measured? What are the benefits of well-executed Project Management to the developer and client?

How can a firm increase productivity without long hours and cost over-runs? Over the last four years we tried a range of approaches in this ever-evolving area.

These principles apply across the board, from the one-person shop to the larger firm.

I will be doing a presentation on Functional Interactive Design, and why good design is more than simply aesthetics:

Ever walk up to a door and pull on the handle, only to discover the door is push-only? Do you really know how to operate your clock-radio? Doors may be pretty, clocks may look cool, but when we have to actually use them, the measure of their design changes.

Same with websites. A website may be pretty at first blush, but can you find what you're looking for? Can you do what you want to do? Can you even figure out what you're supposed to do?

This presentation is on functional design concepts and how they apply to websites and web apps.

I will also be leading the closing plenary, where I hope not to do the talking at all — rather facilitating a general discussion where we'll all talk about what happened, what was great, what's happening next, etc.

And that's not even close to all that's happening at DrupalCamp Colorado this weekend!

We have three concurrent tracks of sessions presented by Drupal experts and enthusiasts in multiple topic areas!

We have Übercamp 2009!

We have a sponsored Saturday night party overlooking downtown Denver!

We also have stickers and t-shirts!

And lots and lots of Drupal!

So far, as I write this, 172 people have registered to get their Drupal on at DrupalCamp Colorado 2009. Join us!

Related:  Excitement, ideas and new designers' focus coming out of Design4Drupal Camp Introducing the Studio Theme Pack Supporting Drupal with a Platinum Sponsorship of DrupalCamp Colorado 2009
Categories: Drupal blogs

Excitement, ideas and new designers' focus coming out of Design4Drupal Camp

Fri, 06/19/2009 - 16:21

Last weekend, MIT was host to a somewhat unusual Drupal event:

Design4Drupal, where some 160 designers and interested developers gathered to talk about designing and theming for Drupal.

The Frank Gehry-designed Ray and Maria Stata Center was somehow appropriate to house a camp focused on Drupal design and theming, which often can feel like an adventure through unexpected curves, angles and walls.

This was one of a series of planned events to change that.

From the start, you could tell that this was an event different from other DrupalCamps and DrupalCons. For one, nearly all of us attending are designers. The percentage of women attendees was highest of any Drupal event I know of. And the energy was all about the design side of Drupal.

Most of the sessions fell into one of two general topic areas:

  1. How to theme for Drupal as it is; and
  2. How to make Drupal easier and better for theming and design.


Both topics are about beauty: the beauty of a successfully executed design, and the beauty of clean mark-up, clean css, clean output. For me, the greatest excitement came from seeing three different endeavors come together in a synergistic way.

Studio + Skinr + 960 = beauty inside and out

One of the wonderful aspects of working in open source is that you often find unexpected opportunities for collaboration and coordination of efforts to make the open source project better. This seems to have happened at Design for Drupal, as people weighed the exciting possibilities of the Studio theme, developed by our own Al Steffen and Matt Tucker, the Skinr module and the 960 theme.

Studio theme streamlines preprocess


Matt Tucker pulled together overnight a presentation on the Studio theme (that he and Al Steffen recently released), which got some buzz the day before in Jacine Rodriguez's presentation on the Skinr module (see below).

One thing that Studio does so elegantly is provide a method for handling attributes. As Matt Tucker said in his presentation, it's crazy to have to edit .tpl files just to add a class to something. It's especially crazy when you have 15 or 20 variant .tpl files for something such as nodes. To add a class, you have to go in and edit each and every .tpl file. It doesn't need to be that hard.

Skinr module's GUI for theming


I missed Jacine's presentation on the Skinr module, but the buzz coming out of it was palpable. There was no question that people had seen something very exciting to make modifying and customizing mark-up every easy to do.

960 grid system on Drupal

Nathan Smith, creator of the 960 grid system, did a fabulous presentation on how his prototyping system can make the flow from design to implementation easy, balanced and, yes, beautiful.

Then Todd Nienkerk presented his an implementation of the 960 grid into within a Drupal theme that was developed by Joon Park (aka "dvessel") and is co-maintained by Todd. [Edited for accuracy. Thanks, Todd!]

Three great tastes that taste great together

The potential of the idea of using NineSixty as a subtheme of Studio is intriguing. Such an approach would afford the benefits of both. (Currently, however, one would have to either hack or fork NineSixty to make it work.)

Adding Skinr promises to making design and theming work even easier.

Patching Drupal core


Some of the efforts at Design4Drupal were centered around improving Drupal's html output to make it easier to theme. Yes, contrary to what some developers seem to believe, it is possible to have too much mark-up -- way way way too much. Extra divs, spans, boatloads of classes and IDs, all that go way beyond what is necessary to target a particular element and can actually make it harder to do theming. Cascading stylesheets cascade.

There has been some push-back on the clean-html effort, so I'd like to offer a very rough analogy:

If Drupal's output standards were applied to PHP coding standards, I can only imagine the heated debate we'd be seeing in the Drupal development email list – that is, if any developers stuck around.

(See Moshe Weitzman's post discussing an aspect of this problem.)

We can do better in the html output. Just because Drupal is a complex CMS and framework doesn't mean the HTML has to be complex. "ID and classitis", as Moshe calls it, is just not necessary.

Let me be clear: This is not need to be an either/or thing. Sure, themers will often need a bit of specific mark-up to be able to target specific elements. But only just enough. Extra stuff just starts to get in the way. Not only that, it's usually un-semantic.

And just wait until we start throwing RDFa markup on top of it all!

Because of theme inheritance, extra-granular HTML markup with extra-just-to-be-sure classes and IDs can be generated in a base theme. I hope the voices of HTML and CSS expertise are not ignored or dismissed. Theming -- what is often called "front-end development" -- is not just an art, it's a craft, and at the heart of that craft are HTML and CSS. We live and breathe this stuff. Our voices matter.

Patches in the queue

And these are in addition to some exciting efforts pre-dating the camp:

All these are very encouraging, positive developments in the effort of making Drupal markup beautiful and more themer-friendly.

Making contributing themes easier

On another front, this week, ceardach started a new module project, Simple Committer:

The initial goal of this module is to simplify the process of committing a theme to Drupal's CVS. For a HTML/CSSer, CVS is too much of a barrier for contributing new projects, and we would like to lower that barrier as much as possible.

During Design 4 Drupal, we had discussed that we could create a means to allow a user to upload a zipped file and it would automatically (or manually if we need to....) commit the contents of the file to Drupal's CVS.

We should keep the development path open, and plan a long term goal that is not CVS, Drupal and theme specific. For the first 30 days, we can hard code Drupal/CVS, but keep in mind during our development that we'll eventually want to make this flexible so the project can grow with ease.

This idea was given voice by Jay Batson of Acquia [disclosure: pingVision is an Acquia partner] in his second-day keynote as part of an effort to make it easier for themers not familiar or comfortable with CVS to contribute their work to the community. This was part of a larger vision he shared:

A Drupal designer community site

Designers as a rule tend to be different personality types than developers. For one thing, designers strive to create unique, one-off works, not designs to be used and reused on all kinds of sites. For the most part, designers work alone and don't collaborate on design work (though the best are open to collaborative feeedback and constructive criticism). And, almost to a rule, designers are not comfortable in the programming world. A designer may be quite comfortable working with (x)html and CSS, sure, but PHP? SQL? Not likely.

Jay's idea is to foment a constructive, nurturing community space where Drupal designers can talk about design, share comps of what they're working on, discuss useful design tools and approaches, debate techniques, and generally help each other as designers.

Where this community ends up living -- if it happens -- was left open last weekend, but today Jay announced the launch of http://design.acquia.com, which trumpets "Drupal is Beautiful!".

Jay points out some of the challenges designers at Design4Drupal identified:

  • A really, really well done, useful, base theme in core. (But there is debate about what it should contain - all possible CSS, or none?)
  • When displaying a base theme (on Drupal.org), indicate the sub-themes derived from the base theme (and vice-versa). (Can people just start to do this in the description of the theme, until it gets automated, please?)
  • ID & class adding facility per menu item (currently in queue)
  • Put the skinr project - or something like it - into D7 core. There was also some growing affection for the Studio theme pack
  • If Drupal emits markup, it should be themable. (This, apparently, isn't always the case now.)
  • Drupal.org has a security team, and an ops team. Should there be a design team? What would its authority / charter be?
  • A way to mark a contrib issue as having a design problem - not just a "user experience" problem (which is actually a completely different thing in the eyes of designers.) (This involves a change to the Project module.)
  • Guidelines for developers on when to do X with design / output to make the lives of designers (who have to deal with a module's output) easier
  • Modules should list what markup it is going to emit that needs styled. Preferably list this somewhere _not_ in the module code - e.g. on the module's config page, or ..., so that designers don't need to shift into command line mode to discover this info.
  • For every module, should there be a description of relevant design info or assumptions?
  • How do we get a critical mass behind making all these changes? Do it on d.o? The systems aren't set up there well, but there is where coders (who may need to make changes) live. Do we create "community" among designers outside of d.o where we can change and modify systems quickly? Does this Balkanize efforts, or accelerate them?

I find the idea compelling.

All volunteer effort

Huge piles of thanks and hugs go out to Susan McPhee, who was at the heart of organizing this event, Morten, who has been championing the designer perspective in the Drupal community, and the fabulous D4D sponsors.

More: on Design4Drupal on IRC

Also check out the IRC chatroom #drupal-design on irc.freenode.net.

on UX

And all this is in addition to the Drupal 7 usability improvements being spearheaded by Mark Boulton and Leisa Reichelt. A UX sprint is about to happen in Utrecht, The Netherlands. All over the world, Drupal's design is getting all kinds of love and attention.

Related:  Introducing the Studio Theme Pack
Categories: Drupal blogs

Disallow node discovery by ID

Mon, 06/15/2009 - 14:40

Recently I wondered if viewing a node via its internal path could be disallowed, making it accessible using a path alias only. With hook_menu_alter(), a router item's page callback can be changed to our own function that will check if the requested path is internal or not.

<?php
function hidenid_menu_alter(&$items) {
  $items['node']['page callback'] = 'hidenid_check';
  $items['node/%node']['page callback'] = 'hidenid_check';
  $items['node/%node/view']['page callback'] = 'hidenid_check';
}

function hidenid_check($node = NULL, $cid = NULL) {
  $path = $_REQUEST['q'];
 
  if (strpos($path, 'node') === 0) {
    drupal_not_found();
    return;
  }
  return node_page_view($node, $cid);
}
?>

You might be asking what's the point of this? Good question! I wondered how such a thing could be accomplished after dreaming up a schedule service built on Drupal. I didn't want to use a node access control, just restrict visibility with obfuscated URLs. Without such a solution a curious visitor could still view posts at node/NID. The above solution is a proof-of-concept, I haven't deployed beyond a prototype so there are likely to be implications I don't know about.

We can't use the PHP superglobal $_GET because Drupal overwrites 'q' in drupal_init_path(). In the above code example the $node argument defaults as NULL in hidenid_check() for the case the requested path is 'node', because no page arguments are set for that callback.

Of course, for practicality there must be an alias or the node cannot be viewed. That's where the core path module and Pathauto helps, perhaps altering the node form to require the alias field as well. And you could always allow user 1 or certain roles to view it via the internal path.

Categories: Drupal blogs

Supporting Drupal with a Platinum Sponsorship of DrupalCamp Colorado 2009

Fri, 05/22/2009 - 16:40

Drupal is not generally taught in schools. Open source is largely off-topic in universities. Many, if not most, of the leaders in open source, including Drupal, are self-taught experts who bootstrapped their learning process. This doesn't mean they aren't bona fide computer scientists and programmers. On the contrary. But Drupal books aren't on many syllabi.

So we seek to grow the Drupalverse one event at a time, through monthly Drupal meetups ... and, once a year (and hopefully more frequently in the future), collaborating with other sponsors and several volunteers on throwing DrupalCamp Colorado, a two-day, hands-on Drupal conference/meet-up/sprint for people of all levels and all disciplines – designers and coders, website administrators and sysadmins, business people and freelancers, community leaders and entrepreneurs.

When: June 27-28
Cost: only $20

At any hour over the weekend event, there will be simultaneous presentations on topics including development, design, theming, site building, community and business issues, all relating to Drupal and the cutting-edge interwebs 'verse where Drupal lives and breathes.

Plus there will be a lot on e-commerce, because this year DrupalCamp Colorado is combining with Ubercamp, the annual Ubercart conference!

And all these presentations are aimed for audiences ranging from the novice to the expert.

Also there will be "birds of a feather" sessions (BOFs), ad hoc gatherings on a smaller scale where people can explore what interests them with like-minded folks.

We're expecting over 200 attendees!

If you are working with Drupal in any way, or are just curious about it, DrupalCamp Colorado 2009 is an event not to miss! Sign up now! It will be the most productive 20 bucks you ever spent.

(Want to help? Start here, and join us in IRC at #drupal-colorado.)

Related:  DrupalCamp Colorado 2008 DrupalCamp Colorado and LinkedIn pingVision presenters at DrupalCamp Colorado 2008
Categories: Drupal blogs

Gold Horizon Award for Pregnancy.org

Thu, 05/21/2009 - 16:55

This week we learned that we won a Gold Horizon Interactive Award for Pregnancy.org. The Horizon Awards hold a special place in our heart as our first award we ever won was a Horizon Award. This one makes our eighth Horizon award – and third gold (the others were PopSci and BlogHer.

Our thanks go out to the Horizon judging committee!

Related:  pingVision wins five Horizon Interactive Awards pingVision wins design awards Horizon Awards PopSci.com relaunches on Drupal New BlogHer.org launches beta
Categories: Drupal blogs

Drupal wins CNET Webware 100 Award ... again!

Tue, 05/19/2009 - 18:37

For the third year in a row, Drupal has won a CNET Webware 100 Award, which is, we feel, a strong indication of the power, resourcefulness and creativity of the Drupal community.

Congratulations, Drupal!

Related:  Drupal CMS wins CNET Webware 100 again!
Categories: Drupal blogs

We've moved! (See our new space at the Drupal Meetup tonight!)

Wed, 05/13/2009 - 11:48

Last week we moved into new offices...


...upstairs from Techstars (@techstars) [who can nourish our minds]...

...and Sidney's Coffee Shop (@sidneyscoffee) [who can caffeinate our brains].

Once again, after nearly two years, we're all on the same floor, in the same space. Don't ever underestimate the value of that!

We made the move over the first weekend of May. In the weeks before, the space was being prepped -- walls torn down, paint thrown up, carpet thrown across -- transforming it from the forlorn abandoned space we could work with into a sharp, clean, bustling space we could work in.

Meetup tonight


Tonight we'll be hosting our first Drupal User Group Meetup in our new offices. All are welcome!

It starts at 6.

Free pizza and (soft) drinks!

For those traveling by bus, we're now catty corner from the main downtown Boulder bus terminal.

We're in the big tall ugly building with the pastel panels on the side that decades ago some architect thought would look cool. pingVision is located on the Mezzanine level.

Follow the Druplicon!

Farewell to the Pine Street home

Just over 29 months ago, we moved into the building at 14th and Pine. All we had was Suite 1. After bootstrapping the company from a livingroom office, we finally had our own space: 4 rooms plus a full bathroom.

The building was slated for demolition in six months or so, to make way for a new development, so we got a great deal on the space -- perfect for a start-up!

As we grew, we took over more of the building, one suite at a time, until we had five separate suites -- each with multiple rooms, each with separate utility bills, each with a full bathroom (including bathtub and shower). It was nice to have the room, but it was hard to have everyone scattered across three floors, in separate small rooms.

A lot has happened in these walls.

...Meetups, a DrupalCamp, oodles of client meetings, getting snowed in, internal moves, hirings, architecting, running cables, mounting whiteboards, designing, coding, theming, and lots and lots of laughter.

We take away many fond memories.


So now we move on to the next phase, with brighter horizons and better views of the Flatirons, remembering that place that was our home for over two years.

More photos on Flickr.

Categories: Drupal blogs

Introducing the Studio Theme Pack

Tue, 04/21/2009 - 09:24

A couple weeks ago, Matt Tucker and I gave some folks at our local Drupal users group a preview of our recently contributed theme pack called Studio. We're announcing the official 1.0 version release of the theme and we felt it would be interesting to provide some background.
<!--break-->

A bit of history

I began working with Drupal back in January 2007 as version 5 was just coming out. My comfort level and skills increased in the theming layer over the course of time. These experiences, married with community input, identified new elements that we thought beneficial to a base theme. This theme was contributed to the community as Hunchbaque.

Hunchbaque became pingVision's standard base theme through Drupal 5's life cycle. It provided the company with time savings by avoiding repetitive efforts on each project. There were, however, limitations. The most significant being development of a brand new version of the theme for every site.

As Drupal 6 approached a stable release, I began porting Hunchbaque. I approached this assuming I could leverage the relationship between base themes and sub-themes. However, as I continued development, I found I could do so much more. Early versions, in Drupal 6, illustrated new flexibility that didn't exist in Drupal 5.

I decided that to take full advantage, it would be best to start from scratch. The Studio theme pack was created. The theme has grown from a simple theme to a full pack of themes. They include Paint, a simple three-column layout; Workspace, an administrative theme; and, soon, a mobile theme.

After several months of maturation and help from co-themer Matt Tucker, we feel it is time to release it to the community. So with the history lesson over, it is time to tell a little more about what this theme contains.

The usefulness of base themes

The Studio set of themes is intended to provide a starting point to quickly begin work on your custom themes. It provides a theme called Canvas as a base that does not get altered and can be upgraded. It should provide a good foundation to quickly get started on a new and original look for a site. The other two (Paint and Workspace) are provided as examples of how to build off of it.

You may be wondering why one should even bother with a base theme. It is a simple matter of preserving reusable code. For many of the themes we have done at pingVision there was a common set of code that every theme contained. Previously this was handled by starting with our in-house theme and modifying it as needed. Unfortunately, this also meant we had to role any useful bits we devoloped in individual projects back into our base. Now that there is a base theme that is exactly the same from project to project, we can simply commit the code and not worry about conflicts.

Cleaning up the theme

The first thing that is possibly noticed is that the template files are now placed in a subdirectory. Not only that, but we have decided to break this up into "custom" and "overrides" directories. This is best illustrated by looking at the CVS repository. We found this made finding needed files easier for us and, best of all, does not require any extra declarations in the theme. This is a Drupal core functionality in version 6 and our arrangement is merely a matter of taste. Feel free to arrange these files as you wish in your subthemes.

Next on the list of generally messy parts of the theme is the template.php. Through the course of building any theme, this gets filled up with a lot of logic in preprocess and theme functions. The simplest way to get this file back to a managable state is to break up the file. We chose to do this a couple different ways.

The biggest culprits that were filling up the template.php file were the many preprocess functions. These got rather large when building out the base classes for the theme and most could justify being a file themselves. For this reason there is a folder named "preprocess" in canvas and the subthemes. In here are several .inc files named for their related hooks. We also wanted to automate the process of including these files so that we did not have to tell PHP to include each manually. The following snippet found in Canvas' template.php allows for this:

<?php
function canvas_preprocess(&$vars, $hook) {
  if(is_file(drupal_get_path('theme', 'canvas') . '/preprocess/preprocess-' . str_replace('_', '-', $hook) . '.inc')) {
    include('preprocess/preprocess-' . str_replace('_', '-', $hook) . '.inc');
  }
}
?>

This function is the generic preprocess function that can handle any hook in Drupal. The function checks in the preprocess folder for a file named after the hook. If that file exists, it is loaded into the system. Unfortunately this functionality does not translate to subthemes well. The plus is that it is easy to duplicate for your own themes by copying the above code into your own theme's template.php and changing the word "canvas" to the name of your theme.

The next step in cleaning up the theme is to offload the bulk of custom theme functions and overrides to separate files. Unlike preprocess functions, normal theme functions rarely justify having an individual file for each one. This is why we broke them up into custom theme functions and overrides similar to the tpl files. These files can be found in the folder names "functions".

We take what some would consider nonstandard ways to include these files and that is by overriding the definition of theme function in the theme registry. This is done by simply defining a "file" key in the hook_theme() function. For instance, we wanted to remove the containing <div /> from the theme_item_list(), so we re-register it like so in the Canvas theme:

<?php
funtion canvas_theme() {
  return array(
    'item_list' => array(
      'arguments' => array(
        'items' => array(),
        'title' => NULL,
        'type' => 'ul',
        'attributes' => NULL,
      ),
      'file' => 'functions/theme-overrides.inc',
    ),
  )
}
?>

Even though this is what some would consider overkill, we like this for a reason other than using the "file" declaration: it gives us a functional list of overridden functions.

Additional defining attributes

There are several ids and classes declared to accommodate many of the situations we have found to be needed in the majority of sites. Logged in status, section designators, types of nodes, etc. With the way these are all added, it should be very easy to add more of your own or even remove some. This system is also upgradeable to accommodate new versions of the Canvas core. Simply add the $attributes variable to the container to the containing element of your template.

In the process of providing all these classes and ids, We found the core drupal_attributes() function inadequate. We had to perform and extra step to format the array of classes into a string since drupal_attributes() only handles strings for the values. For this reason we created theme_render_attributes(). It is very close in functionality to the original function except that it can accept an array or a string for a value.

The value of this expands beyond simple classes and ids also. One example of this is RDFa support in a theme. Details on how this would work is beyond the scope of this post, but it is something we hope to cover in the future.

Stylesheets for Internet Explorer

There is also support for Internet Explorer specific stylesheets. There is a good example on how to use this in the Paint theme's preprocess-page.inc.

<?php
$vars['ie_styles'] = array(
  'lte IE 6' => array(
    'screen' => array(
      path_to_theme() . '/css/lte-ie6.css',
    ),
  ),
);
$vars['styles'] .= theme('ie_styles', $vars['ie_styles']);
?>

The above process is pretty straight forward. We are constructing an array consisting of a conditional, media type and the path based on the Drupal root. This will allow for multiple stylesheets with similar properties to be grouped together. To get the stylesheets into the page output, simply render them with theme_ie_styles() and append it to the end of the $styles variable.

Region theming

There is now a theme_region() function. This provides a region.tpl.php that you can use to customize and wrap your regions how you wish. No more need to put extra if statements in the page.tpl.php files in your theme. If you need different markup for a certain region, just add a region-[region name].tpl.php to your theme and wrap as needed.

As an example of how this can clean up a file, look no further than Canvas' page.tpl.php. There is less logic, but all the appropriate wrappers are in place. We feel this creates a file that is easier to parse for the themer.

Cutting the fat

In addition to all of this, we have overridden theme functions and template files to trim out as much of the markup as possible. Currently this is limited to major themes in core Drupal and there are many more on the docket to override. In time this will be expanded even further to cover popular modules like Views and CCK.

How do I use this?

To begin using the capabilities of this theme, all you have to do is add base theme = canvas to your theme's .info file. Simple as that. If you wanted to have more of a structured start, you can make a copy of the Paint or Workspace themes and change all instances of the themes name in the included files. As an example, this is the beginning of the Paint theme's .info file:

name = Paint
description = This is a starter derivative theme of Canvas. If you would like to make your own custom theme, copy this one and change the name of the folder and .info file then provide your own information in the .info file.
engine = phptemplate
base theme = canvas
version = 1.x-dev
core = 6.x

Now, we must stress that making a duplicate is the proper method for this as we would hate for you to accidentally overwrite your hard work in an upgrade to the theme system.

Conclusion

One of the questions that will be asked is "How does this compare to the other base themes available?" This is a theme that grows and evolves with our company and it fits with what we do. This industry and technology is evolving at a fast pace. There are always new ways to implement various aspects of a site and we want a theme that can change as fast as we can. In the end there will be a lot of similarities between this and other themes out there in the wild. On the flip side, we feel there are enough differences to justify a new contribution to the community.

This concludes our not-so-brief rundown of the theme. In the future, we will be posting some more posts and videos on how to use it. There will also be more information on upcoming improvements later.

[edit] Studio was also presented at Design For Drupal in Boston and DrupalCamp Colorado in Denver. Slides from those presentations are available in pdf here

Related:  Studio theme pack Hunchbaque Hunchbaque: Ugly, Yet Beautiful Matt Tucker
Categories: Drupal blogs