Last week I jumped on an opportunity to do some Drupal crusading in my department at UC Berkeley. We are standardized on VB.NET, but I sensed an willingness to consider alternative solutions for an ailing website that offers very light CMS functionality. I don't know of any framework comparable to Drupal that exists in the .NET world. If you do, comment here and let me know! The functionality already present in Drupal 5.1 allowed me to bring up a fully functioning prototype in my free time.
The Challenge: The existing crippled website (written by a UCB student volunteer a few years ago) provides simple websites for staff organizations at UCB. One user from each staff organization can login and update website content. The basic content they create is Mission, Officers, Events and a Contact Us form. When they update their sites, their new content enters an approval queue and is reviewed by a site admin who decides whether or not to publish it. The site was coded quite insecurely, and as the caretaker, I ultimately had to disable all of the content update functions. Here's an
example staff organization page on the old site.
The Drupal Solution: If you have some knowledge of Drupal, the following ramblings might be of some use. If you don't, and you insist on reading this, you are one odd bird. It might be helpful to take a look at one of the Staff Organization websites that I'm describing below.
I used Custom Content Types
(CCK), Drupal Views
(not to be confused with an SQL view - although the concept is the
same) and Panels to
duplicate this functionality in Drupal. Since Drupal already offers a
great Contact
Form right out of the box, I did not have to recreate that
functionality. I also improved on the old site by defining a Role
for each organization. This way multiple Drupal users could be
allowed to edit content for one organization.
CCK: I created content types for Mission, Officers, Events and Logo (well, I just used the existing Image content type for Logo).
Views: This is where it got interesting. I needed to pull all of the content for an organization into a view. I wanted to use one generic view for every organization's website. Drupal allows you to pass multiple arguments to a view. One of my arguments would be the role name associated with the organization. This would allow me to gather all of the content created by users in an organization's role and display it. (Note: I had to apply this patch to make role names available as arguments to a view.)
How to create "tab" functionality in a Drupal view. If you look at the page on the old site (above), there are links that act like "tabs" allowing you to move between Mission, Events and Officers. One solution would be to create three Drupal views - one for each tab. But wouldn't it be nice to create one view that does it all? This is where my second view argument came into play: In addition to Role, we will pass and argument indicating what "tab" (Mission, Events or Officers) the user has clicked. Let's call this our "type" argument. To make this all work, I needed to dynamically generate the href for each tab link. We know that the Mission link will always need a type argument that evaluates to "mission." It will also need an argument that evaluates to the role associated with the organization. To achieve this, I wrote custom PHP in the Header subsection of the Page section in the Drupal Edit View form. Further down this form there is a section which allows you to write custom argument handling code. There you can reference an array called $args to get all of the arguments that have been passed to a view. I could not use the Argument Handling Code section because my code has to be in the view Header. As far as I can tell, you don't have access to $args in the Header section. For this reason I had to parse the URL (which is accessible in Drupal as $_GET['q']). There may be a better way to accomplish this (Comments invited!). Here is my code for the Header section:
<?php
$getargs = split('/',$_GET['q']);
//print_r($getargs);
$orgarg = $getargs[1];
?>
<br>
<a href ="http://stafforg.nwood.org/stafforg/<?php echo $orgarg;?>/mission">Mission</a>
<a href ="http://stafforg.nwood.org/stafforg/<?php echo $orgarg;?>/officer">Officers</a>
Contact (see link at left)
<a href ="http://stafforg.nwood.org/stafforg/<?php echo $orgarg;?>/events">Events</a>
<hr>
<p>
Different numbers of different nodes in one view: Something else to consider! An organization can have multiple Officers and Events but only one Mission and Logo. But there is nothing to stop the users from uploading multiple Logos and Mission statements...what to do? Well, a Drupal view allows you to set number of nodes to display on a page. You can also define a sort order for these nodes. What I want is to only display the latest Mission and Logo. The "latest" part is easy: I added Node Created Time to Sort Criteia and specified Descending in the Order select menu. Now for the tricky part. When my type argument is set to Mission or Logo I only want to allow one node to display. However if the type is Event or Officers, multiple nodes can be shown. In the Page section there is a Nodes per Page setting. Specifying "1" here would make the node limit one regardless of the type argument. The solution is to create custom argument handling code (in the section mentioned above) and set this limit programatically:
if ($args[1] == 'mission') {
$limit = 1;
$use_pager = false; //this prevents "previous, 1, 2, 3... next" from appearing at the bottom of the view.
}
Panels: I fudged a little in the description above. Logo is actually in a separate view which is married to this one using a two column Panel. I don't think I'll go into that right now. It's not too hard to figure out.