Drupal 7 Module Development


Drupal 7 Module Development
eBook: $26.99
Formats: PDF, PacktLib, ePub and Mobi formats
$22.94
save 15%!
Print + free eBook + free PacktLib access to the book: $71.98    Print cover: $44.99
$40.49
save 44%!
Free Shipping!
UK, US, Europe and selected countries in Asia.
Also available on:
Overview
Table of Contents
Author
Reviews
Support
Sample Chapters
  • Specifically written for Drupal 7 development
  • Write your own Drupal modules, themes, and libraries
  • Discover the powerful new tools introduced in Drupal 7
  • Learn the programming secrets of six experienced Drupal developers
  • Get practical with this book's project-based format

Book Details

Language : English
Paperback : 420 pages [ 235mm x 191mm ]
Release Date : December 2010
ISBN : 1849511160
ISBN 13 : 9781849511162
Author(s) : Matt Butcher, Larry Garfield, John Wilkins, Matt Farina, Ken Rickard, Greg Dunlap
Topics and Technologies : All Books, CMS and eCommerce, Content Management (CMS), Drupal, Open Source, PHP

Table of Contents

Preface
Chapter 1: Developing for Drupal 7
Chapter 2: Creating Your First Module
Chapter 3: Drupal's Theme Layer
Chapter 4: Theming a Module
Chapter 5: Building an Admin Interface
Chapter 6: Working with Content
Chapter 7: Creating New Fields
Chapter 8: Drupal Permissions and Security
Chapter 9: Node Access
Chapter 10: JavaScript in Drupal
Chapter 11: Working with Files and Images
Chapter 12: Installation Profiles
Appendix A: Database Access
Appendix B: Security
Index
  • Chapter 1: Developing for Drupal 7
    • Introducing Drupal (for developers)
      • Technologies that drive Drupal
        • PHP
        • Databases and MySQL
        • HTML, CSS, and JavaScript
        • Other technologies
        • The web server
        • The Operating System
    • Drupal architecture
      • Drupal core libraries
      • Drupal hooks
      • Drupal core modules
      • The database
      • The theme system
    • Drupal's major subsystems
      • Themes
      • Menus
      • Nodes
      • Files
      • Users
      • Comments
      • Fields and entities
      • Forms API
      • Installation Profiles
      • Simple test
      • Blocks
      • Other subsystems
    • Tools for developing Drupal code
      • Version control with Git and CVS
        • The book's code and Git
      • The API site and coding standards
      • Developer-oriented modules
        • The developer module
        • Drush (the Drupal shell)
        • Coder
    • Summary
    • Chapter 2: Creating Your First Module
      • Our goal: a module with a block
      • Creating a new module
        • Module names
        • Where does our module go?
        • Creating the module directory
        • Writing the .info file
        • Creating a module file
          • Source code standards
          • Doxygen-style doc blocks
          • The help hook
          • The t() function and translations
      • Working with the Block API
        • The block info hook
        • The block view hook
        • The first module in action
      • Writing automated tests
        • Creating a test
          • Starting out
          • Writing a test case
          • The basic pattern
          • The getInfo() method
          • Setting up the test case
          • Writing a test method
      • Summary
      • Chapter 3: Drupal's Theme Layer
        • Business logic versus presentation logic
        • Data granularity
        • Theme engines
        • Two ways to theme
          • Theme functions
            • Preprocess functions
            • Theme overrides
          • Template files
            • The preprocess zoo
        • Render elements
          • Render properties
          • hook_element_info
          • hook_page_alter()
        • The power of theme()
          • Theme hook suggestions
        • Theme registry
          • Variable default values
          • hook_theme
          • hook_theme_registry_alter
        • What else?
        • Summary
        • Chapter 4: Theming a Module
          • Reusing a default theme implementation
            • Drupal blocks revisited
            • Theming a Drupal block
            • Render element and a theme hook suggestion
            • Creating a pre_render function
            • Attaching CSS to render arrays
            • RTL languages
          • Steps to build a default theme implementation
            • hook_theme() implementations
            • Variables versus render element
            • Preprocess functions
            • Template files
          • Summary
          • Chapter 5: Building an Admin Interface
            • The User Warn module
            • Starting our module
            • The Drupal menu system
              • Defining a page callback with hook_menu
              • Using wildcards in menu paths
            • Form API
              • Using drupal_get_form()
              • Building a form callback function
              • Managing persistent data
              • Form submission process
              • A shortcut for system settings
              • A shortcut for confirmation forms
            • Sending mail with drupal_mail() and hook_mail()
              • Calling drupal_mail()
              • Implementing hook_mail()
            • The token system
              • What are tokens?
              • Implementing tokens in your text
            • Summary
            • Chapter 6: Working with Content
              • Why create your own entities
              • The goal
              • Bundles
              • The Schema API
              • Declaring our entity
                • The entity declaration
                • The entity controller
              • Entity management
                • Managing artwork types
                • Adding artworks
                  • Adding new artwork
                  • Validation callback
                  • Submit callback
                  • Saving your artwork
                  • Handling revisions
                • Viewing artworks
                • Editing an artwork
                • Deleting an artwork
              • Summary
              • Chapter 7: Creating New Fields
                • Our goal: a "dimensions" field
                • How Field API works
                • Creating our new field type
                  • Declaring the field
                  • Defining the field structure
                  • Defining empty
                  • Field settings
                  • Field validation
                • Exposing fields to the Form API with widgets
                  • Declaring a widget
                  • Simple widget forms
                  • Complex widgets
                • Using formatters to display our field
                  • Declaring a formatter
                  • Single-value formatters
                  • Complex formatters
                • Managing non-Field fields
                • Finding entities and fields
                • Summary
                • Chapter 8: Drupal Permissions and Security
                  • Using user_access() to assert permissions
                  • Checking the proper user account
                  • Using hook_permission()
                    • Defining your module's permissions
                    • Writing hook_permission()
                  • Declaring your own access functions
                  • Responding when access is denied
                  • Enabling permissions programmatically
                  • Defining roles programmatically
                  • Securing forms in Drupal
                    • The Forms API
                    • Disabling form elements
                    • Passing secure data via forms
                    • Running access checks on forms
                  • Handling AJAX callbacks securely
                    • Using AJAX in forms
                    • Using AJAX in other contexts
                  • Summary
                  • Chapter 9: Node Access
                    • Node Access compared to user_access() and other permission checks
                      • How Drupal grants node permissions
                      • The node_access() function
                        • The access whitelist
                        • Caching the result for performance
                        • Invoking hook_node_access()
                        • Access to a user's own nodes
                        • Invoking the node access API
                      • hook_node_access() compared to {node_access}
                    • Using hook_node_access()
                      • A sample access control module
                      • A second access control module
                      • View operations and access control modules
                    • When to write a node access module
                      • The {node_access} table and its role
                      • {node_access} table schema explained
                      • Defining your module's access rules
                    • Creating the role access module
                      • Using hook_node_access_records()
                      • Using hook_node_grants()
                      • Security considerations
                      • Rebuilding the {node_access} table
                    • Modifying the behavior of other modules
                      • Using hook_node_grants_alter()
                      • Using hook_node_access_records_alter()
                    • Testing and debugging your module
                      • Using Devel Node Access
                        • Using hook_node_access_explain()
                        • Using the Devel Node Access by user block
                    • Summary
                    • Chapter 10: JavaScript in Drupal
                      • JavaScript inside Drupal
                      • Adding JavaScript
                        • Adding JavaScript and CSS files to .info files
                        • Using drupal_add_js()
                          • Adding JavaScript files
                          • Adding CSS files
                          • Passing variables from PHP to JavaScript
                          • Adding inline JavaScript
                          • Adding inline CSS
                        • Using the Library API
                          • Defining a library with hook_library
                          • Altering information in hook_library
                        • Using renderable arrays
                      • Altering JavaScript
                        • Altering CSS
                      • Drupal specific JavaScript
                        • Themeable presentation
                        • Translatable strings
                        • Behaviors
                      • AJAX helpers
                        • Adding AJAX to forms
                        • AJAX automatically applied
                        • AJAX commands
                          • ajax_command_after
                          • ajax_command_alert
                          • ajax_command_append
                          • ajax_command_before
                          • ajax_command_changed
                          • ajax_command_css
                          • ajax_command_data
                          • ajax_command_html
                          • ajax_command_prepend
                          • ajax_command_remove
                          • ajax_command_replace
                          • ajax_command_restripe
                          • ajax_command_settings
                      • Summary
                      • Chapter 11: Working with Files and Images
                        • The Twitpic and watermark modules
                        • Files in Drupal
                        • File API
                        • Stream wrappers
                          • Creating a stream wrapper
                        • Images in Drupal
                          • Image API
                          • Image Styles
                          • Creating image effects
                          • Creating image styles from a module
                        • Summary
                        • Chapter 12: Installation Profiles
                          • Introducing installation profiles
                          • Drupal distributions
                            • Setting up a distribution
                            • Standard and minimal profiles
                            • Creating a profile directory
                            • Profile modules and themes
                          • Creating profiles
                            • Enabling modules
                            • The install task system
                            • Choosing an install task or using hook_install
                            • Anatomy of an install task
                            • Creating a task
                            • Altering tasks
                            • Configuring blocks
                            • Variable settings
                            • Text filters
                            • Code placement
                          • Running the installer from the command line
                          • Summary
                          • Appendix A: Database Access
                            • Basic queries
                            • Result objects
                            • Dynamic queries
                            • Insert queries
                            • Update queries
                            • Delete queries
                            • Merge queries
                            • Advanced subjects
                              • Transactions
                              • Slave servers
                            • Summary
                            • Appendix B: Security
                              • Thinking securely
                              • Filtering versus escaping
                                • Filtering
                                • Escaping HTML
                                • SQL injection
                              • Node access control
                              • Handling insecure code
                              • Staying up to date
                              • Summary

                              Matt Butcher

                              Matt is a web developer and author. He has previously written five other books for Packt, including two others on Drupal. He is a senior developer for the New York Times Company, where he works on ConsumerSearch.com, one of the most traffic-heavy Drupal sites in the world. He is the maintainer of multiple Drupal modules and also heads QueryPath – a jQuery-like PHP library. He blogs occasionally athttp://technosophos.com.

                               


                              Larry Garfield

                              Larry Garfield has been a PHP developer for over a decade and a Drupal developer for half a decade. He is currently a Senior Architect and Consultant with Palantir.net, a leading Drupal development firm specializing in institutional non-profit clients. Larry is also the Drupal database maintainer and maintainer of many Drupal modules, and was one of the lead organizers of the GoPHP5 project. He writes about Drupal and, occasionally, other technical subjects at http://www.garfieldtech.com/


                              John Wilkins

                              John Wilkins has been a web developer for a long time. In April 1993, he was one of the lucky few to use the very first graphical web browser, Mosaic 1.0, and he’s been doing web development professionally since 1994. In 2005, John finally learned how idiotic it is to build your own web application framework and discovered the power of Drupal; he never looked back.

                              In the Drupal community, he is best known as JohnAlbin, one of the top 20 contributors to Drupal 7 and the maintainer of the Zen theme, which is a highly-documented, feature-rich “starter” theme with a powerfully flexible CSS framework. He has also written several front-end-oriented utility modules, such as the Menu Block module. John currently works with a bunch of really cool Drupal developers, designers, and themers at Palantir.net.


                              Matt Farina

                              Matt Farina is a senior Front End Developer and Engineer at Palantir.net, a Chicago-based firm that specializes in Drupal development. At Palantir.net, he works on a wide variety of projects ranging from museums to large interactive sites, including OpenSource.com. He is a contributor to Drupal code as well as a maintainer of multiple Drupal modules.

                              Prior to doing Drupal development full time, Matt worked in the defense industry for General Dynamics Land Systems. At General Dynamics he started as a Diagnostics and Testability Engineer. He eventually transitioned into the role of a Software Engineer building internal web based tools.


                              Ken Rickard

                              Ken Rickard is a senior programmer at Palantir.net, a Chicago-based firm specializing in developing Drupal web sites. He is a frequent contributor to the Drupal project and is the maintainer of the Domain Access, MySite and Menu Node API modules. At Palantir, he architects and builds large-scale web sites for a diverse range of customers, including Foreign Affairs magazine, NASCAR and the University of Chicago.

                              From 1998 through 2008, Ken worked in the newspaper industry, beginning his career managing web sites and later becoming a researcher and consultant for Morris DigitalWorks. At Morris, Ken helped launch BlufftonToday.com, the first newspaper web site launched on the Drupal platform. He later led the Drupal development team for SavannahNOW.com. He co-founded the Newspapers on Drupal group (http://groups.drupal.org/newspapers-on-drupal) and is a frequent advisor to the newspaper and publishing industries.

                              In 2008, Ken helped start the Knight Drupal Initiative, an open grant process for Drupal development, funded by the John L. and James S. Knight Foundation. He is also a member of the advisory board of PBS Engage, a Knight Foundation project to bring social media to the Public Broadcasting Service.

                              Prior to this book, Ken was a Technical Reviewer for Packt Publishing’s Drupal 6 Site Blueprints by Timi Ogunjobi.

                               


                              Greg Dunlap

                              Greg Dunlap is a software engineer based in Stockholm, Sweden. Over the past 15 years Greg has been involved in a wide variety of projects including desktop database applications, kiosks, embedded software for pinball and slot machines, and websites in over a dozen programming languages. Greg has been heavily involved with Drupal for three years, and is the maintainer of the Deploy and Services modules as well as a frequent speaker at Drupal conferences. Greg is currently Principal Software Developer at NodeOne.

                              Several people played crucial roles in my development as a Drupal contributor, providing support and encouragement just when I needed it most. My deepest gratitude to Gary Love, Jeff Eaton, Boris Mann, Angie Byron and Ken Rickard for helping me kick it up a notch. Extra special thanks to the lovely Roya Naini for putting up with lost nights and weekends in the service of finishing my chapters.

                              Code Downloads

                              Download the code and support files for this book.


                              Submit Errata

                              Please let us know if you have found any errors not listed on this list by completing our errata submission form. Our editors will check them and add them to this list. Thank you.


                              Errata

                              - 35 submitted: last submission 15 Oct 2013

                              Errata type: grammar | Page numbers: given below

                              Drupal 5.1 should be PHP 5.1

                              pg 16, However, Not should be However, not

                              pg 17, it's own data should be its own data

                              pg 25, architecture advanced should be advanced architechture

                              Errata type: grammar | Page numbers: given below

                              pg 29, an equal sign should be an equal sign

                              pg 41, the the should be the

                              pg 146, exercising every should be exercising of every

                              pg 84, its should be their

                              pg 90 and 98, then should be than

                              pg 108, you will be passed to should be you will be passing to

                              pg 235, FormsAPI should be Forms API

                              pg 291, ever page should be every page

                              pg 311, html should be HTML

                              pg 318, is to associate should be to associate

                              pg 326, how to we might integrate should be how we might integrate

                              pg 326, let's make create should be let's create

                              pg 376, many of types of input should be many types of input

                              pg 8, has lead many to claim should be has led many to claim

                               

                               

                               

                              pg 145, $message['body] should be $message['body']

                              Errata Type: Code page no:189

                              In the signature of the 'dimfield_field_validate()' function, replace &$items with $items (no ampersand).

                              Page numbers : 52,57

                              1. First non-note line, word "test" has second t in wrong font.
                              2. Sentence "Note that each..." should end "split into two lines for clarity.

                              Errata type: Code | Page number: 308

                              $page = array('#type' =>'ajax_commands', '#ajax_commands' => $commands);
                              should read:
                              $page = array('#type' => 'ajax', '#commands' => $commands);

                               

                              Errata Type: Code Page No:189

                              In the code: if ($field['type'] == 'dimensions')'' { should be: if ($field['type'] == 'dimensions') { It is correct in the supplied code.

                              Errata Type:Website link Page No:43

                              The link "http://api.drupal.org/api/drupal/developer--examples--block_example.module/7" is incorrect.

                              The actual URL is http://api.drupal.org/api/examples/block_example--block_example.module/7

                              Errata Type:Code Page No:197

                              $language = $values['language']; should be $language = $element['#language'];

                              Errata Type:Code Page No:51

                              Instead of - Add a getInfo() function. It should be - Add a getInfo() method

                              Errata Type: Grammar Page No:17

                              The errata listed for page 17 that says "The principle way should be principal" is wrong. 'Principal' is a noun (sometimes used as an adjective), which make it incorrect in this situation. The original usage (The principle way) is correct and the errata comment should be removed.

                              Errata Type:Code Page No:366

                              In the query code the line that says: $query->fields('n', array('nid, title'));

                              should be

                              $query->fields('n', array('nid', 'title'));

                              Errata Type: Page No:

                              It's impossible to add artworks because the access right is mispelled : 'access arguments' => array('create artwork') This should be : 'access arguments' => array('create artworks')

                              Errata Type: Version of software Page no:32

                              Drupal does now require PHP 5.2.6 or greater, with 5.3.x recommended.

                              Errata Type:Screenshot Page No:38

                              The final screenshot that made it into the book was incorrect. The text matches the current version of Drupal, not the pre-release version shown in the figure.

                              Errata Type:URL Page No:43

                              The new URL for the block example module is: http://api.drupal.org/api/examples/block_example--block_example.module/7

                              Errata Type:code page No:166

                              It's impossible to add artworks because the access right is mispelled : 'access arguments' => array('create artwork') This should be : 'access arguments' => array('create artworks')

                              Errata Type:code page No:308

                              $page = array('#type' => 'ajax_commands', '#ajax_commands' => $commands); should be $page = array('#type' => 'ajax', '#commands' => $commands);

                              Errata Type:code Page No:366

                              In the query code the line that says: $query->fields('n', array('nid, title')); should be $query->fields('n', array('nid', 'title'));

                              Errata Type:code Page No:192-193

                              The code is incorrect. In most cases it will work. However, if and instance of the field for which the widget is begin defined is set to an unlimited cardinality, then, when editing content, the field order will be reversed. See discussion at http://drupal.org/node/1292844.

                              Errata Type:code Page No:189

                              In the signature of the 'dimfield_field_validate()' function, replace &$items with $items (no ampersand).

                              Errata Type:code PageNo:189

                              In the code: if ($field['type'] == 'dimensions')'' { should be: if ($field['type'] == 'dimensions') { It is correct in the supplied code.

                              Errata Type:code Page No:51

                              Should be - Add a getInfo() method instead of - Add a getInfo() function

                              Errata Type:typo Page No:115

                              Filename should be single_blog_block_item.tpl.php not single-blog-block-item.tpl.php

                              Errata Type:code Page No:308

                              $page = array('#type' => 'ajax_commands', '#ajax_commands' => $commands); should be $page = array('#type' => 'ajax', '#commands' => $commands); Read the API: http://api.drupal.org/api/examples/ajax_example--ajax_example_misc.inc/7/source

                              Errata type:code pg No:197

                              $language = $values['language']; differs from downloaded code where it is listed as $language = $element['#language']; in the downloaded code, which appears to be correct

                              Errata type:code No:180

                              [in the code] module_invoke_all('entity_delete', $artwork, 'artwork'); should be called inside foreach($artworks as $artwork_id => $artwork) cycle (otherwise it works only for sigle delete)

                              Errata type:code No:197

                              near top of page, $language = $values['language']; should be $language = $element['#language'];

                              Errata type:typo No:43

                              Please describe the errata.: The link "http://api.drupal.org/api/drupal/developer--examples--block_example.module/7" is incorrect. The actual URL is http://api.drupal.org/api/examples/block_example--block_example.module/7

                              Errata type:typo Page No:138

                              When adding system_settings_form() functionality to the user_warn settings form, the variable_get() calls to retrieve the current value of the variables was removed, but system_settings_form() does not replace this functionality.

                              Errata type:typo Page No:3

                              Who this book is for should be Whom this book is for

                              Errata type:typo Page No:29

                              The line in the book says 'and equal sign.' The errata says (copy/paste): pg 29, an equal sign should be an equal sign The correct correction is 'and s/b an'.

                              Errata type: Others

                              Page number: 43 - For printed book readers

                              Page number: 63 - For digital e-book readers

                              Tip Box: The entire Block API is documented in the official Drupal 7 API documentation, and even includes an example module: http://api.drupal.org/api/drupal/developer--examples--block_example.module/7.

                              The link mentioned in the tip is not working. Here is the new link:
                              http://api.drupal.org/api/drupal/modules%21block%21block.api.php/7

                              Errata type:typo | Page No:29

                              In the downloaded code: twitpic.module (~line 142)

                              Last line of function twitpic_image_style:

                              return theme('image_style', array('path' => $local_path));

                              should be

                              return theme('image_style', array('path' => $local_path,'style_name' => $style));

                              then path twitpic/style/[ID]/[STYLE] will work.

                              Errata type: Code | Page number: 189

                              The Field Validation section

                              dimfield_field_validate() needs to be updated:

                              $errors[$field['field_name']][$delta][] should have [$langcode] inserted  between the 'field_name' and $delta arrays, the result of which is  $errors[$field['field_name']][$langcode][$delta][]

                              On Drupal 7.22, without the additional $langcode array level, everything will  pass validation.  See the API for hook_field_validate().

                              Sample chapters

                              You can view our sample chapters and prefaces of this title on PacktLib or download sample chapters in PDF format.

                              Frequently bought together

                              Drupal 7 Module Development +    Drupal 7 Development by Example Beginner’s Guide =
                              50% Off
                              the second eBook
                              Price for both: £24.65

                              Buy both these recommended eBooks together and get 50% off the cheapest eBook.

                              What you will learn from this book

                              • Build modules extending Drupal's core functionality
                              • Create custom content types and entities
                              • Learn how to work with Drupal's hook system
                              • Explore the major APIs introduced in Drupal 7 that the pros use to build successful Drupal websites
                              • Test your code programatically with Drupal's new Simple Test framework
                              • Build and extend themes to make your Drupal 7 shine
                              • Author interactive form-based tools with Drupal's Forms API
                              • Apply the principals of Test Drive Development (TDD) using Drupal's built-in SimpleTest framework
                              • Leverage the book's working module examples as a starting point for you own code
                              • Discover the secrets of Drupal professionals as they explain the practical aspects of good Drupal development

                              In Detail

                              Drupal is an award-winning open-source Content Management System. It's a modular system, with an elegant hook-based architecture, and great code. Modules are plugins for Drupal that extend, build or enhance Drupal core functionality.

                              In Drupal 7 Module development book, six professional Drupal developers use a practical, example-based approach to introduce PHP developers to the powerful new Drupal 7 tools, APIs, and strategies for writing custom Drupal code.

                              These tools not only make management and maintenance of websites much easier, but they are also great fun to play around with and amazingly easy to use.

                              If you're eager to learn about these new APIs and start creating modules for Drupal 7, this is your book. Walk through the development of complete Drupal modules with this primer for PHP programmers.

                              From basic modules and themes to sophisticated Drupal extensions, learn how to use Drupal's API and hook system to build powerful custom Drupal websites. With an emphasis on practical programming, this book takes a project-based approach, providing working examples in every chapter
                              Specifically written for Drupal 7, this book will get you coding modules as quickly as possible, and help you add the features that will give your work that professional gloss!

                              This book will walk you through the development of complete Drupal modules and show you how to add various features to meet your requirements.

                              The Drupal content management system, written in the popular PHP language, has skyrocketed in popularity.

                              Developers for this system are in high demand. This book prepares PHP developers for Drupal development, explaining architecture, exploring APIs, and emphasizing practical approaches.

                              In each chapter, readers will learn new aspects of the system while creating fully-functioning modules, themes, and libraries. Learn how to “hook into” any part of the Drupal process, creating custom content types, extending existing capabilities, and integrating with external services and applications.

                              Learn the ins and outs of writing custom modules, themes, installation profiles and libraries for the Drupal PHP content management system.

                              Approach

                              This book takes a hands-on, practical approach to software development. The authors, all professional Drupal developers and contributors to the Drupal project, provide accessible coding samples designed to exhibit not only the technical merits and abilities of Drupal, but also proper architectural and stylistic approaches to coding on one of the world's most popular content management systems.

                              Every chapter provides fully functional code samples illustrating the APIs and strategies discussed in the chapter. With this foundation, developers can quickly build sophisticated tools on their own by making use of the strategies and techniques exemplified in this book.

                              Who this book is for

                              If you are a PHP developer or a Drupal user looking to dive into Drupal development then you will find this book an excellent introduction to coding within Drupal.

                              Those with some Drupal experience will also find this an invaluable tool for updating their knowledge about the powerful new features of Drupal 7. Theme developers looking to extend their abilities will find this an accessible introduction to PHP coding within the Drupal environment.

                              This book assumes that you are familiar with basic PHP programming, along with HTML and CSS.
                              No experience with programming Drupal is required, although it is also a handy way for experienced Drupal developers to get up to speed with Drupal 7.

                               

                              Code Download and Errata
                              Packt Anytime, Anywhere
                              Register Books
                              Print Upgrades
                              eBook Downloads
                              Video Support
                              Contact Us
                              Awards Voting Nominations Previous Winners
                              Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
                              Resources
                              Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software