Notes on Drupal and Development by stariya


									Notes on Drupal and Theme/Module Development
Created 09/29/07
Updated 10/07/07, Updated 10/15/07, Updated 10/21/07, Updated 10/30/07, Updated 11/03/07, Updated 11/12/07
Updated 11/21/07, Updated 11/26/07, Updated 12/13/07, Updated 12/26/07, Updated 01/02/08, Updated 01/10/08
Updated 06/13/08, Updated 08/28/08, Updated 10/24/08, Updated 11/09/08, Updated 11/30/08, Updated 01/02/09
Updated 02/05/09, Updated 02/22/09, Updated 03/07/09, Updated 05/06/09, Updated 07/12/09, Updated 09/17/09
Updated 11/27/09, Updated 12/18/09, Updated 12/28/09, Updated 03/06/10, Updated 04/17/10, Updated 07/18/10
Updated 08/15/10, Updated 01/12/11, Updated 05/09/11. Updated 05/26/11, Updated 06/17/11, Updated 08/24/11

Drupal (termed “community plumbing”) is an open-source platform and content management system for building
dynamic web sites offering a broad range of features and services including user administration, publishing
workflow, discussion capabilities, news aggregation, metadata functionalities using controlled vocabularies and
XML publishing for content sharing purposes. Equipped with a powerful blend of features and configurability,
Drupal can support a diverse range of web projects ranging from personal weblogs to large community-driven sites.
It is frequently used by schools, museums, churches, civic organizations, and many other communities. One of the
flagship deployments is at See our document “Notes on Drupal Sites”.

Drupal has a basic usage model of submitting entries, supporting revision histories, managing users, selecting
themes, and organizing entries into categories, menus, etc. It supports uploads as well as basic HTML content. It is
written in PHP and uses MySQL. It has a developer community that has created upwards of a thousand plug-ins.

The primary difference between Drupal and blogging tools like WordPress is that Drupal is more like an application
building environment for content-intensive applications, with an underlying layer that can be extended to perform
specific functions. It has aspects of shared content management, permission management, display management,
navigation, menus, and filtering that are used to build blogging, polling, and other types of capabilities for your site.
Blogging is only one application of Drupal. Also, Drupal has extensible content types and presentation generation

There is a demo of the current version of Drupal available at: Note however, that
the demo provided is a bit simplistic, and doesn‟t have all that many modules turned on, and in fact doesn‟t have any
modules that are not in the standard deployment.

Drupal 7 was released in early 2011, and the current production version is 7.7 released on July 28, 2011. The
production release of version 6 is 6.22, released on May 26, 2011.

New features in the 7.x series include a new admin screen, integration of many parts of the CCK and Views modules
for better extensibility, and many new usability and installation improvements. See our document “Notes on Drupal

New features in the 6.x series include a new API for database schema within modules, better support for
internationalization, better theming facilities, and triggers that are run when content changes. The major usability
improvements include the addition of drag and drop ordering of blocks and nodes in lists (useful for quickly
assigning block to display areas on the themes), improvements to the menu and filter format administration
interface, plus integration of the ThemeSettings_api module.

For many years, Drupal has been well-known in the open-source CMS community, and has won a number of
community awards, including the Packt Publishing award for “Best Overall” Open Source CMS for 2009, 2008, and
2007. See In 2009 and 2008,
Drupal gained publicity in the IT community beyond the open-source community. The most visible example was an
article in Information Week in which Drupal was shown on the cover. See

Page 1 of 55
The Drupal download is free, and is about 1061MB in size (about comparable to recent versions of WordPress). It
is compatible with PHP 5.2 and later.

Features and Community
    Completely database-driven site engine
    Fully customizable layouts including placement of blocks onto left and right sides
    Content can be organized as stories, pages, polls, blogs, events, etc.
    New content types can be defined
    Navigation hierarchy can be customized

Extensive Administration:
     Change order of objects including news, FAQs, articles etc.
     Organize site and content
     Uploading of files such as PDF‟s, DOCs, XLSs, GIFs, JPEGs, etc.

    There appears to be a large community of developers, producing themes, plugins, modules, and more.
      We‟ve even found that some of the favorite themes for WordPress have been ported over to Drupal.
    There are entire organizations using Drupal as the basis for value-added community support tools. One
      example is Lullabot.
    There is also Acquia, a company created by the Drupal development founders, to support commercial
      applications of Drupal, as well as to provide some standard distributions with the most common modules
      and themes.

Evolution of Drupal:
     Version 7.x (released in early 2011) has major improvements in usability, administration, and deployment.
     Version 6.x (released in early 2008) has major improvements in support for database schema management,
        internationalization, improvements to the documentation, improvements to the theming engine, more
        support for JavaScript in the client-side code, and a new event/trigger model that can notify modules when
        there are changes are made to content.
     Version 5.x (released in late 2006) had major improvements, including an installer, requirement checking
        for modules, a reorganization of the administration pages and file structure, a light-weight CCK, inclusion
        of jQuery and much more. It went a long way to toward making Drupal be easier to install and easier to
        enhance. The facilities for extending the content types have been greatly changed. The template engine for
        themes has been standardized, which helps focus on the community on one technology so that effort can
        focus on the visual development.
     Version 4.x (released in 2005) appeared to be the first version that caught on widely, including the
        development of third-party themes and modules.

Examples of Use:
    Indianapolis Museum of Art (see This project has a custom interface, and a
       number of custom modules.
    The Rake (see This project has also completely changed the interface, and
       has content of thousands of nodes. The article on the Drupal web site provides details regarding the
       organization of the site and the modules used.
    There is a large set of examples at

The most important resource is the online Drupal community site, Developers typically use
the API documentation in the „books‟ of the site. It is very complete, though you are on your own for finding
things, as compared to the books below which tend to have an organized approach.

Page 2 of 55
Another resource is third-party pages and even videos or podcasts, such as those from and

The first book on Drupal 7 is “Drupal 7” by Todd Tomlinson. APress, June 2010, 315 pages. List price $49.99,
Amazon price $44.55, not available used yet. This book covers the standard features of Drupal core modules, using
the Drupal 7 UI, and then provides information on additional modules such as those for social networking and e-
commerce. The discussion in the “Using Drupal” book is a bit more detailed, but has the Drupal 6 UI.

“Using Drupal” by Angela Byron, Heather Berry, Nathan Haug, and Jeff Eaton. O‟Reilly Press, December 2008,
490 pages. List price $44.99, Amazon price $40.49, used from $36.39. Rated 5 stars on Amazon. This is the first
Drupal publication by a major publisher like O‟Reilly, and reflects the growing interest in Drupal today. This book
is largely a usage and administration guide, comparable to the Mercer books, but is a step up in clarity of writing,
and usage of current modules and examples. It covers over 30 important modules, and about half a dozen themes. It
is organized into a series of case studies, each selecting relevant components and applying them. The case studies
include content management, wiki-building, and ecommerce. The book covers some about theme customization and
structure of themes, but it doesn‟t cover module development. There is a web site that goes with the book, If you only buy one book, buy this one.

“Front End Drupal: Designing, Theming, Scripting” by Konstantin Kafer and Emma Hogbin. Prentice-Hall PTR,
April 2009, 456 pages. List price $39.99, Amazon price $26.33, used from $22.00. Rated 4.5 stars on Amazon.
Com. Very similar to the O‟Reilly book as it covers everything from installation to theming and scripting. But it
uses a different set of themes and modules, so it gives you a different perspective.

“Drupal in Action” by Ezra Barnett Gildesgame and Greg Knaddison. Manning Press, 2010. Not yet released, but
there is a MEAP edition. A hands-on tutorial that gets you started with Drupal and shows you how to build stable,
interactive, and scalable websites. This will probably be comparable to the O‟Reilly book.

“Drupal 6 Social Networking” by Michael Peacock. Packt Press, February 2009, 312 pages. List price $39.99,
Amazon price $31.57, used from $29.46. Rated 3.5 stars on This book describes the modules used to
create social networking site, such as the blogging, comment, and group manager facilities. Plus information on
setting up your site, using themes, and using RSS feeds. It has a few pages on building themes. Most of the
modules discussed are standard ones, rather than custom development. Has good discussion of using the Organic
Groups module. The book uses a case study of building a site like the one we made for Yosemite Association.

“Building Powerful and Robust Websites with Drupal 6” by David Mercer. Packt Publishing, February 2008, 380
pages. List price $44.99, Amazon price $40.90, used price $38.30. Rated 4 stars on Amazon. Second edition of
well-regarded book on Drupal by same author. First edition rated 3.5 stars on Amazon. Until the “Using Drupal”
book came out, this was considered to be the best printed reference for beginner and intermediate users. Has
chapters on installation, setting up modules and components in the site, and adding content. Has a section near the
end on administration and backups. Provides some good hints as to which third-party modules are most useful. All
screens updated to Drupal 6.

“Getting Started with Drupal” by Matt Vance. DZone Refcard, 2009. 6 pages. Like all refcardz, this is a terse
introduction, but the fact that a refcard has been created is another checkpoint in favor of Drupal. This refcard
covers mostly topics that are of interest to site builders, or those writing themes or modules. It recommends the
CCK, Views, and Administration Menu modules, then goes into theme development. There is no coverage of basic
content creation – that is either too basic, or covered elsewhere.

“Learning Drupal 6 Module Development” by Matt Buchter. Packt Publishing, May 2008, 328 pages. List price
$44.99, Amazon price $28.79, used from $22.49. Rated 4 stars on Amazon. This is a great introduction to begin
developing on Drupal. If you use Drupal but want to start going beyond merely plugging in new modules, this is the
book to get. It starts from ground zero on developing a new module and theme. It is a great introduction on the way
Drupal works. Assumes knowledge of PHP, which you need anyway to program Drupal modules. Much better to
start with this book than any of the others on developing for Drupal.

Page 3 of 55
“Pro Drupal Development, Second Edition” by John VanDyk and Matt Westgate. APress, August 2008, 700 pages.
List price $49.99, Amazon price $31.49, used from $31.30. Rated 5 stars on Amazon. This book spends only 1
chapter on the background of Drupal, and then moves into how to write a module. It covers the front end and the
back end. There is excellent discussion about the login sequence, the facilities for integrating a new module into the
system, how the menu system works, how to write themes and forms, etc. Appendix A describes the data model.
The first edition came out in early 2007, and was also well-received. It has a similar organization, but less detail.

“Drupal 6 Themes” by Ric Shreves. Packt Publishing, September 2008, 312 pages. List price $39.99, Amazon
price $35.99, used from $30.01. Rated 5 stars on Amazon. Updated from the Drupal 5 version of one year earlier.
This is focused on theme development, including a discussion of the theme engines, variables, templates, etc.

There is a very useful series of documents from IBM developerWorks on selecting an open-source collaboration
system, in which they chose Drupal, then how to install it, populate content, and then develop a custom module. See Here was the result of their evaluation:

While the IBM document itself was written for Drupal 4.7 and early 5.x, the custom module, called
“announcements”, has been maintained and updated to Drupal 6.x. The module is used for some of our discussion
about module development below.

Sample Runs
These sample runs were made from the opensourcecms web site of demos. Select “Drupal” from the menu.

You can log into the front page, or you can log in as an administrator. The site is generally running a current stable
release, and is updated often. They also reset the content every two hours, back to some standard and generic stuff.
The Drupal initial screens tend to be very empty, partly because they are not pre-populated with any content, and
don‟t have any extra blocks or areas on the screen. Here is a typical session back in 2007, after two items were

Page 4 of 55
We have added two content items (one is a blog entry with a date, and one is a page with no date), and we have
added a category. Here is an admin screen that shows the list of content items:

Here is an editing screen that shows one item being changed. Since the standard release doesn‟t include a
WYSIWYG editor, this looks pretty simple and less effective than WordPress. However, TinyMCE can be added.

Page 5 of 55
From here, you can classify the content, and control what content is shown on the title page. Opening up the
administration options on the left looks like:


Page 6 of 55
There appear to be two ways to get into the administration screens: you can drill down in the tree-like structure on
the left, or you can use the functional groups classified “By Task” or “By Module”. In the tree, you don‟t click on
the triangles to click on something to open it and all other pieces close at that point.

To return to the external view, click on the Drupal icon at the top; to return to the admin root, click on

Modules which are Provided in the Basic Download
The list below gives help for the modules that come with Drupal. When you install Drupal, these modules are
automatically installed. To make use of a module, first make sure it's enabled at Administer >> Site Building >>
Modules (some modules automatically are). Then set the correct permissions for it at Administer >> User
Management >> Access Control.

       Aggregator: publishing syndicated content
       Block: controlling content in the sidebars
       Blog: a blog for every user
       BlogApi: post from blog tools
       Book: structured document publishing
       Color: Allows the user to change the color scheme of certain themes
       Comment: allow comments on content
       Contact: a way for users to get in touch
       Drupal: Drupal sites directory server
       Filter: Input formats for user content
       Forum: create threaded discussions
       Help: context-sensitive guidance
       Legacy: remapping of old-style URLs
       Locale: multi-language support

Page 7 of 55
       Menu: customize site navigation
       Node: the basic content type
       Page: post static pages
       Path: readable URLs
       Ping: notify services of changes
       Poll: community voting
       Profile: extending user account information
       Search: an internal site search system
       Statistics: tracking referrers, page hits, etc.
       Story: post static pages
       System: cron and caching
       Taxonomy: A way to organize your content
       Throttle: congestion control
       Tracker: viewing new and updated content
       Trigger: Assign actions to system events
       Update status: Notifications about new versions of Drupal and contributions
       Upload: collaborate with files
       User: access and management settings
       Watchdog: monitor your site

The following modules are core, required, and enabled at all times: Block, Filter, Node, System, User, and
Watchdog. These provide content storage and content display, user management, filtering of a display, and site
monitoring. The content can be a page or a story, which are the simplest non-time-stamped and time-stamped
content types.

The following modules are enabled by default: Color, Comment, Help, Menu, Taxonomy, and Update Status. This
gives you a system that offers customizable of a presentation and the menu system, a help facility, a way to record
comments against content, the taxonomy system which enables classification but is not required for us, and
automatic check for updates against the master site.

In the introductory Drupal books written 2005 or 2006, they suggested turning on the following modules: Blog,
Forum, Locale, Poll, Search, and Upload. This turns the system into a more powerful CMS that has real blogging
for users, forums and polls for discussion, uploads for attachments, and search to find content within nodes after
posting. Locale deals with internationalization.

As a slightly more advanced example, you should consider turning on: Book, Path, Profile, and Statistics. This
gives better management of user information, URL paths which are more readable and will be handed by external
search engines better, and a collaborative book facility that deserves further review. Plus having statistics means
that you can measure the readership of the site.

The set of contributed modules is quite large and has undergone substantial revision as new modules are developed
that incorporate prior functions, modules are made irrelevant by changes in the Drupal core, or modules become
obsolete because they are not changed to match changes in the Drupal core. As of fall 2008, Drupal 6 had been out
for nearly 10 months, and the set of important contributed modules had changed greatly from our initial review in
fall 2007. One good way to track the importance and usage is to view the Drupal site‟s usage survey at The other good way is to look at the set of modules used in sites similar to yours.

Using these statistics the following modules stand out as important, in order:

Page 8 of 55
        Views – provides customizable tabular displays, which can be populated from nodes. In combination with
         CCK, this is very powerful. This could be a good way to show database-like content, such as a course
         inventory or a staff directory
        Content Construction Kit (CCK) – allows for the population of custom fields. Builds on the facilities for
         creating custom content that are in core.
        PathAuto – generates path names for the nodes, replacing the numeric id‟s. This module tries to generate
         paths using keywords in the node name or title, similar to the automatic slugs provided by WordPress.
        Token – used by PathAuto, not all that important on its own.
        Organic Groups – used to create collections of content.
        FCKeditor – provides WYSIWYG editing of text. We don‟t know why something like this isn‟t built in, as
         several reviewers have mentioned the need for it.
        TinyMCE – another WYSIWYG editor.
        Calendar – draws calendars and supports scheduling.
        Date – contains both the Date module and a Date API module. The Date API is available to be used by
         other modules and is not dependent on having CCK installed. Used by the Calendar module.
        Site Documentation – documents and cleans up your configuration.
        Panels – greatly extends the layout facilities of Drupal.
        Lightbox2 – an image display facility.

Semantic Data Model
This section is parallel to the one in our notes on Textpattern. Those notes had a diagram of sections, categories,
pages, etc. which could be clearly drawn on one page. Drupal is more complex, and is built from the following:

        Node: This is, in simple terms, a unit of content. Each node is of a particular content type. It may, for
         example, be a "page," "story," "book page," or "blog entry."
        Module: These are collections of PHP code following a specific API, that handle the defining, rendering
         and updating of the nodes of a specific content type. For instance, the Story module defines the Story node
         and its presentation, the Book module defines the Book node, the Poll module defines the Poll node, etc.
        Block: These are the named output of the modules. Think of these as "containers" for pieces of content on
         your displayed page. While nearly all nodes can be shown in the built-in generic blocks (or those provided
         by the Node module), the more interesting blocks are those produced by the more advanced modules.
         There are also blocks that are the output of some of the system-level modules, such as “User Login” block,
         a navigation menu block, and you may also have blocks such as "Recent posts," "Sponsored links," or
         "Who's online." The menu system can be thought of as being specified through blocks.

Page 9 of 55
        Theme: These are not database objects, but are objects in the file system and control the way your site is
         displayed (or rendered) to the end-user. Think of theming as a post-processing of a block‟s content as
         produced by a module.

Within the model for “nodes” are the ideas of revisions, taxonomy, and extensibility to other “subclasses” of node.
There isn‟t anything like custom fields – if you want to add fields you must create a new content type (using CCK or
using PHP code) which adds those fields.

Within the idea of a “module” are concepts such as permission management and access control, data base
initialization, specialized presentation include references to CSS and JavaScript files, and more. A module is also a
unit of extensible deployment, so it has a standard structure, and a control/information file that defines name,
version, and status, as well as an install file that defines all steps to carry out when the module deployed. As
mentioned above, there are numerous modules already present in the Drupal community.

With the idea of a “block” is the idea that the output page is composed of these blocks, and that the blocks may have
a configuration of their own. For instance, a “list announcements” block might have a configuration option
specifying the max number of announcements to list, etc. Also, the blocks have a placement in a region of the
output page (the regions are defined by the theme). For instance, the “left column” region might have block A with
a weight of -5, block B with a weight of +5, and block C with a weight of 0. Since the blocks will be ordered
according to their weight, this would render in the order A,C,B (actually, the block positioning administration screen
developed with later versions of Drupal takes care of positioning and generating the weights, but sometimes this
information is visible).

Within the idea of “theming” is all of the final HTML generation for PHP arrays that contain the content generated
by the blocks. The theming system goes far beyond the definition of CSS style rules, it includes all of the definition
of a page, the regions on the page, the menu system, and the facilities to take the output of the blocks and create
HTML. For instance, a block might create a table as an array of arrays of strings in the PHP, and the theme‟s table
processor will generate the TR, TD elements and have them reference the theme‟s CSS rules for tables. The
theming system uses a PHP template system for of its behavior.

Underlying all of these facilities is the Drupal permission management system. This enables an administrator to
define what actions can be performed by what roles of users. There are three built-in roles:

        anonymous user
        authenticated user
        administrator

In addition, an administrator can define new roles.

While the administrator can perform all actions, the offering of actions to the other two classes must be activated on
the Admin/User/Permissions screen.

From a software architecture perspective, the Drupal core consists of User Management, Localization, Templating,
Syndication, Logging, Basic Content Management, Session Management, and URL Aliasing.

What is interesting about comparing Drupal and Joomla is that they both perform the same functions, but the code
and the administration screens are organized in very different ways. Likewise, the module API is entirely different.

The statistics collected by Drupal's built-in statistics module is rather limited and there are no facilities to create nice
graphs or in other ways manipulate the collected data. On the other hand there are a lot of great and free web tracker
services out there which let you gather statistics on your visitors and then query that data in various ways. One such
service, StatCounter, can be integrated with any Drupal-based web site.

Page 10 of 55
Drupal in 2008: CCK and Views
Patterns of use in Drupal have changed greatly in the two years since we first began running it. At that time, the
typical configuration was to turn on modules such as Blog or Forum, and you would be ready to go, but limited in
flexibility if these didn‟t do exactly what you wanted. Under those conditions, you were stuck having to result to
custom module code.

By late 2008, most Drupal usage patterns focus on first activating CCK and Views, which give you a very flexible
environment, full of custom fields and presentations. You then define the objects and screens as needed. For
instance, one of the comments that we have read in early 2009 is that the Blog module is being considered for
removal, since it can be built from CCK and Views.

In fact, CCK (under the name “Field API”) is part of the Drupal 7 core. The current expected release date for
Drupal 7 is third quarter 2009, so we should continue to focus on D6, CCK, and Views.

Usage and Experiences
Create content [done]. We created content that included pages and stories. Stories are like blog entries. We used
HTML tags and links in the pages and stories. We noticed that there is minimal editing support. No HTML
generator and no spell checker.

View content [done]. It was organized chronologically by creation timestamp, and since we were logged in as
admin, clicking on the story/page showed a tab to edit the story/page.

Edit a page/story [done]

Delete a page/story [done]

Change the order of placement for a page/story on the menu by using weights [done]. On the main page by default,
items are shown-newest first, except for the ones which are marked as sticky, and shown at the top of the page.

Change the theme being used [done]. We have been using the theme “Bluemarine” for all of the above screenshots
of the administration side. We have selected and tried several different user themes, including “Pushbutton”.

Activate the Blog module and repeat the above using the Blog Entry content type [done]. Blogging turned on the
link for jrisberg‟s blog (it enables blogs on a per-user basis), and added the RSS feed icon. There wasn‟t any way to
convert the Story node into a Blog Entry node, so we had to re-create the node manually.

Activate the Path module and check how the URLs are organized [done]. Actually, you need to type in the new
URL – it doesn‟t generate it. These become aliases for the node referencing URLs. These can be set up as the
nodes are being edited, or on the Path module‟s configuration page, you can view all of the aliases and edit them,

Install the Barron theme and review all screens mentioned above [done]

Determine the configuration operations possible to customize a theme‟s appearance [done]. You can control the
presence of the custom image, custom logo, titling, etc. To perform what WordPress calls widgets, you use the
block facility, described below. Some themes (i.e., Garland) support color changes, but not many. If such a feature
is supported, it uses the Color module.

Configure the menus, placing links for the Pages onto the header [done].

Activate the Upload module and try uploading an image and using it in content [done].

Configure the Comments model (it is always activated) and add a comment to a posting [done]. Later we reviewed
and acted upon the comments in the Comments module of the admin screen.

Page 11 of 55
Add the TinyMCE module for better text support, editing and checking. This would be critical for non-html-skilled
users to run the site [done]. Is there a spell checker provided?

Populate categories [done]. We created four taxonomy categories and put words into them.

Upload a Word document and refer to it in a posting [done]. This is another example of an upload. The reference in
a posting must be manually created. You need to type an <img> or <a> tag into the content (in the full html mode)
and get the URL correct.

Create a custom block and put it somewhere on the screen [done]

Activate the Search module and try using a search [done]. To update the search indices, you must run the
background cron job that performs indexing. We are currently doing this manually, and finding the request to run
the background job on the “Status Report” administration screen.

Customize a theme by changing the style sheet and a few images [done]. We have made changes to Barron that we
have kept, and small patches to others that were not worth keeping.

Activate the Statistics module and try it out [done]. We configured it to display a reads count after each entry.

Set up a non-admin account [done].

Try out the Views module [done]. This was quite interesting, as it allows for creating very flexible tabular views.
This is discussed in more detail below.

Try out the Book module [done]. This is the most powerful model in Drupal, and is considered to be a counterpart
for a wiki facility. A book can have multiple book pages, and Drupal maintains the links between the pages. There
is further description below.

Activate the Poll module and try using a poll [done]. We also had to turn on polling for authenticated users.
Otherwise the only user who could vote was the ID1 user. The poll module is described further below.

Activate the Forum module and test [done]. This is described further below.

Activate the Aggregator module and test [done]. This is quite useful, as it takes us from a world in which all content
is created within the system to one in which content is arriving from outside.

Permission Management and the Root User
Take care with UID1. The user id 1 account (uid1) is able to do everything on a Drupal site. Drupal access checks
will always allow this account to take an action. Another special permission is that the uid1 account is the only
account that can execute the update script. Due to these permissions, it is generally not appropriate to use this
account for "day to day" purposes.

Selecting Themes
One of the biggest challenges outside of development and administrative configuration is to select a theme. This
controls the visual appearance. There are about 100 different themes available for Drupal 6, which are located on
the Drupal site. A good guide to 20 of the best ones is at

The default theme is called “Garland”, which is a collection of shades of blue, and has a sidebar on the left.

Themes that we liked or learned useful information from included:
    Barron: this theme was one that we visually liked, and then used it as a model for development of the
        Insignia theme. It has all of the standard features, including menus, blocks, etc., and the CSS files are well-

Page 12 of 55
        Foundation: this is very simple, with almost no graphics or complex CSS. Only 15K total size, so it is an
         excellent starting theme. This is a liquid layout theme that handles layout for one, two, and three columns
         based on which blocks are enabled using CSS, not tables
        Zen: also a very good starting theme. It is larger than Foundation, but it has better documentation. One
         way of using it is to create a subtheme, rather than starting from scratch.
        A3 Atlantis: this theme has a good color scheme and very contemporary layout. Is able to handle 2/3
         column layouts dynamically.
        Four Seasons: this is a completely new theme, not derived from others, and has a clean visual appearance
         the good color scheme.
        Nitobe: fixed width (960 pixels) theme with a right side bar region and a bottom region. Designed with a
         single author blog in mind. This is a very complete theme, and has a clean, mostly black and white,
         appearance with interesting graphics. The layout is built around a grid designed for 2 columns or 3
         columns. The grid is similar to the layout grid used in page layout software, and the resulting pages look
         quite good.

Using the Node Module
Basically all content in a Drupal site is stored and treated as a node. Therefore nodes are the basis of any postings
such as pages, stories, blog entries, etc. The Node module manages these content types and is one of the strengths of
Drupal over other content management systems because of its extensibility.

Treating all content as nodes allows the flexibility of creating new types of content. It also allows you to painlessly
apply new features or changes to all content. Comments are not stored as nodes but are always associated with a

Features of the Node module:

        The “list” tab provides an interface to search and sort all content on your site.
        The “configure settings” tab has basic settings for content on your site.
        The “configure content types” tab lists all content types for your site and lets you configure their default
        The “search” tab lets you search all content on your site

Configuration options here let you define content types, limit the size of postings, and set the number of posts on the
main page.

“Nodes” administration overlaps with a number of features regarding content management administration.

Using the Blocks Module
Blocks are boxes of content that may be rendered into specified regions of your web pages, for example, into
sidebars. Blocks are usually provided automatically by modules (e.g., Recent Postings), but administrators can also
define custom blocks.

The region each block appears in depends on both which theme you are using (some themes allow greater control
over block placement than others), and on the settings in the block administration section.

The block administration screen lets you specify the vertical placement of the blocks within a region. You do this
by assigning a weight to each block. Lighter blocks (those having a smaller weight) "float up" towards the top of
the region; heavier ones "sink".

A block's visibility depends on:

        Its region placement. Blocks with no region assigned to them are never shown.
        Its throttle checkbox when the Throttle module is enabled. Throttled blocks are hidden during high server

Page 13 of 55
        Its page visibility settings. Blocks can be configured to be visible/hidden on certain pages.
        Its custom visibility settings. Blocks can be configured to be visible only when specific conditions are true.
        Its user visibility settings. Administrators can choose to let users decide whether to show/hide certain
        Its user-role visibility settings. Administrators can choose to let blocks be visible only for certain user
        Its function. Some dynamic blocks, such as those generated by modules, will be displayed only on certain

The primary way to make a Drupal site have different visual regions is to have different blocks on it. You can‟t
change the theme from page to page, but you can change the blocks on the page. In our earlier work, we treated the
blocks as being present or not present, but lately we have made the block configuration dynamic using some of the
visibility settings.

Examples of controlling a block‟s visibility to use the specifications, such as:

In this case, the block will be shown only on the page whose url is <siteurl>/node/12, or <siteurl>/brandon, where
“brandon” is the alternative URL pathname to a specific node.

The page specification can be used as follows:
 Enter one page per line as Drupal paths.
 The '*' character is a wildcard.
 Example paths are blog for the blog page and blog/* for every personal blog. <front> is the front page.
 If the PHP-mode is chosen, enter PHP code between <?php ?>. Note that executing incorrect PHP-code can
    break your Drupal site.

Defining Custom Blocks
Most of the use of the Blocks module is to specify the location of standard, known blocks. However, you can also
create new Block using the “Add New Block” menu item. You can create content for the block. It is also possible
to create a block that will run PHP code.

For security reasons, only advanced users should create Blocks containing PHP code. For this reason, as of Drupal
6, you can only create a Block containing PHP code if you install the “PHP Filter” module. This will allow you to
define an Input Format with the PHP filter.

Using the Menus Module
Menus are a collection of links (menu items) used to navigate a website. The menu module provides an interface to
control and customize the powerful menu system that comes with Drupal. All menu elements are stored in the
database – there is no XML configuration file like in many Java application. Menu items have a path that is a URL
that gets carried out when the menu item is clicked.

Page 14 of 55
Menus are primarily displayed as a hierarchical list of links using Drupal's highly flexible blocks feature. Each
menu automatically creates a block of the same name (which must then be placed into your block layout for it to be
shown). By default, new menu items are placed inside a built-in menu labeled Navigation (which is generally
shown in the sidebar), but administrators can also create custom menus.

Drupal themes generally provide out-of-the-box support for two menus commonly labeled primary links and
secondary links. These are sets of links which are usually displayed in the header or footer of each page
(depending on the currently active theme). Any menu can be designated as the primary or secondary links menu via
the menu settings page.

Menu administration tabs:
    On the administer menu page, administrators can "edit" to change the title, description, parent or weight of
       a menu item. Under the "operations" column, click on "enable/disable" to toggle a menu item on or off.
       Only menu items which are enabled are displayed in the corresponding menu block. Note that the default
       menu items generated by the menu module cannot be deleted, only disabled.
    Use the "add menu" tab to submit a title for a new custom menu. Once submitted, the menu will appear in
       a list toward the bottom of the administer menu page underneath the main navigation menu. Under the
       menu name there will be links to edit or delete the menu, and a link to add new items to the menu.
    Use the "add menu item" tab to create new links in either the navigation or a custom menu (such as a
       primary/secondary links menu). Select the parent item to place the new link within an existing menu
       structure. For top level menu items, choose the name of the menu in which the link is to be added.

Besides editing the menus through this admin page, you can also cause a new node (such as a story or page) to be
added to the primary (or secondary) links as the node is being created. To specify this, open the “Menu settings”
drop-down at the top of the node editing page. Drupal is smart enough to remove this menu item when the node is

Ordering the presentation of menu items is done by their „weight‟ attribute. The presentation of a menu is typically
an indented tree-like list, formatted via the CSS class “menu”. However, the menus labeled primary links and
secondary links are formatted via the CSS class “links”, which typically arranges them left to right. The links also
are not tree-like, in fact child menu items are skipped. There is no facility that we have found to control the emitting
of the menu elements on the page, so you have to use CSS to format them.

On the “action” handling side of menus, there is really no more support than to carry out the path as a URL-based
request. The linkage is very loose, because the menu system doesn‟t know what the URL‟s do. Also, in Drupal,
there is no concept of specific types of pages or pages with business logic. Instead, think of each presentation page
as a “query” against the nodes pool, for which the results will be rendered on the page. The default query produces
the home page. This contains all nodes for which “Show on Home Page” has been set in the editing form.

Hence, most of the menu operations are requests to carry out a different query, such as a restricting by a condition
such as node by id, all nodes within a time period, all nodes for a content classification, etc. As we will see below,
the most common pattern is to have a menu item referring to a View defined as a Page, where the query parameters
and presentation parameters are in the View.

Finally, there appear to be no facilities for having menu items “checked”, “unchecked”, “disabled”, or other
functions that are typical of menus in Windows or Mac applications. The only API-level control is visibility of the
menu item.

Using the Comments Module
This module enables comments to be attached to nodes (i.e., stories, blog entries, etc.). Under the settings you can
change which nodes have comments enabled by default. The other part of the comments administration module is a
bulk comment manager, which enables you to unpublish, delete, or edit comments.

Page 15 of 55
Simple use of the Taxonomy Module
Drupal‟s categorization system is called the taxonomy module. Taxonomy means "division into ordered groups or
categories." Taxonomy also refers to the science or principles of classification. In the language of taxonomy,
groups of categories are called "vocabularies," and the categories themselves are called "terms."

The simplest way to use this is to create a vocabulary called “Tags”, and assign it to all of the content types (e.g.,
blog entry, page, story). For settings, select “Tags”. Terms are created by users when submitting posts by typing a
comma separated list.

You can then filter for nodes with tags on the list of all content, as shown below:

This would let us search for nodes that published, are of a given type, or have the category „brandon‟. After
selecting the filter, you can refine the filter to add more conditions, hence looking for combinations of values.

More Complex use of the Taxonomy Module
The Drupal taxonomy system is powerful because it allows for content to be categorized when it is created, or
reclassified later. It is built around “vocabularies”, which are a collection of words.

With the categories module you can define groups ("vocabularies") of categories ("terms") by which to classify
     Each vocabulary consists of a set of terms.
     You can have as many vocabularies as you want and for each create as many terms as you want.
     You can order your terms into hierarchies.
     You can also have "free vocabularies," in which users creating new content don‟t have to classify it with
         terms from a "controlled vocabulary," one you‟ve defined. Instead they can freely define their own terms,
         or "tags." (This is sometimes called "free tagging.")
     When you create a term, you can also tie it to related terms. (Think of "See also" in a dictionary.)

You can allow users to classify each piece of content they create--each story, blog item, or whatever--using one term
or many.

A vocabulary can be specified as being assigned to any of the content types. In our example, we assigned them to
“blog posting”, and kept pages and stories without vocabularies.

Page 16 of 55
A vocabulary /classification section will appear in the entry screens for the appropriate content types once a
vocabulary is assigned to that content type.

A vocabulary is of one the following three types:

        Disabled hierarchy – Each term in the vocabulary stands on its own, with no parent
        Single hierarchy – Each term allows for the specification of a parent
        Multiple hierarchy – Each term allows for the specification of multiple parents

Clearly, design of vocabulary hierarchies can become a complex process, but this actually quite powerful, as it
avoids the model of fixed hierarchy of category/sections, etc. that is present in many other CMS applications.

The following options exist for a vocabulary:

When running the administrative screen and entering terms, the screen doesn‟t tell you what vocabulary you are
working on. Likewise, when viewing the vocabularies, there is no indication of how many terms are in each.
Finally, when creating vocabularies, you must do it single term at a time.

Finally, the taxonomy facility isn‟t much use without the facility for running queries that are taxonomy based.
Fortunately, there are several ways to do this, with different expressions like:

        When you create a new term, Drupal assigns it a number. And you can call up all the items categorized
         under that term by calling for its number. The term numbers are sequential across the pool of all terms
         created for all categories.
        To see your term's number, go to the categories page, choose list terms for the category to which your term
         belongs, and now hover over your term's name in the list. You'll see the number in the URL at the bottom
         of the screen.
        Now, on the menus page (administer >> site building >> menus) you can create a menu item for your
         term. Select add item, and when you fill in the path field you add your category like this:


If your category "sonatas" is term 1, this would call for all the nodes of that category.

If your category "Bach" is term 2, you could call for only those sonatas written by Bach:


Page 17 of 55
Or if Brahms is term 3 and you want to call for everything that has to do with either Bach or Brahms, you‟d do it
this way:


Using the Blog Module
You should enable the Blog module, if you want to have a blog per user. Otherwise there is one shared content pool
on the site, which authors can contribute to. Also, the block that shows recent postings is only enabled if you turn
on this module.

The Blog Entry content type is added by the Blog module. The blog module allows you to have a multi-user blog,
meaning that every user can have their own personal blog. This adds titles and breadcrumbs to indicate the blog
authors' names.

The Blog module also provides a number of blocks that give lists of blog entries, such as Recent Postings. On your
blocks layout, add the Recent Postings block.

As of late 2008/early 2009, Drupal usage patterns have begun to change greatly. Instead of using the Blog module
and its predefined data object and display blocks, many developers are creating the data object with the CCK
module and the display blocks with the Views module. Hence, the Blog module (which isn‟t that much code
anyway) may be removed in future versions.

Using the Filter Module
The Filter module allows administrators to configure text input formats for the site. For example, an administrator
may want a filter to strip out malicious HTML from user's comments. Administrators may also want to make URLs
linkable even if they are only entered in an unlinked format.

Users can choose between the available input formats when creating or editing content. Administrators can
configure which input formats are available to which user roles, as well as choose a default input format.
Administrators can also create new input formats. Each input format can be configured to use a selection of filters.

Using the Search Module
The search module adds the ability to search for content by keywords. Search is often the only practical way to find
content on a large site. Search is useful for finding users and posts by searching on keywords.

The search engine works by maintaining an index of the words in your site's content. It indexes the posts and users.
You can adjust the settings to tweak the indexing behavior. Note that the search requires cron to be set up correctly.
The index percentage sets the maximum amount of items that will be indexed in one cron run. Set this number
lower if your cron is timing out or if PHP is running out of memory.

Using the Uploads Module
You need to turn this on for uploads to be available.

The Uploads module allows users to upload files to the site. The ability to upload files to a site is important for
members of a community who want to share work. It is also useful to administrators who want to keep uploaded
files connected to a node or page.

Users with the upload files permission can upload attachments. You can choose which post types can take
attachments on the content types settings page. Each user role can be customized for the file size of uploads, and the
dimension of image files.

Page 18 of 55
Configuration options are: file type limits, file size limits, and image file dimension limits. Note that the default is
1MB for the file size limit which is smaller than the image files that we typically use today. Perhaps this is an old
setting, or used to avoid cluttering up the site with large images.

Using the Statistics Module
This module has one of the most important configuration settings screens. Basically, if you don‟t turn on the
statistics here, you can‟t turn on the display of them on the later screens, etc.

Under access log settings, you have to first enable the log, and then enable count view counters.

Then go to Configure Permissions, and turn on the permission view counter settings, for all users, for all
authenticated users, or both.

When the Statistics module is turned on, and the logging is enabled, there will be an optional table in the node edit
facility called “Track”, this will be bring up the raw tracking records. This will only have the content view records
if “content viewing counter settings” is enabled. In all cases, it will have change tracking.

Using the Profile Module
This module enables you to add custom fields to the user information. The fields can be any of a number of types,
including text fields, numeric, etc. The fields are divided into groups, which will be different tabs within the user
editing screen. The weight information on the field specifies the order in which it appears on the editing and display

The profile data goes into the profile data, which can be joined with the user table. This is commonly performed in
the Views module as a relationship, for instance (the Views module is described below).

Page 19 of 55
Using the Poll Module
The poll module can be used to create simple polls for site users. A poll is a simple multiple choice questionnaire
which displays the cumulative results of the answers to the poll. Having polls on the site is a good way to get instant
feedback from community members.

Users can create a poll. The title of the poll should be the question, and then enter the answers and the "base" vote
counts. You can also choose the time period over which the vote will run. There are options on the poll for length of
time, which roles/user classes can vote, which can view results, which can change their votes, etc.

From a data model perspective, each poll is a node object, plus the modules creates a special queryable display
found at “q=poll”. Placing this into a navigation menu will take you to a page where you can see all the current
polls, vote on them (if you haven't already) and view the results.

Using the Forum Module
The forum module lets you create threaded discussion forums for a particular topic on your site. This is similar to a
message board system such as phpBB. Forums are very useful because they allow community members to discuss
topics with one another, and they are archived for future reference.

Forums can be organized under what are called containers. Containers hold forums and, in turn, forums hold
threaded discussions. Both containers and forums can be placed inside other containers and forums. By planning
the structure of your containers and forums well, you make it easier for users to find a topic area of interest to them.
Forum topics can be moved by selecting a different forum and can be left in the existing forum by selecting leave a
shadow copy. Forum topics can also have their own URL.

From a data model perspective, each Forum topic is a node, and the replies to the topic are stored as comments. All
of the Forum topic nodes are attached to a container, and the parent of all containers is a special kind of object is that
only reached through a query against „q=forum‟. Typically, you would then create a menu item that contains this
query. That way your site has a section that is called “Forums”.

Using the Book Module
A book is a set of pages tied together in sequence, perhaps with chapters, sections, subsections, and so on. You can
use books for manuals, site resource guides, Frequently Asked Questions (FAQs), or whatever you'd like. This
module is used for the Drupal documentation.

Users who have permission can create a book and write, review, modify, or rearrange the pages. Many users can
work together on a book. You can allow or disallow collaboration, to whatever extent you want.

At the bottom of book pages, Drupal automatically provides links for moving to the previous page and the next, and
a link labeled up that leads to the level above in the structure. A contents page is also automatically created.

You can provide your users a menu that helps them find their way around inside your books. You do this by
enabling the book navigation block on the blocks page (administer >> blocks). (Users will see the menu only when
viewing the book.)

A book is built out of book pages (which are a type of node), and each book page has a parent. A page with parent
equal to null is treated as a new book. The linkage can be changed at any point.

Posts of type Book page are automatically added to the book hierarchy. Users with the outline posts in books
permission can also add content of any other type to a book, placing it into the existing book structure through the
interface that's available by clicking on the outline tab while viewing that post.

Administrators can view a list of all books on the book administration page. In this list there is a link to an
outline page for each book, from which is it possible to change the titles of sections, or to change their weight, thus

Page 20 of 55
reordering sections. From this administrative interface, it is also possible to determine whether there are any orphan
pages - pages that have become disconnected from the rest of the book structure.

Using the Aggregator Module
The news aggregator module allows for the definition of RSS news feeds and categories of feed content. Categories
provide a way to group items from different news feeds together. Each news category has its own feed page and

Though this module is activated much like any other module, it is used differently. You create feeds through the
administration screen, using the aggregator > administrator link. For each feed there is a baseURL, a refresh time,

You will create a feed object, combined with a category object, in the administration screens. The feed and content
records are stored in tables specific to the Aggregator module.

Then the output is displayed with a node with the name “aggregator” which is a built-in page. The page loops over
the aggregator outputs. The content is fetched during a run of the back-end back-end script. The approach to
finding and running this script is to go to administrator > logs > status_report, and click the “Run Now” button.
Articles will be assigned to categories, and there are also facilities that allow for assignment of an article to a
specific category.

We don‟t know how to merge the contents of the aggregator into the contents of other collections or nodes on the
page. This would be useful for integrating parts of content, but the articles in the news feeds are stored in the
aggregator_item table, not the node table. Hence you need to set up two separate views or blocks.

Markdown in Drupal (not a built-in module)
Provides Markdown filter integration for Drupal input formats. The Markdown syntax is designed to co-exist with
HTML, so you can set up input formats with both HTML and Markdown support. It is also meant to be as human-
readable as possible when left as "source".

For instance, you can indicate italics by using *word* or _word_, and bold by using **word** or __word__.
There are also rules for generating bulleted and numbered lists. This was very useful for creating wiki-like

To create a link use [linktext](url).

To configure the module, you must create an Input Format that specifies Markdown. The format must not also
specify one of the other input processers, or the Markdown inputs or outputs will be removed.

FCKeditor in Drupal (not a built-in module)
This module allows Drupal to replace textarea fields with a visual HTML editor. This HTML text editor brings
many of the powerful WYSIWYG editing functions of desktop editors like Word to the web. It's relatively
lightweight and doesn't require any kind of installation on the client computer.

TinyMCE in Drupal (not a built-in module)
To install this we added some code downloaded from Drupal into the modules directory, and then we added some
additional code from MoxieCode into that directory. This provides a link to a good bit of JavaScript that makes the
TinyMCE work.

Next, you create a TinyMCE profile, which is a configuration what buttons to turn on, etc. We generated a set of
buttons that is similar to the set provided in the typical WordPress configuration.

Then you assign the TinyMCE profile to the themes and the users.

Page 21 of 55
One problem was that we had to disable auto-save, or we would get a message indicating that navigating away from
page would cause the results to be lost when we did a save. Not sure why.

Also, we would like to provide two tabs for editing, one being the TinyMCE display and one being the raw code
display, as is done in WordPress. Not sure how to do this.

While FCKeditor and TinyMCE appear to have similar features, the “Using Drupal” book suggests FCKeditor as
being more flexible.

Pathauto in Drupal (not a built-in module)
The Pathauto module automatically generates path aliases for various kinds of content (nodes, categories, users)
without requiring the user to manually specify the path alias. This allows you to get aliases like /category/my-node-
title.html instead of /node/123. The aliases are based upon a "pattern" system which the administrator can control,
and the pattern defines a path string that uses tokens from the title, taxonomy, and username. The default pattern is
“content/[title-raw]”, where title-raw is a string built from the words of the title with stop words taken out. We have
seen the results of this pattern used in several of other Drupal sites we have reviewed.

The Pathauto module is one of the most-recommended modules to add to your Drupal installation. Please note that
it depends upon the Token module. You also have to enable the Path module (which is built-in) for Pathauto to

We decided to change the default operation mode for Pathauto to leave existing aliases intact. Otherwise it was
changing specific aliases (such as those with a naming pattern that is used to control block visibility) unless we
unchecked the path generation checkbox before saving any edited node.

Menu_Block Module in Drupal (not a built-in module)
This allows you to define a configurable block that displays a specific menu. You already get a block defined for
each menu that you create, but this module enables you to control more specifically how the menu is placed into the
menu hierarchy, and what level of the menu tree. Typically you would be referring to additional menus built in the
site configuration, other than primary-links and secondary links, since these are typically rendered by the theme

When this module is enabled, you get a new tab in the Blocks editor, called “Add Menu Block”.

So if you‟re only using your theme‟s Primary links feature, you can add and configure a “Primary links (levels 2+)”
block. That block would appear once you were on one of the Primary links‟ pages and would show the menu tree
for the 2nd level (and deeper) of your Primary links menu and would expand as you traversed down the tree. You
can also limit the depth of the menu‟s tree (e.g. “Primary links (levels 2-3)”) and/or expand all the child sub-menus
(e.g. “Primary links (expanded levels 2+)”).

We did most of our initial testing using regular blocks that are defined for each menu, but for a complex hierarchy
(like on the Yosemite Association web site), these added features were very important.

Nice Menus Module in Drupal (not a built-in module)
This supports cascaded menus using drop-downs. This extends the menu management system. However, it doesn‟t
appear to be used by any of the modules that we have installed.

Google Analytics Module in Drupal (not a built-in module)
Adds the Google Analytics web statistics tracking system to your website.

The module allows you to add the following statistics features to your site:
     Single/multi/cross domain tracking

Page 22 of 55
        Selectively track/exclude certain users, roles and pages
        Monitor what type of links are tracked (downloads, outgoing and mailto)
        Monitor what files are downloaded from your pages

Image Module in Drupal (not a built-in module)
This module allows users with proper permissions to upload images into Drupal. Thumbnails and additional sizes
are created automatically.

Images can be posted individually to the front page, included in Stories or grouped in Galleries. The text entered as
the body is shown as a caption below the image, in the teaser and the full view.

The Image module ships with several contributed submodules:

        Image Gallery: using taxonomy terms, organize and display your uploaded pictures in galleries.
        Image Attach: allows you to easily attach image nodes to other node types.
        ImageMagickAvanced Options: adds advanced ImageMagick options such as image sharpening to the
         ImageMagick image toolkit.
        Image Import: simplifies adding multiple images by importing images from a directory on the server.

We began to try out this module during November 2008. The current release is 6.x-1.0-alpha4, released in January
2009. In our configuration, we turned on only the Image Gallery and Image Attach submodules.

Be sure to increase the image upload size on the Images module configuration page from 800KB to 4000KB. Also,
you create the Image Gallery definitions in the admin screens, under Administer > Content Management > Image
Galleries. This allows you to optionally attach each image to one Gallery, and to view the Gallery using the URL

Although it isn‟t documented in anything that we could find, this module also provides two new blocks, called
“Random Image”, and “Latest Image”. These draw from the set of images which have been uploaded by the Image
module. They are somewhat limited in that little can be configured, such as image sizing or captioning, but it can be
a quick way to get a random image or the most recently uploaded image.

How would you download the actual image file? There isn‟t any button for this, so you would do it by right clicking
the image in the browser and selecting the browser‟s Save or Copy option.

Lightbox2 in Drupal (not a built-in module)
The Lightbox2 module is a simple, unobtrusive script used to overlay images on the current page. It's a snap to set-
up and works on most modern browsers. The module places images above your current page, not within. This frees
you from the constraints of the layout, particularly column widths. It keeps users on the same page. Clicking to
view an image and then having to click the back button to return to your site is bad for continuity (and no fun!). The
module inserts the required JavaScript and CSS directly into your page with no need to edit the theme.

It appears that this module is a display facility for the images, rather than an upload or management tool for them.
Hence you still need the Image module.

The configuration settings that we used were: Image Node Settings -> Automatic Handler for Image Nodes =
Lightbox., and Lightbox Image Display Size = Preview

Service Links in Drupal (not a built-in module)
The Service Links module creates buttons or links across the bottom of a displayed node that allow you to post this
node to community sites such as Facebook, Digg, or Yahoo.

Page 23 of 55
First, install the module. Then configure it, selecting which node types will have service links added, and which
services should be offered.

You can display the service links as icons, text, or both. Here is an example of using both:

You select if the service links are to be shown in full articles, teasers, or both.

To change the yahoo button to use Yahoo bookmarks instead of Yahoo myWeb, change line 374 of the .module file
to generate a URL like:$url&t=$title

As of March 2009, the Service Links module was being refactored to allow easier addition of new services.

Site Documentation in Drupal (not a built-in module)
The Site Documentation module collects up information from various places within the Drupal environment,
providing a tabulation of modules used, themes used, content types defined, views defined, and data content such as
record counts for the nodes table and other tables. The primary purpose is to generate a “living document” that can
help you keep track of your site, or hand it over to some one else. In many community organizations, the site
ownership task changes with the volunteers, so a facility like this is very useful.

Some of the information comes from internal arrays, some is derived from system calls, and some comes directly
from the database tables. The module makes quite a few database fetches as it operates, and should only be run
infrequently. This typically means during periods of low site demand (or when the site is offline for maintenance).

Notifications in Drupal (not a built-in module)
By default, Drupal doesn‟t send out email notifications when content is changed or added. However, by using the
Notifications module, you can add this.

The administration screen for Notifications enables you to define the conditions for notification, the email targets,
and the message to be sent. It is similar to that provided in other CMS‟s or in CRM systems.

Content Creation Kit (CCK) module in Drupal (not a built-in module)
This is a module that allows you to easily define custom content types and the fields for those content types.
Without this kit, the only approach would be to create a new module in PHP code. The CCK is becoming a critical
tool for Drupal development, and apparently will be a core module in Drupal 7.x.

The current version is 6.x-2.2, released March 18, 2008.

After activating the module, you must activate one or more field types. The provided ones include:
     text.field - may contain plain text only, or optionally, may use Drupal's input format filters to securely
         manage rich text input. Text input fields may be either a single line (text field), multiple lines (text area), or
         for greater input control, a select box, checkbox, or radio buttons. If desired, CCK can validate the input to
         a set of allowed values
     number.field – may contain a number in integer, decimal or floating point form. You may define a set of
         allowed inputs, or specify an allowable range of values. A variety of common formats for displaying
         numeric data are available.
     userreference.field - creates custom references to your sites' user accounts. By adding a userreference field,
         you can create complex relationships between your site's users and posts. To track user involvement in a

Page 24 of 55
         post beyond Drupal's standard Authored by field, for instance, add a userreference field named "Edited by"
         to a content type to store a link to an editor's user account page.
        nodereference.field - creates custom references between Drupal nodes. By adding a nodereference field and
         two different content types, for instance, you can easily create complex parent/child relationships between
         data (multiple "employee" nodes may contain a nodereference field linking to an "employer" node).

These are provided as extensions themselves, and in fact there are additional extension modules for field types
including data and computed field. The included optionswidget.module provides radio and check box selectors for
text and numeric types.

Now go to Administer -> Content Management -> Content Types. Create a new content type and edit it to add some
fields. For each field you also define the display widget that is used to display and edit the value.

You can also add additional fields to existing Content Types, such as adding more fields to a Story node. You also
must set up the permissions to allow users other than the admin user to access and edit the new fields.

One restriction that we didn‟t expect is that the same field name cannot be used in more than one node type.

After defining the Content Type, test it by creating a new node of your new type using the „Create Content‟ menu

The included fieldgroup.module allows you to group fields together in fieldsets to help organize them. This is
similar to the grouping facilities in

For display of these customized nodes, it is suggested that you use the Views module, or the ConTemplate module.

In initial runs of this module, we defined a new type, added fields, and marked instances to not be shown on the on
the front page by default. Hence, the new records would only shown be on specialized screens. This could be
useful for types that represent calendar entries, inventory asset records, course availability records, etc. The CCK
makes Drupal into something more like ExpressionEngine.

In later runs, we defined entire new Content Types that were specific to the domain.

Views in Drupal (not a built-in module)
The Views 2 module (which is an update of Views 1 from Drupal 5.x) provides a flexible method for Drupal site
designers to control how lists of content (nodes, but also other data objects) are presented. Traditionally, Drupal has
hard-coded most of this, particularly in how taxonomy and tracker lists are formatted.

You need Views if:
    You like the default front page view, but you find you want to sort it differently.
    You like the default taxonomy/term view, but you find you want to sort it differently; for example,
    You use /tracker, but you want to restrict it to posts of a certain type.
    You like the idea of the 'article' module, but it doesn't display articles the way you like.
    You want a way to display a block with the 5 most recent posts of some particular type.
    You want to provide 'unread forum posts'.
    You want a monthly archive similar to the typical Movable Type/WordPress archives that displays a link to
        the in the form of "Month, YYYY (X)" where X is the number of posts that month, and displays them in a
        block. The links lead to a simple list of posts for that month.

Views is a very useful module, which can display list of tabular rendering of the fields associated with nodes or
other pieces of the data model. It also has filtering, sorting, and customizable field-based displays. You create a
view and then place it on the page as a block, or create it as a full page.

Page 25 of 55
This tool is essentially a smart query builder that, given enough information, can build the proper query, execute it,
and display the results. A view can be provided as a page, block, or menu:
     Page: this means that it will be a full-page display, with header and footer, but no other blocks or node-
         driven content. Typically you will create a button or menu item that links to this page.
     Block: this means that it will be block that can be included on page with other blocks. This is even more
     Menu: this means that it will create a menu with dynamic content.

We are now running Views 6.x-2.11, which was released in June 2010. The Views module also provides the answer
to the question about having a display with multiple queries/lists. There can be only one main query, but you can
have views be offered as blocks that can be put on the sidenav areas. In turn, the block in these views can be
filtered, so the facility is really very powerful, much more like a multiple-pane content portal. See discussion of the
“Rake” project below.

The process of managing views is to use the admin functions for Views. This produces a list of Views, and you can
create or edit a View. Here is a simple View definition:

The most important part is the specification that this view is for the type “User”. The key parts include the field list
and the filter/sort specifications. You can also specify presentation as list or table, and the path used to invoke the
view. There are also facilities that allow specification of filters, parameters, and use of parameter by filters.

We used an example of the “All-time popular content” view, and this provided a sorted, filtered table as expected,
and it looked good in the View Type: Table. Then we created an example of the “front page” view, and it matched
the front page because it had the View Type: Teaser. This means that it would be possible to re-create the front page
with the Views module, perhaps to apply some different filtering or formatting to it that matched the controls over
the other presentations using the Views module.

One very useful part is the live preview display, which will run the View, and display the query and the results. This
lets you check the View‟s configuration while in the editing screen.

Relationship Management
Before selecting fields, it is generally important to review what modules have tables are to be joined to the primary
table (typically the Node table) in order to get the combined set of rows and columns. For example, we often want
to display the name of the user who posted the node, so that means a relationship with the User module and its table.
Likewise, some of the statistical information is in related tables.

The most common modules (and their tables) to join with are:
     User
     Comment
     Revision

Page 26 of 55
        Group (for nodes within Organic Groups)
        Node_statistics

Field Management
Clicking on the [+] icon next to the word Fields displays a section beneath the view information with all the
available fields grouped by Comment, File, Node, Node revision, Taxonomy and User, and probably a few others.
This is a general paradigm for the interface -- clicking on a widget or link displays a section beneath the view
information with the relevant interface. Usually, what is being edited will be highlighted in yellow, as well. When
adding items, you can use the Groups drop-down box to show only a subset of the fields available according to the
above groups, or select All to see all fields available, which is what was selected when the section unfurled. For our
example, we're selecting the 'User' group and adding the User: E-mail, User: Name and User: Picture fields.

Once we add our fields they show up in the Fields section of the interface. We will be walked through each field we
added, so keep clicking update, even if you don't make changes to the field and you will see the next one. The
fields we added can be rearranged by clicking the up/down icon, right next to the add icon we used earlier. We can
also remove a field using the same interface.

From here, the fields can be dragged up and down by grabbing the little drag handle on the left and moving them
where you like. Making a change to any part of the view by clicking update usually triggers a refresh of the view
preview which is conveniently located right below the main interface.

View Formatting
We change the style by clicking on the current style on the left hand side of the View information area.

We're given the style options of Grid, List, Table and Unformatted. Additional display styles can be added by
modules which have Views style plugins. Choosing a style reveals a "settings" button which you can click to
configure the style you've chosen.

View Arguments
Arguments are parts of the URL of a view that can be used to reduce the result-set. A classic example of an
argument would be in the case of taxonomy/term/TID or tracker/UID. In the former case, the view is restricted to
posts tagged with the associated taxonomy ID; in the latter case, the view becomes restricted to posts by the
specified user.

There is also a special case where arguments can be embedded into a View's URL. For example, the URL
/user/$arg/track would be valid on any /user/WHATEVER/track URL, and the WHATEVER would be passed into
the view as the first argument.

A given view can have multiple arguments. For example, you might have blogs as a view, and provide UID, Year,
Month, and Day as arguments in that order. Thus the URL might look like blogs/1/2006/3/15 which would display
all blog posts written by user id #1 on March 15th, 2006. Arguments can also be specified as *, which will be
interpreted as 'all values'; so in this case, blogs/*/2006/3/15 would show blog posts by ALL users on that date.

Using Views to Generate Backlinks
Backlinks module has been incorporated into the Views module. Install the Views module and enable the backlinks
view, or create your own using the "Search: Links to" argument.

Styling Views
One important follow-up is how to define the presentation for a view. The following CSS selectors are important:

view – selector for any view
view-<viewName> – selector for a specific view
view-header – selector for any text generated above the view

Page 27 of 55
view-content – selector for all elements of a view
views-table – selector for the table elements of a view – what is left?
views-field – selector for all table fields in a view
views-field-<fieldname> – selector for a specific table field in a view
views-field a – selector for fields which are links
even – selector for even rows. Typically specifies a background color.
odd – selector for odd rows. Typically specifies a background color.
view-footer – selector for any text generate below the view

Cloning, Exporting, and Importing Views
Since it takes considerable effort to design a view, you wouldn‟t want to start over for another one. So the Views
module allows you to „clone‟ a view, making a distinct copy which has a new name (this is also handy for changing
the provided, default, views, since being in code rather than a database entry, they can‟t be changed, so clone them

You can also export a view, which will give a textual description of all of the view specifications. This textual
description is also what is serialized into the „views_view‟ database table as a blob to store the view specification.
This textual description can also be useful for reviewing the configuration options. Then to make a new view, you
can import the exported definition.

Finally, if any editing or consistency issues appear in the View module‟s editor, one fallback approach is to export
the view, verify the contents of the textual export, then delete the view, and import the textual description to re-
created it. We had to do this once or twice.

Insert View module in Drupal (not a built-in module)
This is a convenient way to nest a database-driven table into a page. You need to create an Input Format that has
this filter in it. Then the syntax to use is:


There are additional forms of the syntax:

[view:name of view=name of display] invokes the view using the specified display.
[view:name of view=name of display=arg1,arg2,arg3] invokes the view using the
specified display and passes arg1, arg2 and arg3 to the view.
[view:name of view==arg1] passes arg1 to the view and will use the "default" display
set for the view.

With this facility, it becomes quite possible to create dashboard-like screens of multiple query/display panes, though
the Panels module improves on the concept even more. With this, many of the difficult examples of page layout
involving complex tables become simple. There is a note about performance issues, as it means that the page
content is highlight dynamic and can‟t be cached.

Panels in Drupal (not a built-in module)
The Panels module is the ideological son, successor to and almost complete replacement for the Dashboard module.
It was written by the person who developed the View module. This module allows you to create pages that are
divided into areas of the page. This offers is a completely flexible system that includes a couple of 2 column and 3
column layouts by default, but is also highly extensible and other layouts can be plugged in with a little HTML and
CSS knowledge, with just enough PHP knowledge to be able to edit an include file without breaking it.

Panels contains the following features:
        Panels supports styles, which can control how individual content panes, regions within a panel, and the
         entire panel will be rendered. While Panels ships with few styles, styles can be provided as plugins by
         modules, as well as by themes!

Page 28 of 55
        The layout builder is nice for visually designing a layout, but a real HTML guru doesn't want the somewhat
         weighty HTML that this will create. Modules and themes can provide custom layouts that can fit a
         designer's exacting specifications, but still allow the site builder to place content wherever you like.

        Panels includes a pluggable caching mechanism. A single cache type is included, the 'simple' cache which
         is time-based. Since most sites have very specific caching needs based upon the content and traffic patterns,
         this system was designed to let sites that need to devise their own triggers for cache clearing and implement
         plugins that will work with Panels. Panels can be cached as a whole, meaning the entire output of the panel
         can be cached, or individual content panes that are heavy can be cached.

        Panels can be integrated with Organic Groups through the og_panels module to allow individual groups to
         have their own customized layouts.

        Panels integrates with Views to allow administrators to add any view as content. Or, for uses where the
         layout editor needs more tightly controlled content, Views can be given custom displays to provide only
         what the site administrator wants the panels builder to use.
Here is a screen shot of the Panels module administration screen:

Voting API in Drupal (not a built-in module)
This module is the basis for a number of vote management facilities (such as Fivestar, shown below). It provides
the storage management for votes.

In this case, we activated the module, but left the default settings. The module by itself doesn‟t perform visible
functions, so move on to the Fivestar module, below.

Page 29 of 55
Fivestar Module in Drupal (not a built-in module)
The Fivestar voting module adds a clean, attractive voting widget to nodes in Drupal 5 and 6. It features:

        jQuery rollover effects and AJAX no-reload voting
        Configurable star sets
        Graceful degradation to an HTML rating form when JavaScript is turned off
        Support for anonymous voters
        Spam protection to keep users from filling your DB with bogus votes
        Easy-to-use integration with Views module for lists sorted by rating, or filtered by min/max ratings
        A Fivestar CCK field for use in custom node types
        An easy-to-use Form API element type for use in other modules
        Compatible with all versions of jQuery (1.0 - 1.2.6)

To use this, go the configuration screen for the module:

Attach voting to each of the content types such as story.

Organic Groups Module in Drupal (not a built-in module)
This module is very helpful for creating a community that has some flexible structure to it. Rather than creating a
fixed set of content types (which only the administrator could change), what this module does is associate nodes
with containers, called “groups”. Each container has a name, and a set of visibility and posting rules. For instance,
groups can be configured to require that you belong to it in order to see the content, groups can track requests for
member ship, groups can have approval policies for posting, etc. There are numerous preferences to configure
groups as you need.

Groups can be defined for any of the usual node types: blog, story, page, etc. Each group has a “home page” which
describes information about the group. A block is shown on the group home page which facilitates posting to it.
The block also provides summary information about the group.

You can create content which goes into a group by using the “organic groups” drop-down in the node editor. For
instance, you can create a regular node, or one which is in a specific group.

Groups get their own theme, language, taxonomy, and so on. The Organic Groups module has been revised several
times, and the current version uses the Views module for all of its summaries of groups or group contents. This
allows you to apply your understanding of View styling to handle presentation of the group information.

Page 30 of 55
The Organic Groups module also has a „notification of changes‟ facility available within the site, and you can
configure it for email-based notification of changes.

    1) Enable the Organic Groups and Organic Groups Views integration modules. If you want to protect some
       posts so that only certain users may view them, enable the 'Organic Groups access control' module as well.
       Please make sure OG is working well on its own before enabling other OG related modules.
    2) On the Administer > Organic Groups configuration page, see the content types table at the top. Click edit
       beside each type to set its 'usage'. Disable comments and attachments for node types which are designated
       as group nodes. You usually want to create a new node type via admin/content/types page. The content
       type should have the name “group”, the label “Group”, and the body label “A <em>group</em> is a
       collector of content with access rules. A group may be moderated, such that all content must be approved,
       or allow immediate posting”. In the Organic Groups configuration page, specify the type you defined for
    3) On the Administrator > Organic Groups configuration page, define the content types which can be placed
       into a group.

        There are a few handy tabs at the path 'group'. You might want to add a link in your Navigation to that url.
         Each tab also provides a useful RSS feed.
        „Administer nodes‟ permission is required for changing the Manager of a group (do so by changing the
         posts' Author.)
        „Administer nodes‟ permission enables viewing of all nodes regardless of private/public status.
        All membership management happens on the 'membership list' page which is linked from the group details
         Block (while viewing a group page). This includes approving membership requests (for selective groups),
         adding/removing users and promoting users into group admins.

Calendar Module in Drupal (not a built-in module)
Requires Views and the Date API (packaged with the Date module).

There are several steps to using the Calendar module:
     Define a content type that has a Date field. Typically this is called “Event”
     Enable the view called “Calendar”, and configure it to use the Event content type. Have the view create a
     Create a link to the Calendar Page somewhere in the menu system.
     Control the permission of content_date to indicate if any user should be able to see dated events, or just
         authenticated users. This makes calendars using-specific or shared.

This module will display any Views date field in calendar formats. Switch between year, month, week, and day
views. Back and next navigation is provided for all views.

The display of the calendar is a standard HTML table, with lots of CSS formatting. The table is actually generated
by a version of the View rendering code, so it has similar naming conventions in its CSS classes.

Location Module in Drupal (not a built-in module)
This module enables you to attach a location to a node or a user. Activate the module, and activate the sub-modules
for node locations and/or user locations. For nodes, you then need to go the Content Type admin screen, and for
each content type for which you wish to have locations attached, edit the content type, and enter a non-zero number
of locations. Then configure a geo map in the Location module configuration. We started with a minimal
configuration of the Location sub-modules, as follows:

Page 31 of 55
Now each node of the specified type will have a “Location” attribute. This is can be a string, or you can enter the
lat-long directly. In some respects, this module just gets you the data structure for Location, and you need to
activate other modules to provide the presentation or other tools (this model is similar to how the Voting API
provides the data structure, and the Fivestar module provides the UI).

It also appears that the data structure for location is that a node has a many-to-many link with a location, so that
Location data is reused and not replicated by the nodes. This could be handy for having many nodes at one location.

GMap Module in Drupal (not a built-in module)
This module depends upon the Location module, and integrates Google Maps as a presentation vehicle. We set it up
as follows:

Page 32 of 55
The approach is that this module creates path /map/node or /map/user, which can have an optional argument that
takes a specific node id (we changed it to have a list of node ids).

Configure GMap to specify the Google map type (terrain, street, satellite, hybrid), and GMap Location to specify the
Google Map Macro, which is the JSON string that gets built and sent to Google. Other parts of the GMap module
handle display of the map within a Drupal page.

There appear to be advanced facilities within the module that allow for using the Google Map as input, including
tracking mouse clicks. We have currently only used GMap for output.

Using CiviCRM (a set of extension modules, packaged)
Nonprofits and community groups maintain relationships many types of constituents. CiviCRM enables
organizations to maintain comprehensive constituent relationship management information in a single database,
creating efficiencies and new opportunities for nonprofits to better communicate and benefit from relationships with
their constituents. CiviCRM includes optional components which give you more power to connect and engage your

        CiviContribute - Online fundraising and donor management, now including pledges and personal campaign
        CiviEvent - Online event registration and event management
        CiviMember - Online signup and membership management
        CiviMail - Personalized email blasts and newsletters.
        CiviGrant - Simple grants management.
        CiviCase - Integrated case management.

This is downloadable as a packaged distribution.

Development started back in 2006 to 2007, and for a while CiviCRM was behind in matching the updates to Drupal
versions. There was concern that it would become out of date. However, that seems have been addressed in 2009.
For instance, CiviCRM now also includes integration with Views2 - providing enormous flexibility in exposing
CiviCRM data in Drupal "views".

The most recent update is from June 17, 2009. That supports Drupal 6. We have never actually tried these modules
or distribution, and are just recording this for completeness. It may also be that the Acquia distributions provide or
will provide some similar capabilities, since non-profits are a major target of Acquia.

Page 33 of 55
Implementing a Random Image
There is no currently-maintained module for having a random image chosen from a set. One approach is that is can
be built by defining an Image content type, and then a View that has a random mode in it. However, a simpler
approach that works is to create a Block with PHP code such as the following, which in turn was based on a
suggestion from the AListPart web site.

$extList = array();
$extList['gif'] = 'image/gif';
$extList['jpg'] = 'image/jpeg';
$extList['jpeg'] = 'image/jpeg';
$extList['png'] = 'image/png';

// You don't need to edit anything after this point.

$img = null;

if (substr($folder,-1) != '/') {
        $folder = $folder.'/';

if (isset($_GET['img'])) {
         $imageInfo = pathinfo($_GET['img']);
         if (
              isset( $extList[ strtolower( $imageInfo['extension'] ) ] ) &&
        file_exists( $folder.$imageInfo['basename'] )
    ) {
                  $img = $folder.$imageInfo['basename'];
} else {
         $fileList = array();
         $handle = opendir($folder);
         while ( false !== ( $file = readdir($handle) ) ) {
                  $file_info = pathinfo($file);
                  if (
                      isset( $extList[ strtolower( $file_info['extension'] ) ] )
                  ) {
                           $fileList[] = $file;

           if (count($fileList) > 0) {
                   $imageNumber = time() % count($fileList);
                   $img = $folder.$fileList[$imageNumber];

if ($img!=null) {
         $imageInfo = pathinfo($img);
         $contentType = 'Content-type: ' . $extList[ $imageInfo['extension'] ];
} else {
         if ( function_exists('imagecreate') ) {
                 header("Content-type: image/png");
                 $im = @imagecreate (100, 100)
                     or die("Cannot initialize new GD image stream");
                 $background_color = imagecolorallocate ($im, 255, 255, 255);
                 $text_color = imagecolorallocate ($im, 0,0,0);
                 imagestring($im, 2, 5, 5, "IMAGE ERROR", $text_color);

Page 34 of 55

Note that this code reads a directory, generates a random index using time() as source of ever-changing numbers,
and then emits an image result. About the last 20 lines are devoted to generating error messages as images, and
could perhaps be simplified.

Triggers in Drupal (new in Drupal 6)
Triggers are Drupal events such as saving or updating a post, a user logging in or someone viewing a piece of
content. Think of it like a trigger for an argument – when the Trigger happens (i.e. a disagreement), an Action
happens (the argument). This allows you to heavily customize Drupal and paves the way to amazing new
implementations of the software.

What is an Action?
Actions are something that happens after the trigger. For example, you could redirect the user to a page, send an
email notice to administrators or display a special message. This can allow you to integrate Drupal into other

How do I enable triggers?
To begin using Triggers and Actions, you first must enable the Triggers Module included in Drupal 6.0. Follow the
following instructions:
     1. Login to your Drupal administration panel
     2. Go to the Administer page
     3. Select the Modules section
     4. Scroll down the page to "Triggers" on the list. Tick the box adjacent to it and then click "Save
        configuration" at the bottom
     5. Return to the administer page - a Triggers option should have appeared.

What can I do with actions and triggers?
Actions and Triggers are pretty awesome really. They give you the ability to add some extra dynamic features to
your Drupal installation without any coding or real technical knowledge.

It‟s like writing a new Module for Drupal, but easier. The best thing is that there are so many things you can do!
Here are some real-world examples of things you could do using Actions and Triggers:

Example - alert writer to a new comment
Don‟t you just love that warm, fuzzy feeling when you get a comment on something you‟ve written? It‟s really nice
to be appreciated for your hard work. You can get an alert when someone comments on your story using the “After
saving a new comment” trigger with the “Send an email” action. In this set, you will be using variables.
     1. Go to the Administer page, and then go into the "Actions" section. Scroll down - we will be using a
         customized option this time.
     2. In the menu, select "Send e-mail..." and then click "Create".
     3. A new page will appear for you to customize it. Make sure you use a description so you can recognize what
         one it is - before long you'll have loads of different actions!
     4. Look at the "Recipient" field. Below it says that you can put "%author" in the field to send the email to the
         author of the post, which is what we want to do! Type "%author" into the field.
     5. Set a subject of your choice and then put a message into the final field - for example, you could put "You've
         got a new comment on your story - go take a look!". Finally, click Save.
     6. You will return to the Actions page. Scroll down to see your new action. Head back to the "Administer"
         page now.
     7. Go to the "Triggers" page, as we now need a trigger.
     8. This one is in the "Comments" tab, as opposed to the comment tab. Click "Comments" near the top.

Page 35 of 55
    9.  We need the "After saving a new comment" trigger - go to the drop down box in it and then select the
        Action that you made earlier. Click "Assign".
    10. It's done! Now you will receive an email if someone comments on your post!

Example 2 - personalized member welcome
Is your site a bit of a niche site with a dedicated fan-base or do you want to really make your customers feel at
home? You can get notified when a new member joins so that you can send a customized notice to them personally!
Use the “Send email” action with the “After a user account has been created” trigger.

    1.   Go to your "Administer" page and then go to Actions.
    2.   Once again, we need to use the "Send e-mail..." action but this time with the "After a user account has been
         created" trigger. Scroll down, and then create a "Send e-mail" action.
    3.   In the Recipient box type your email. Give it a memorable description, in the Subject put something like
         "New member has joined" and in the message put something like "A new member has joined, remember to
         email them!". Click "Save".
    4.   Go to the "Triggers" page now - you can use the link at the top of the "Actions" page.
    5.   For this one, you need to use the "Users" tab. Click on "Users".
    6.   Scroll down to the "After a user account has been created" trigger and then in the drop down box select the
         Action that you just created and then click Assign.
    7.   You will now receive an email when a new member joins.

Workflow in Drupal
The workflow module allows the creation and assignment of arbitrary workflows to Drupal node types. Workflows
are made up of workflow states. For example, a workflow with the states Draft, Review, and Published could be
assigned to the Story node type.

Transitions between workflow states can have actions assigned to them. In our example, we could assign an action
so that when the story moves from the Draft state to the Review state an email is sent out. Another action could be
assigned to the transition from Review to Published so that the node's status is set to Published (and becomes visible
on your website).

Early versions of the Workflow module made use of the “actions” module and the “triggerunlock” module, but as of
6.x, these are already integrated into the release.

While we have not actually run this module, it appears that the module supports definition of workflows on an
admin screen, and execution by attaching to the triggers. There is no reference to complex workflow concepts like
splits, joins, and tokens as in jBPM, instead, we believe that the workflow model is similar to that use in Plone,
where each object is in one state and the rules are relatively simple conditionals.

Drupal Data Model
There are about 60+ tables in all. The most important tables are node and node_revision. The latter has columns
called: body, teaser, and log, which are all long text fields. Comments are held in a separate table called comment.
There is also a table of node types.

The next most important tables are probably those that deal with user management, presentation management, and
permission management.

The voting API module adds tables for votingapi_vote, and votingapi_cache. These are good examples of tables
that are linked to nodes, and add more information. The prior table records each vote by user, and the latter table
records combined votes across users.

The total number of tables varies from deployment to deployment because some modules create more tables when
added and activated, and can drop those tables when the module is removed.

Page 36 of 55
Developing Themes in Drupal
The theme development process begins with the primary files in a theme, particularly template.php, style.css, and
page.tpl.php. As of release 6.0, there is a .info file which is also required.

The resulting output is created by using the different tpl files in combination. A diagram is shown below:

The now-standard template engine is called PHPTemplate, and is described below. Earlier versions of Drupal didn‟t
use a standard template engine, and so each template was a bit more complex and ad-hoc.

The .info file defines the metadata such as the theme name, author, version, features, regions, stylesheet(s), etc. and
use of the template engine. The internal name of the theme is also derived from this file. For example, if it is named
"", then Drupal will see the name of the theme as "drop". An example .info file would be:

name = Barron
description = XHTML & CSS based two column theme
core = 6.x
version = 1.0
engine = phptemplate
regions[sidebar] = Sidebar
regions[content_top] = Content Top
regions[content_bottom] = Content Bottom
regions[footer] = Footer
features[] = logo
features[] = favicon
features[] = name
features[] = slogan
features[] = mission
features[] = node_user_picture
features[] = comment_user_picture
features[] = primary_links
features[] = search
stylesheets[all][] = html.css
stylesheets[all][] = layout.css
stylesheets[all][] = style.css
stylesheets[print][] = print.css

This defines a theme named „Barron‟ to be written for Drupal 6.x, be currently in version 1.0, use the phptemplate
engine, and have the additional regions Sidebar, Content Top, Content Bottom, and Footer. The features provided

Page 37 of 55
include logo, name, slogan, mission, primary links, search, etc. There are a set of stylesheets used, which are
organized as:
      html.css – contains overrides for the basic HTML elements
      layout.css – defines positioning rules for the container and other geometric elements
      style.css – defines the font, text, color, and border information for visual elements
      print.css (only for the printable representation of the site) – defines overrides for the printed output.

This splitting of CSS into html, layout, and style is a common recommendation in CSS design. Even if these rules
are all in one file, the file should be in sections that are organized this way.

The standard template files are:

There is also a separate style sheet for the printed version of a page, called print.css.

The process of defining a region for a theme is quite simple: just add it to the .info file, and then place a print of a
variable with the same name in the appropriate place of the theme‟s page.tpl.php file.

Content is assigned to regions through the block system and also through drupal_set_content() calls. For
example, drupal_set_content('left', 'Hello there.') would assign the text 'Hello there.' to the left region
(usually implemented as a left sidebar). Any regions defined in the theme are available on the block configuration

In general, the themes for Drupal seem less complex than the themes for WordPress. However, the themes are
better thought of as the wirework for a presentation, rather than having the detailed formatting guts of what
information is shown for a posting, what is done conditionally, how are single posts shown differently than multiple
posts/archives, etc.

Template Files
page-front.tpl.php: can be used to specify a custom front page.
node-<nodetype>.tpl.php: optional template file to configure nodes of a specific type.
block-<region>.tpl.php: optional template file to configure blocks in a specific region.

The PHPTemplate Facility
This is used in most of the themes and is the standard engine as of release 5.x and later.

A .tpl file is one that is run over and over for a set of objects. It appears that the main code handles the looping and
runs the .tpl files. For instance, since a page has a pool of nodes, the code will run the node.tpl php file over and
over. The engine avoids having loop structures be visible in the PHP files.

A template is a file designed to be friendly to the typical administrator. There is not supposed to be any complex
PHP code there, because that would scare off many a user. In fact the only PHP code that typically appears is “if”
statements. They're lightweight files used to generate the equivalent of what a theme_function does. Values can be
passed into the template through variables by use of a PHP function, template_preprocess_<template_name>().

The structure of a .tpl file is actually standard PHP. There is a context object provided in the global namespace. For
instance for block.tpl.php it is $block.

Page 38 of 55
Structure of page.tpl.php
This paints the outer portion of the page, working from variables such as $head, $content, $site_name, $site_slogan,
$closure, $primary_links, and $language.

<html xmlns="" xml:lang="<?php print $language->language ?>"
lang="<?php print $language->language ?>">
  <head profile="">
    <title><?php print $head_title ?></title>
    <?php print $head ?>
    <?php print $styles ?>
    <?php print $scripts ?>
    <style type="text/css" media="print">@import "<?php print base_path() . path_to_theme()
<div id="page">

  <div id="header">
    <div id="headerimg">
                  <?php if ($logo) { ?>
                   <div style="float:left; margin: 5px;">
                       <img src="<?php print base_path() . path_to_theme() ?>/images/header-
                 <?php } ?>
          <div><h1><a href="<?php print check_url($base_path); ?>">
                         <?php print check_plain($site_name); ?>
         <div class="description" style="margin 5px;"><?php print check_plain($site_slogan);
      </div><!-- headerimg -->
      <?php if (isset($primary_links)) : ?>
      <?php print theme('links', $primary_links, array('class' => 'nav')) ?>
    <?php endif; ?>
 </div><!-- header -->

  <div id="content">
    <?php if ($breadcrumb): print $breadcrumb; endif; ?>
    <?php if ($mission): print '<div id="mission">'. $mission .'</div>'; endif; ?>
    <?php if ($tabs): print '<div id="tabs-wrapper" class="clear-block">'. $tabs .'</div>';
endif; ?>
    <?php if (isset($tabs2)): print $tabs2; endif; ?>
    <?php if ($help): print $help; endif; ?>
    <?php if ($messages): print $messages; endif; ?>
    <?php if ($title): print '<h2'. ($tabs ? ' class="with-tabs"' : '') .'>'. $title .'</h2>';
endif; ?>
    <?php print $content ?>
   <div class="navigation">
     <span class="previous-entries"></span> <span class="next-entries"></span>
  </div><!-- content -->

<div id="sidebar-right">
    <?php if ($search_box): ?>
    <div class="block block-theme"><?php print $search_box ?></div>
   <?php endif; ?>
    <?php if ($right): ?>
      <?php print $right ?>
    <?php endif; ?>
</div><!-- sidebar -->

  <hr class="clear" />
</div><!-- page -->

Page 39 of 55
<div id="footer">
<php print $footer_message ?>
</div><!-- footer -->

  <?php print $closure ?>

In this file, there is no block object to work from, but global vars are used. $content contains the result of expanding
all of the lower level objects using their template.

Structure of block.tpl.php
In this case the input block is $block, and the subcontent is located in $block->content.

<div id="block-<?php print $block->module .'-'. $block->delta; ?>"
     class="clear-block block block-<?php print $block->module ?>">

  <?php if ($block->subject): ?>
    <h2><?php print $block->subject ?></h2>
  <?php endif;?>

  <div class="content"><?php print $block->content ?></div>

This basically just emits the block subject and the block content.

Structure of node.tpl.php
In this case, the input is $node, and the subcontent is $content.

<div class="node<?php if ($sticky) { print " sticky"; } ?><?php if (!$status) { print " node-
unpublished"; } ?>">
    <?php if ($picture) {
      print $picture;
    <?php if ($page == 0) { ?><div class="nodeTitle"><a href="<?php print $node_url?>"><?php
print $title?></a></div><?php }; ?>
    <span class="submitted"><?php print $submitted?></span>
    <?php if ($terms) { ?><div class="taxonomy">Tagged: <?php print $terms?></div><?php }; ?>
    <div class="content"><?php print $content?></div>
    <?php if ($links) { ?><div class="nodeLinks"><?php print $links?></div><?php }; ?>

If there is a taxonomy, then the terms are listed before the content. If there are links, they are listed before the
content on page 0, but after the content on page 1.

$page is equal to 0 for all front-like pages (including nodes classified under a specific taxonomy term etc).
Otherwise it is equal to 1. Front-like pages display a list of nodes, while pages with $page == 1 are displaying a
single node. There is also a variable called $is_front that can be checked.

The way that the header and footer meta data for a node is rendered is that these are treated as links on the node and
are located in the global variable $links. Hence they are not specified through the node formatting (which was
typical of the fine-grain decoration through a theme as used in WordPress) but are controlled through the variable
population function.

Using body_classes for dynamic layouts
Drupal 6 provides a new tool for dynamic layouts called $body_classes. This enables the CSS rules of your theme
to be told what sidebars are active, and hence you can have different layout rules for when there is one sidebar, two
sidebars, etc. The previous approach to handling this relied on tables that conditionally rendered content, etc.

To use this, just add $body_classes to the body tag of your page.tpl.php file, as in the following:

Page 40 of 55
         <body class=”<?php print $body_classes; ?>”>

The values of $body_classes include the following:
                       Condition                          Class Available
                       no sidebars                        .no-sidebar
                       one sidebar                        .one-sidebar
                       left sidebar visible               .sidebar-left
                       right sidebar visible              .sidebar-right
                       two sidebars                       .two-sidebars
                       front page                         .front
                       not front page                     .not-front
                       logged in                          .logged-in
                       not logged in                      .not-logged-in
                       page visible                       .page-[page type]
                       node visible                        .node-type-[name of type]

Note that this also enables you to have different layouts for front page and not front page, logged in and not, etc.

Using the template.php file
If you want to override a theme function not included in the basic list (block, box, comment, node, page), you need
to tell PHPTemplate about it.

To do this, you need to create a template.php file in your theme's directory. This file must start with a PHP opening
tag <?php but the close tag is not needed and it is recommended that you omit it. Also included in the file are stubs
for the theme overrides. These stubs instruct the engine what template file to use and which variables to pass to it.

Developing New Modules in Drupal
A Drupal module is simply a collection of files containing a set of routines written in PHP, following a set of
initialization and invocation conventions. When used, the module code executes entirely within the context of the
site. Hence it can use all the functions and access all variables and structures of the main engine. A module is
therefore comparable to a “plug-in” as defined in other environments such as WordPress.

Since the original Drupal code predates the object model of PHP 5, there is no use of classes to scope elements of a
module. Instead, this is carried out by having all of the external identifiers begin with the module name (such as
“association_install”, and having all of the files to be loaded follow naming conventions (such as the main file is
called “association.module”, and the registry information file is called “”, etc.

The module is composed of functions that implement extensions to the standard Drupal framework, and these are
called "hooks" and are defined by a fixed interface. For example these hooks include “<moduleName>_view”,
“<moduleName>_edit”, etc. The basic model is that in places where hooks are made available, the engine calls each
module's exported functions by using reflection.

Key elements of a module include:
     Providing info such as name and requirements
     Installing and uninstalling, including setting up table and removing them
     Implementing hooks that are called by the framework
     Using the presentation and editing features of the framework, including methods l() and t().
     Writing actions
     Packaging the presentation with support files such as CSS, image, and language definitions

Page 41 of 55
This is covered in the “Pro Drupal Development” book, and starts with adding content to the data model. Most of
the modules that are typically added are ones of custom data fetching and editing, such as a event calendaring
system, and appointment system, a set of objects that describe educational classes offered by the an organization,

Where there about 40 different “hook” points to learn, there is an even larger Drupal API of functions which are
callable from your hook code. These are listed at

Examples of hooks include:

hook_block: declare a block or set of blocks.
hook_db_rewrite_sql: rewrite database access queries, usually for acces control
hook_enable: perform necessary actions after module is enabled
hook_menu: define menu items and page callbacks
hook_perm: define user permissions.
hook_user: act on user account actions.

The available hooks include database utilities, lookup utilities, menu management, session management, permission
checking, internationalization, and more. The typical sequence of learning to develop a module begins with creating
a simple module that has a minimum of hooks and uses a minimum of the API, then learning more and of the

For developer support, there is a Drupal module that adds developer tools. Check the “Devel” module at This provides tools that display all queries carried out by a module under
development, a window that displays stack traces, tools to step through the theming logic, and other performance
management tools.

There is a query monitoring facility built right into Drupal, and the Devel module just builds upon it. You can
activate this feature by setting the variable dev_query to 1. As there's no interface to do this, the quickest way is
to set the $conf array in settings.php.

$conf['dev_query'] = 1;

When this variable is set to one, all queries issued via db_query and it's brothers and sisters like
db_query_range, pager_query are gathered in a global variable $queries. Global variables can be
accessed anywhere by declaring the variable as global (again).

function test() {
  global $queries;

And there you have it! All queries are printed out using print_r.

Specifying Module Info
This file is called <moduleName>.info, and contains a set of attributes regarding the module.

All modules must have a file, which contains meta-information about the module. The format of
the file is:
; $Id$
name = Module Name
description = A description of what your module does.
core = 6.x

Page 42 of 55
Without this file, your module will not show up in the Module listing.

Other information which can be specified include the names of the modules upon which this module depends.

Defining Content for a Module
Several approaches, based on using extensions to the basic node.

Create a new content type, use CCK, and other approaches.

Module Schema, installation instructions, and un-installation instructions
Starting in Drupal 6.x, the installation process doesn‟t carry out a SQL statement to create a table (which might be
database-vendor specific), but instead uses a schema definition that is transformed into a database SQL statement.
These are located in the .install file, and are based on defining the following hooks:

hook_install: install the current version of the database schema, and other setup tasks.
hook_schema: define the current version of the database schema.
hook_uninstall: remove any table or variables that the module sets.

An example is shown below:

// Create the database table on install
function tasks_install() {

function tasks_uninstall() {

 * Implementation of hook_schema().
function tasks_schema() {
  $schema['tasks'] = array(
    'fields' => array(
      'vid'    => array('type' => 'int',          'unsigned'   =>   TRUE,   'not null' => TRUE, 'default' => 0),
      'nid'    => array('type' => 'int',          'unsigned'   =>   TRUE,   'not null' => TRUE, 'default' => 0),
      'parent' => array('type' => 'int',          'not null'   =>   TRUE,   'default' => 0),
      'weight' => array('type' => 'int',          'not null'   =>   TRUE,   'default' => 0, 'size' => 'tiny')
    'indexes' => array(
      'nid'    => array('nid'),
      'parent' => array('parent')
    'primary key' => array('vid'),

    return $schema;

This definition, much like the vardef definitions of SugarCRM, allows Drupal to add and remove tables. There is
also a provision for having table references.

Using the Drupal API to Query Content
A block is chunk of PHP code which is run when the block is viewed. Typically the code will use one or more
global variables to determine what to display, perhaps make a database query, and typically use a call the theme()
for the output rendering. Here is an example block that does all of these:

  $sql = "SELECT node.title, node.nid FROM node ORDER BY node.created DESC LIMIT 50";
  $result = db_query($sql);

Page 43 of 55
  $items = array();
  while ($aNode = db_fetch_object($result)) {
    $items[] = l($aNode->title, "node/$aNode->nid");

  return theme("item_list", $items);

The database methods all begin with db_. For instance, to make a database query, use db_query($sqlString), or
db_query_range($sqlString, $start, $count). The latter specifies a range of records (typically for pagination, or for
limiting a result size). Both of these functions return a ResultSet-like object, which you can then iterate over using
db_fetch_object($result), for instance:

while ($row = db_fetch_object($result)) {
      $ids[] = $row->nid;

This shows that the row as being fetched as a PHP Object, for which you can access instance variables using ->
notation. The columns that are to be available must be specified in the query statement.

The SQL statement may be an ordinary SQL statement that you can test in DB-visualizer, for instance.

You can also write the statement more abstractly , and call db_rewrite_sql(). This has the following args:

($query, $primary_table = 'n', $primary_field = 'nid', $args = array())

Use this for listing queries, such as when processing the following query:


Do not use the SQL „FROM table1, table2‟ syntax, use „JOIN ON table2 where‟ instead. SQL_rewrite will process
your query so that it works correctly in the list views, in which the query must have restriction where clauses added
in. The result of this call is the original query with JOIN and WHERE statements inserted when needed. The args
in the db_rewritesql call are specific to where it is being used.

Typically your query will return objects that contain the ids of Drupal nodes, but not the nodes themselves, therefore
you need to call node_load:

node_load(array('nid' => $ids[$i])

The arguments are as follows:
     $param: Either the nid of the node or an array of conditions to match against in the database query
     $revision: Which numbered revision to load. Defaults to the current version.
     $reset: Whether to reset the internal node_load cache.

Using the Drupal API to Present Results, direct and via theming
The theming engine uses methods that begin with “theme”, and have a suffix of a type of object to be themed, such
as “theme_table” or “theme_item_list”. To call them, you create an argument list that matches the theming method,
and then call “theme(<type>, args…)”. This will find the correct theming method, in the current module or the
current theme or the baseline theme, and carry out the rendering. As such, there should be few places in the PHP
code where HTML elements and tag appear.

This also uses the l() function which generates the links in HTML. It also calls the theme engine on the output.

This function correctly handles aliased paths, and allows themes to highlight links to the current page correctly, so
all internal links output by modules should be generated by this function if possible.

Page 44 of 55
        $text: The text to be enclosed within the anchor tag.
        $path: The Drupal path being linked to, such as "admin/content/node". Can be an external or internal URL.
             o If you provide the full URL, it will be considered an external URL.
             o If you provide only the path (e.g. "admin/content/node"), it is considered an internal link. In this
                  case, it must be a system URL as the url() function will generate the alias.
             o If you provide '<front>', it generates a link to the site's base URL (again via the url() function).
             o If you provide a path, and 'alias' is set to TRUE (see below), it is used as is.
        $options: An associative array of additional options, with the following keys:
             o 'attributes' An associative array of HTML attributes to apply to the anchor tag.
             o 'query' A query string to append to the link, or an array of query key/value properties.
             o 'fragment' A fragment identifier (named anchor) to append to the link. Do not include the '#'
             o 'absolute' (default FALSE) Whether to force the output to be an absolute link (beginning with
                  http:). Useful for links that will be displayed outside the site, such as in an RSS feed.
             o 'html' (default FALSE) Whether the title is HTML, or just plain-text. For example for making an
                  image a link, this must be set to TRUE, or else you will see the escaped HTML.
             o 'alias' (default FALSE) Whether the given path is an alias already.

If block code fails, the entire PHP page will be replaced with an error messages, because the all of the block evals
appear to be done before the page assembly starts.

Installing, Enabling and Testing a Module
At this point we have covered enough to create and run a simple module.

To install the module, you'll need to copy your *.module file to the modules directory of your Drupal installation
(which itself can be a subdirectory of your Drupal install or a subdirectory of sites/all or if you are coding a site
specific module for a multisite install then sites/hostname). The file must be installed in this directory or a
subdirectory of the modules directory, and must have the .module name extension and must have a corresponding
.info file.

Log in as your site administrator, and navigate to the modules administration page to get an alphabetical list of
modules. In the menus: Administer » Site building » Modules, or via URL:
When you scroll down, you'll see the new module listed with the description next to it. Enable the module by
selecting the checkbox and save your configuration.

If your module outputs a block, you'll need to also enable it in the blocks administration menu and specify a location
for it to display. Node modules may or may not need further configuration depending on the module. Any module
can have settings, which affect the functionality/display of a module. We'll discuss settings later. For now, navigate
to the blocks administration page: admin/build/block or Administer » Site building » Blocks in the menus.

Enable the module by selecting the enabled checkbox for the new block and save your blocks. Be sure to adjust the
location (left/right) if you are using a theme that limits where blocks are displayed.

Creating a Module Configuration (settings) Page
The module configuration page is described by a link from the hook_menu, and makes use of the Drupal form-
building API.


Page 45 of 55
The forms-building API uses definitions such as:

$form['onthisdate_maxdisp'] = array(
    '#type' => 'textfield',
    '#title' => t('Maximum number of links'),
    '#default_value' => variable_get('onthisdate_maxdisp', 3),
    '#size' => 2,
    '#maxlength' => 2,
    '#description' => t("The maximum number of links to display in the block."),
    '#required' => TRUE,

This would create a text field on the page, with a default value, a description, a length, and an indication that this
field is required.

Generating Page Content
The implementation of a content block can be organized in any of a number of approaches. Typically it will carry
out a query and then collect the results into a string, as shown below:

function onthisdate_all() {
  // content variable that will be returned for display
  $page_content = '';
    $query = "SELECT nid, title, created FROM {node}";
    // get the links (no range limit here)
    $queryResult = db_query($query);
    while ($links = db_fetch_object($queryResult)) {
      $page_content .= l($links->title, 'node/'.$links->nid).'<br />';
    if ($page_content == '') {
      $page_content = "No records found.";
    return $page_content;

However, for complex block or page content, you should call the theming functions as described above.

Note that this function isn‟t actually a hook, function, meaning that Drupal doesn‟t call it directly. See more
information in the next section.

Telling Drupal about the Function
As mentioned previously, the function we just wrote isn't a 'hook': it's not a Drupal recognized name. We need to
tell Drupal how to access the function when displaying a page. We do this with Drupal's hook_menu. Remember
that we have already used hook_menu earlier. The hook_menu defines the association between a URL and the
function that creates the content for that URL. The hook also does permission checking, if desired. We will use the
hook_menu made previously and continue with it.

function onthisdate_menu() {
    $items = array();
    //add this definition
    $items['onthisdate'] = array(
      'title' => 'On this date',
      'page callback' => 'onthisdate_all',
      'access arguments' => array('access onthisdate content'),
      'type' => MENU_CALLBACK
    return $items;

This definition will tell Drupal to call „onthisdate_all‟ when the menu item is invoked.

Page 46 of 55
Using Language and International Facilities
In localizing a site there are four main areas to deal with:
     1. Human-readable formats for data items such as dates and numbers.
     2. The (generally short) text strings used commonly throughout the user interface, for such things as labels on
          form buttons.
     3. Major items of content such as blog articles, informational pages and static blocks.
     4. Theme content. To accomodate different local conventions - and quite often to make room for longer text
          strings - the layout of pages and their components may need to be adjusted.

Drupal provides for the internationalization of such strings with the t() function, meant to be called whenever a
module outputs an English text string. This takes as arguments a string for translation and, optionally, an array of
values to be substituted into it, so for example, you might call it like this:

t('My hat it has @count corners',
The English result when $number_of_corners is 3 would be “My hat it has 3 corners” whereas the German
translation might be “Mein Hut er hat 3 Ecken”.

In Drupal 5, each language had one .po file for download and import for runtime translations and one installer.po
file for installer translation. With Drupal 6, the translation packages themselves will have multiple smaller .po files,
organized by modules and themes. This is good, because the end users see the same files the translators work with
(until we migrate to a web based translation service, see later), so they can contribute back editing those files. But
what's better is that only the .po files for modules and themes users actually install are used by Drupal.

Guide to the Drupal API
The most important guide is the Cheat Sheet for the set of Hooks, which is located at

The various routines of the API fall into the following categories:
                                                                 Functions allowing forms processing to be
                                                                 spread out over several page requests, thus
                                                                 ensuring that the processing does not get
Batch operations             includes/
                                                                 interrupted because of a PHP timeout, while
                                                                 allowing the user to receive feedback on the
                                                                 progress of the ongoing operations.
Database abstraction                                             Allow the use of different database servers
layer                                                            using the same code base.

Default theme                                                    Functions and templates that present output to
implementations                                                  the user, and can be implemented by themes.

Example batch                developer/ examples/
                                                                 Definitions of the batches used in this module.
definitions                  batch_example.module
File interface               includes/                  Common file handling functions.
Form builder                                                     Functions that build an abstract representation
functions                                                        of a HTML form.
                                                                 Functions to enable the processing and display
Form generation              includes/
                                                                 of HTML forms.
                                                                 Functions to format numbers, strings, dates,
Formatting                   includes/
                     modules/ node/
implementations for
user-created content

Page 47 of 55
Hooks                 includes/     Allow modules to interact with the Drupal core.
                                               Drupal's image toolkits provide an abstraction
                                               layer for common image file manipulations like
Image toolkits        includes/      scaling, cropping, and rotating. The abstraction
                                               frees module authors from the need to support
                                               multiple image libraries, and it allows site...
Input validation      includes/     Functions to validate user input.
                                               Define the navigation menus, and route page
Menu system           includes/
                                               requests to code based on URLs.
                      modules/ node/           The node access system determines who can
Node access rights
                      node.module              do what to which nodes.
                                               A Drupal schema definition is an array
                                               structure representing one or more tables and
Schema API            includes/   their related keys and indexes. A schema is
                                               defined by hook_schema(), which usually
                                               lives in a modulename.install file.
                      modules/ search/         The Drupal search interface manages a global
Search interface
                      search.module            search mechanism.

Complex Block example: Display the highest-rated images
  $num_nodes = 3;
  $sql = "SELECT node.nid AS nid, AS users_name,
    users.uid AS users_uid,
    node.title AS node_title,
    node.created AS node_created,
    votingapi_cache_node_percent_vote_average.value AS
 FROM node node
 LEFT JOIN votingapi_cache votingapi_cache_node_percent_vote_average ON node.nid =
votingapi_cache_node_percent_vote_average.content_id AND
(votingapi_cache_node_percent_vote_average.content_type = 'node' AND
votingapi_cache_node_percent_vote_average.value_type = 'percent' AND
votingapi_cache_node_percent_vote_average.tag = 'vote' AND
votingapi_cache_node_percent_vote_average.function = 'average')
 INNER JOIN users users ON node.uid = users.uid
 WHERE (node.status <> 0) AND (node.type in ('image'))
    ORDER BY votingapi_cache_node_percent_vote_average_value DESC
  $result = db_query_range($sql, 0, $num_nodes);
  while ($row = db_fetch_object($result)) {
       $ids[] = $row->nid;
  if (count($ids) > 0) {
     $i = time() % count($ids);
     $node = node_load(array('nid' => $ids[$i]));
     $attributes1['width'] = 450;
     $attributes1['height'] = 313;
     $attributes2['html'] = true;
     $label = 'preview';

     print l(theme('image_display', $node, $label,

Page 48 of 55
                'node/'. $node->nid,
  else { ?>
    <img src="<?php print $front_page; ?>sites/all/themes/yosemite/DefaultImage.jpg"
height="313" border=0 hspace=0 vspace=0>
<?php } ?>

The first part of this code is a query, which joins the node table on the voting api tables. The next part executes the
query, returning up to “n” records, where n is the number of top-rated images to be chosen from. The next part
creates an array of image ids, then selects a random one from it (if any are present). The randomization uses the
mod of the time function.

The final part calls file_create_url(), theme(), and l() to create the output, and supplies a default HTML image
element in case that no rated records were found in the db query.

Checkpoints in Learning and Using Drupal
By this point we have learned the basic operation of Drupal. For instance, as we went through the creating and
editing of blog entries, stories, etc. We understood all of what we were working with on the editing and admin
screens, and how the system was painting/displaying the nodes. For instance, the labeling at the top and bottom of
each entry was as expected, and the decoration around the list of entries was as expected. The permissions and
configuration options were as expected.

We have activated Blog, Path, Statistics, Search, TinyMCE, Upload, Profile, Book, and Views. Next ones to try out
would be Forum, and Poll. All of these modules are in the standard distribution except for TinyMCE and Views.

Likewise, all of the configuration options were clear to me, and we could find them on either the “Administrate by
tasks” view or the “Administrate by modules” view. Plus, the TinyMCE made it easy to apply changes, the statistics
were working, and some categories were defined, populated, required, and multi-selectable.

Switched back to the Garland theme, since Barron didn‟t work correctly in Safari. TinyMCE is still reported to have
problems in Safari, but we didn‟t notice them.

We have also been working with both the Garland theme (particularly now that we have changed the colors) and the
Barron theme. We‟ve tweaked Barron to give more text space for a content-richer site. Fixed Barron for use in

Completed tests of the Forum, Poll, and News Aggregator modules. Have begun to look into the data model to
understand the table structure.

Now using the Archives module, which is not a built-in module. The current version is different from the 4.7
version shown in the book - it doesn‟t have a way to navigate to other months.

Now trying out CCK, which is the successor to the flexinode module. Have also reviewed the “Drupal Learning
curve” diagram, and found that we are about 75% through it. The main steps to undertake to cover the rest would be
to develop a new theme or a new module. The main item that puzzled me recently is how to get a theme screen
output that shows multiple lists of nodes, however the Views module seems to provide this.

The combination of CCK and Views enables me to create tabular displays, like with ExpressionEngine. However,
the presentation control is limited. Although the theme wizard helps, it still appears that the developer needs to

Page 49 of 55
write the .tpl file and the .css file and store them into the file system manually. Facilities in WordPress allow the
files to be edited through the application, and facilities in ExpressionEngine appear to take care of all of this
processing, with template files that include loops and macro expansion. The remaining approach is to use a module
called Context Template.

Why do WordPress and ExpressionEngine appear to be better than Drupal? Partly it is because of the ease of
creating content, the better layout of the editing/admin screens, etc. Also, the WYSIWYG text editing is much
better, and the process of writing themes appears to be more accessible (though actual amount of code to craft in
Drupal is less).

Strengths of Drupal: this is a full system of content management functionality. It can be used for a community,
because you can login and maintain a session or profile. In WordPress, you are just looking at the contents of the
posting table, and there is no facility to manage users or interact with users.

It seems that in order to focus our work on Drupal, we should generate a theme that is high enough quality, improve
the text editing, and see if the content management and navigation facilities can be improved.

Started creating example theme. Created file style.css, and file page.tpl.php. This was enough to get started. Also
created the .png screen shot files. The smaller one appeared in the theme selector screen.

The page.tpl.php file is similar to index.php in WordPress, however, it prints $content for the loop over the content
nodes. The loop is not visible.

Then we simplified the header area to take out extra <div>s, and wrote up a simple .css with different colors in each
layout area (container, header, nav, content, sidebar, footer, etc.). Soon had a screen on display, and then reworked
the color and image management. As with WordPress, all of the images used in the theme are in /images, except for
the screenshots, but in Drupal, you put the „druplicon‟ logo file directly in the theme‟s directory rather than the
image directory.

After reviewing the node.tpl.php and block.tpl.php files, we understood them, and created corresponding CSS rules
for these layout areas.

Soon had the sidenav, block and node level areas marked off with borders. The rest fell into place over the next 2
hours. By putting a view into a block, we were able to generate multiple areas on the page that had query results for
their content.

After spending four days working on WordPress themes, we switched back to Drupal, and updated to 6.0RC1.
There were a few differences in the theming code, but otherwise it worked fine.

Note: there is a “book” of information on Drupal 6 theming at The theme facilities
have been greatly extended.

Learned how the theme callbacks work. You can call theme(“name”, list) at any time to run a function. There are
built in functions for most theme callbacks, such as one that generate a list of links. There is a hierarchy of

Spent a few hours getting the Drupal theme to look just like the “Insignia” theme for WordPress that we had made
earlier. Insignia now has all of the functionality of Barron. In the node rendering, there are divs for node, nodeTitle,
submitted, taxonomy, content, and nodeLinks. The correspondence is: node=post, nodeTitle=post h2,
submitted=nodeheader, content=nodecontents, nodeLinks=nodefooter. This is using the default copy of
node.tpl.php. We could change them to align the conventions with our WordPress themes even further, but this is
not critical.

Page 50 of 55
The question is where does the text come from for “submitted” and “nodeLinks”? They are from the variables
$submitted, and $links which were generated before the theme engine got to process the text. In version 5, this is
hard to alter, but Drupal 6 introduces the concept of a theme preprocess function. In short, it allows themes, theme
engines, and even modules to step into the theming process and manipulate the variables that get sent to a template.

We reviewed the list of variables that already exist, and found that most are quite useful. One useful one is the
“zebra” variable, which toggles from “even” to “odd” and back, in order to flip between different CSS rules that
change colors for every other horizontal stripe in a table, for instance.

In the processing functions, the input is a keyed array (hashmap), and the output is a modified keyed array. The
node is available with the key “node”.

Another way to get context information in a preprocessing function is to use to the arg() function. This decodes the
URL, which is a global somewhere in the PHP request processing infrastructure. The arg function gives us the
Drupal path of the current page as component bits. For /node/3, the arg function returns arg(0) = node and arg(1) =
3. Even if the page is accessed via /about, the arg function returns arg(0) = node and arg(1) = 3. To get the Drupal
path as a string, you can use $_GET['q'], which would return the string /node/3.

Now starting to look into module development, starting with the “Archive” module. We‟ve been learning more
about theming and about nodes and blocks, even submitted suggestions for code changes to the Drupal web site.

Created an example block, one that fetches and displays a list of nodes.

Pending patch in modules/comment/comment.module:

function theme_comment_submitted($comment) {
  return t('Submitted by !username on @datetime.',
      '!username' => theme('username', $comment),
      '@datetime' => format_date($comment->timestamp)

Remove the period after @datetime.

Also, looking into the issue of “how to change theme or color for different parts of the site?”. One approach is to
use the Taxonomy Theme module, which associates taxonomy keywords with theme names. A related approach
would be to have the set of themes organized into a main theme and them subthemes, so that only the color
specification would have to change.

           Turn on Taxonomy, classify Brandon‟s pages
           Create a subtheme of Barron or Insignia
           Try out Taxonomy Theme module

Updating this document for changes in Drupal 6, and the reviews of the updated edition of the Mercer book. There
were two patch updates for Drupal during the spring, called 6.1 and 6.2.

Continuing to update this document for Drupal 6, and recently introduced books. It appears that Drupal is gaining a
good following. We are now on Drupal 6.3. We have done a fresh install for the Risberg Family site. We have also
switched from using Bluemarine to using Garland for the administration theme.

Page 51 of 55
Rebuilding the site has meant that we have taken out a number of modules that were pre-release for Drupal 6.x, such
as early versions of Views and CCK, and can start over on learning the latest versions of these. We also deleted
some old content that was about the Woods project, which stemmed from a test for the project team back in October

Now trying theme “Pluralism”. This looked good, but we had trouble making it wider.

When trying to fix the problem with the scrolling in theme Baron, we have noticed the following: the approach to
having a scroll header on a web page is to use a table and a fieldset.

Had more success with the Views 2 module, after watching a demonstration video. To create a view, select
Administration->Views->Add. Provide a name, and then select the primary object, such as Node or User. Click

We created a view that shows published pages and a view that shows the list of registered users. Here is the
configuration of the second one:

Tonight we re-read the Mercer book, but didn‟t learn too much new information. The book spent a great deal of
time on some of the more basic modules, such as paths and archives, plus had material on configuring blocks and
menus. The most useful part is probably the taxonomy part, for projects in which such actually gets built up (it still
seems like it would take quite a while to build up a complex taxonomy).

Upon checking WordPress again, it seems that the editing environment for postings is much better in WordPress, as
there is support for WYSISWYG editing; spell checking; and image management.

Drupal has won a key award in the reviews of open source CMS software, sponsored by Packt Publishing.

When looking for information on writing Drupal modules, given our experience with SugarCRM, we noticed that
the schema description approach is very similar. We are now starting to write a to-do list manager module, using
facilities from the Drupal 5.7 ToDo list manager module, and the 6.x Announcements module.

When trying to update a module from 5.x to 6.x we had to change the following:
    db_num_rows replaced by a “select count(*)” call on db_query
    Change to arguments of l().

We am now looking into the Notifications module for sending email, and also comparing the Drupal framework
code with the Zend framework code. It appears that Drupal is ahead in its interactive database management and
forms management facilities, as it was quite easy to define a new table, and create list, detail, and edit views.

We am now trying out different themes, such as Four Seasons, which we liked a lot. It has left and right sidebars,
and an admin switcher that allows for changes of color and font (though we disabled this at the moment). We are
also trying out the Image module and the Lightbox module.

We have now switched to Drupal 6.9, and are testing some of the modules indicated in the “Using Drupal” book,
such as Markdown, and applying the techniques listed in the book to create a wiki page content type. Have also
installed Views2-6.x-2.2, as that is the “most recommended” module, and used that to create a custom view of

Page 52 of 55
As we work on the Drupal-based project for Yosemite Association, these links to articles about how Drupal sites
were built for churches have been relevant:
     - this is for a church in Huntsville Alabama. Built with version 4.7.3 and
         using about 20 add-on modules. The theme is built from the Foundation theme.
     - this is for a church in Beaumont, Texas. Built with version 6.9 and using
         only 5-6 add-on modules. The theme is built from the Foundation theme.
     - this is a developer‟s journal from a Drupal module developer, as she
         went about setting up a site for her church.

Began to evaluate the Foundation theme. It is very simple, with almost no graphics or complex CSS. Only 15K
total size. This is a liquid layout theme that handles layout for one, two, and three columns based on which blocks
are enabled using CSS, not tables.

The theme includes one extra region (called ContentTop) to place blocks above the page content, as well as below it.
The regions are:
         regions[left] = Left sidebar
         regions[right] = Right sidebar
         regions[contenttop] = Content Top
         regions[content] = Content
         regions[header] = Header
         regions[footer] = Footer

Consists of only the following files:

The CSS rules are broken down into sets corresponding to the templates, such as ones for the page layout, for a
block, for a box, for a node, and for a comment. Then there are three sets of optional rules for variations on the page

First version of Yosemite Association collaboration site was demonstrated today. Incorporated a theme based on
Foundation, modules such as the Fivestar rating facility, the Pathauto facility, and a custom front page. Also began
to look at Calendars and integrating views into pages.

Began to evaluate the Insert View module. This enables you to write the text of a page, and then place a reference to
a defined view anywhere in the text. After that we began to evaluate the Organic Groups module and the Calendar
Module. These were very powerful, and we integrated both.

Have now finished the second version of the YA site. Besides completing the calendar integration, we created
CCK-based node class for a visit description, and used Views to view it. It is pretty clear now that CCK and Views

Page 53 of 55
have dramatically changed the landscape of using Drupal, and we have updated this document in several places to
reflect that.

Based on notes in the “Using Drupal” book, we have evaluated the “Administration Menus” and the “CSS Injector”
modules, as well as the “Nitobe” theme (this theme has a set of clean-layout boxes, with a rotating header of
different images at the top). The book also recommended FCKEditor over TinyMCE.

Also tried out the “Zen” theme, and figured out how to control the visibility of calendar events by changing the
permission of the content_date field. If this field is not visible, then no events will appear on the calendar.

Currently looking into how to control “sessions” in Drupal. For instance, suppose that you wanted to filter by two
orthogonal types, selected on two different submits. We know how to do this in PHP using sessions, but it appears
in Drupal everything must be part of the query string of the URL.

Tried out the “A3 Atlantis” theme, and reviewed examples of geoprocessing in Drupal. The modules to use are
“Location”, and “GMap”. We tried each one of these.

Now reviewing the “Menu Block” module, and the “Service Links” module. The former provides a configurable
display of a part of the menu tree system, located in a block (so you can place it anywhere on the page), and the
latter adds buttons to connect to Digg and other services. Within a day, we added both of these to the Yosemite
Association site.

Documenting the solution to having an image at the top of the page that is selected from the “best rated” query.

Migrated discussion of specific sites out into a separate document, “Notes on Drupal Sites”.

Starting to try out the Panels module.

It has been a year of carrying out maintenance updates on our Drupal 6 sites, but today we began to try out Drupal 7,
which was released a week ago.

Updated our sites to 6.20, which is probably going to be the final version of 6.

Began to try out jQuery UI module. This could be used in a theme to provide nice effects. However, the jQuery
version used in Drupal 6.x is 1.2.6, which is quite old compared to our other coding projects, so we skipped working
on this. Drupal 7.x has jQuery 1.5.2, which is up to date.

Begin to try out Nice Menus and Google Analytics modules.

Appendix A: The Drupal Association
The Drupal Association is an organization dedicated to helping the open-source Drupal CMS project flourish. It
helps the Drupal community with funding, infrastructure, events, promotion and distribution. It was organized in
2006, and is a registered non-profit in Belgium.

Page 54 of 55
Creating the Drupal Association opens up a number of opportunities for the project. For example, donations may be
given to the project through a central entity, rather than to individual community members. By handling
administrative tasks, such as event management, this frees resources within the community to focus on improving
the Drupal project. It also provides the opportunity for individuals and businesses to be formally recognized as
supporters of the project.

There are currently over 1000 members in the Drupal Association. Their three most recent conferences were
Drupalcon Boston 2008 (March 2008), which attracted over 800 people; Drupalcon Szeged 2008 (held in Europe in
late August 2008), had an attendance of 500; and Drupalcon Washington DC 2009 (March 2009) which had an
attendance of over 1000.

Annual dues for the Drupal Association are 22 euros for an individual, and 73 euros for an organization. The direct
benefit is that you get to use the Drupal Association logos on your web site.

Page 55 of 55

To top