Pro Drupal 7 Development, 3rd Edition

  

  

Pro Drupal 7 Development

Third Edition

  ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀

  ฀฀ ฀฀ ฀ ฀ ฀฀ ฀฀ ฀ ฀ ฀ ฀฀ ■ ■ ■ Todd฀Tomlinson฀ John฀K.฀VanDyk฀ ฀

Pro฀Drupal฀7฀Development:฀Third฀Edition฀

  Copyright฀©฀2010฀by฀Todd฀Tomlinson฀and฀John฀K.฀VanDyk฀ All฀rights฀reserved.฀No฀part฀of฀this฀work฀may฀be฀reproduced฀or฀transmitted฀in฀any฀form฀or฀by฀any฀means,฀ electronic฀or฀mechanical,฀including฀photocopying,฀recording,฀or฀by฀any฀information฀storage฀or฀retrieval฀ system,฀without฀the฀prior฀written฀permission฀of฀the฀copyright฀owner฀and฀the฀publisher.฀

  ISBN-13฀(pbk):฀978-1-4302-2838-7฀

  ISBN-13฀(electronic):฀978-1-4302-2839-4฀ Printed฀and฀bound฀in฀the฀United฀States฀of฀America฀9฀8฀7฀6฀5฀4฀3฀2฀1฀ Trademarked฀names,฀logos,฀and฀images฀may฀appear฀in฀this฀book.฀Rather฀than฀use฀a฀trademark฀symbol฀ with฀every฀occurrence฀of฀a฀trademarked฀name,฀logo,฀or฀image฀we฀use฀the฀names,฀logos,฀and฀images฀only฀ in฀an฀editorial฀fashion฀and฀to฀the฀benefit฀of฀the฀trademark฀owner,฀with฀no฀intention฀of฀infringement฀of฀ the฀trademark.฀ The฀use฀in฀this฀publication฀of฀trade฀names,฀trademarks,฀service฀marks,฀and฀similar฀terms,฀even฀if฀they฀are฀ not฀identified฀as฀such,฀is฀not฀to฀be฀taken฀as฀an฀expression฀of฀opinion฀as฀to฀whether฀or฀not฀they฀are฀subject฀ to฀proprietary฀rights.฀

  President฀and฀Publisher:฀Paul฀Manning฀ Lead฀Editor:฀Michelle฀Lowman฀ Technical฀Reviewers:฀Joshua฀Brauer,฀Robert฀Douglass,฀Peter฀M.฀Wolanin฀ Editorial฀Board:฀Steve฀Anglin,฀Mark฀Beckner,฀Ewan฀Buckingham,฀Gary฀Cornell,฀Jonathan฀Gennick,฀

  Jonathan฀Hassell,฀Michelle฀Lowman,฀Matthew฀Moodie,฀Duncan฀Parkes,฀Jeffrey฀Pepper,฀Frank฀ Pohlmann,฀Douglas฀Pundick,฀Ben฀Renow-Clarke,฀Dominic฀Shakeshaft,฀Matt฀Wade,฀Tom฀Welsh฀

  Coordinating฀Editor:฀Anita฀Castro฀ Copy฀Editor:฀Mary฀Ann฀Fugate฀ Production฀Support:฀Patrick฀Cunningham฀ Indexer:฀BIM฀Indexing฀&฀Proofreading฀Services฀ Artist:฀April฀Milne฀ Cover฀Designer:฀Anna฀Ishchenko฀

  Distributed฀to฀the฀book฀trade฀worldwide฀by฀Springer฀Science+Business฀Media,฀LLC.,฀฀ 233฀Spring฀Street,฀6th฀Floor,฀New฀York,฀NY฀10013.฀Phone฀1-800-SPRINGER,฀fax฀(201)฀348-4505,฀฀ e-mail฀ For฀information฀on฀translations฀ Apress฀and฀friends฀of฀ED฀books฀may฀be฀purchased฀in฀bulk฀for฀academic,฀corporate,฀or฀promotional฀use.฀ eBook฀versions฀and฀licenses฀are฀also฀available฀for฀most฀titles.฀For฀more฀information,฀reference฀our฀ Special฀Bulk฀Sales–eBook฀Licensing฀web฀page฀at฀ The฀information฀in฀this฀book฀is฀distributed฀on฀an฀“as฀is”฀basis,฀without฀warranty.฀Although฀every฀ precaution฀has฀been฀taken฀in฀the฀preparation฀of฀this฀work,฀neither฀the฀author(s)฀nor฀Apress฀shall฀have฀ any฀liability฀to฀any฀person฀or฀entity฀with฀respect฀to฀any฀loss฀or฀damage฀caused฀or฀alleged฀to฀be฀caused฀ directly฀or฀indirectly฀by฀the฀information฀contained฀in฀this฀work.฀

  ฀

Contents at a Glance

  ฀

  

Foreword฀...........................................................................................฀

About฀the฀Technical฀Reviewers฀......................................................................

Introduction฀.......................................................................................

  

Chapter฀2:฀Writing฀a฀Module฀........................................................................

  

Chapter฀3:฀Hooks,฀Actions,฀and฀Triggers฀............................................................

  

Chapter฀4:฀The฀Menu฀System฀.........................................................................

  

Chapter฀5:฀Working฀with฀Databases฀..................................................................

  

Chapter฀6:฀Working฀with฀Users฀......................................................................

  

Chapter฀7:฀Working฀with฀Nodes฀......................................................................

  

Chapter฀8:฀Working฀with฀Fields฀.....................................................................

  

Chapter฀9:฀The฀Theme฀System฀........................................................................

  

Chapter฀10:฀Working฀with฀Blocks฀....................................................................

  

Chapter฀11:฀The฀Form฀API฀...........................................................................

  

Chapter฀12:฀Manipulating฀User฀Input:฀The฀Filter฀System฀

  

Chapter฀13:฀Searching฀and฀Indexing฀Content฀

  

Chapter฀14:฀Working฀with฀Files฀.....................................................................

  ■ Chapter฀15:฀Working฀with฀Taxonomy฀..................................................................

  ■ Chapter฀16:฀Caching฀................................................................................

  ■ Chapter฀17:฀Sessions฀...............................................................................

  ■ Chapter฀18:฀Using฀jQuery฀...........................................................................

  ■ Chapter฀10:฀Localization฀and฀Translation฀...........................................................

  ■ Chapter฀20:฀XML-RPC฀................................................................................

  ■ Chapter฀21:฀Writing฀Secure฀Code฀....................................................................

  ■ Chapter฀22:฀Development฀Best฀Practices฀

  ■ Chapter฀23:฀Optimizing฀Drupal฀......................................................................

  ■ Chapter฀24:฀Installation฀Profiles฀..................................................................

  ■ Chapter฀25:฀Testing฀................................................................................

  ■ Appendix฀A:฀Database฀Table฀Reference฀...............................................................

  ■ Appendix฀B:฀Resources฀.............................................................................. ฀

  Index฀..............................................................................................

Contents

  ฀

  

Foreword฀...........................................................................................฀

About฀the฀Technical฀Reviewers฀......................................................................

Introduction฀.......................................................................................

  

What฀Is฀Drupal?฀...............................................................................................................

Core฀..........................................................................................................................

Modules฀.......................................................................................................................

Themes฀........................................................................................................................

Fields฀........................................................................................................................

File฀Layout฀...................................................................................................................

  The฀Web฀Server’s฀Role฀.........................................................................................................

  Processing฀a฀Request฀.......................................................................................................... Summary฀.......................................................................................................................

  ■ Chapter฀2:฀Writing฀a฀Module฀........................................................................

  Implementing฀a฀Hook฀................................................................................ Defining฀Your฀Own฀Administration฀Section฀........................................................... Validating฀User-Submitted฀Settings฀.................................................................

  Using฀Drupal’s฀variables฀Table฀................................................................................................ Further฀Steps฀.................................................................................................................

  ■ Chapter฀3:฀Hooks,฀Actions,฀and฀Triggers฀............................................................

  Understanding฀Actions฀.............................................................................. The฀Trigger฀User฀Interface฀.................................................................................................... Assigning฀the฀Action฀..........................................................................................................

Using฀the฀Context฀in฀Actions฀............................................................................................฀45

  How฀the฀Trigger฀Module฀Prepares฀the฀Context฀................................................................................... Establishing฀the฀Context฀......................................................................................................

  How฀Actions฀Are฀Stored฀............................................................................. The฀actions฀Table฀.............................................................................................................

  Calling฀an฀Action฀Directly฀with฀actions_do()฀....................................................... Adding฀Triggers฀to฀Existing฀Hooks฀..................................................................

  Chapter฀4:฀The฀Menu฀System฀......................................................................... ■

  Callback฀Mapping฀................................................................................... Creating฀a฀Menu฀Item฀............................................................................... Page฀Callbacks฀in฀Other฀Files฀...................................................................... Menu฀Nesting฀.................................................................................................................. Title฀Localization฀and฀Customization฀...............................................................

Wildcards฀in฀Menu฀Items฀.................................................................................................฀74

  Basic฀Wildcards฀............................................................................................................... Using฀the฀Value฀of฀a฀Wildcard฀................................................................................................. Passing฀Additional฀Arguments฀to฀the฀Load฀Function฀............................................................................. Building฀Paths฀from฀Wildcards฀Using฀to_arg()฀Functions฀.............................................

  Altering฀Menu฀Items฀from฀Other฀Modules฀............................................................. Kinds฀of฀Menu฀Items฀................................................................................

  Assigning฀Callbacks฀Without฀Adding฀a฀Link฀to฀the฀Menu฀ Hiding฀Existing฀Menu฀Items฀.................................................................................................... Common฀Mistakes฀...............................................................................................................

  Summary฀....................................................................................................................... ■

  Defining฀Database฀Parameters฀....................................................................... Connecting฀to฀the฀Database฀......................................................................... Retrieving฀Query฀Results฀...........................................................................

  Getting฀a฀Single฀Value฀........................................................................................................ Using฀the฀Query฀Builder฀and฀Query฀Objects฀..................................................................................... Getting฀Results฀for฀Paged฀Display฀.............................................................................................

Inserts฀and฀Updates฀with฀drupal_write_record()฀.............................................................฀98 The฀Schema฀API฀...............................................................................................................฀99

  Using฀Module฀.install฀Files฀................................................................................................... Using฀the฀Schema฀Module฀.......................................................................................................

  Declaring฀a฀Specific฀Column฀Type฀with฀mysql_type฀................................................... Deleting฀Tables฀on฀Uninstall฀..................................................................................................

  Modifying฀Other฀Modules’฀Queries฀with฀hook_query_alter()฀ Using฀a฀Temporary฀Table฀............................................................................ Summary฀.......................................................................................................................

  ■ The฀$user฀Object฀................................................................................... Introduction฀to฀user฀hooks฀.........................................................................

  Understanding฀hook_user_view($account,฀$view_mode)฀................................................. The฀User฀Registration฀Process฀...................................................................... The฀Login฀Process฀..................................................................................

  Adding฀Data฀to฀the฀$user฀Object฀at฀Load฀Time฀.................................................................................. External฀Login฀................................................................................................................

  Chapter฀7:฀Working฀with฀Nodes฀...................................................................... ■

  So฀What฀Exactly฀Is฀a฀Node?฀......................................................................... Creating฀a฀Node฀Module฀.............................................................................

  Creating฀the฀.install฀File฀....................................................................................................

  Creating฀the฀.module฀File฀..................................................................................................................... Modifying฀the฀Menu฀Callback฀...............................................................................................................

  Limiting฀Access฀to฀a฀Node฀Type฀with฀hook__node_access()฀. ............................................................. Validating฀Fields฀with฀hook_validate()฀.................................................................................................. Keeping฀Data฀Current฀with฀hook_update()฀........................................................................................... Modifying฀Nodes฀of฀Our฀Type฀with฀hook_load()฀....................................................................................

  Manipulating฀Nodes฀That฀Are฀Not฀Our฀Type฀with฀hook_node_xxxxx()฀. ................................................ How฀Nodes฀Are฀Stored฀.................................................................................................. Restricting฀Access฀to฀Nodes฀.........................................................................................

  Defining฀Node฀Grants฀............................................................................................................................ Summary฀.......................................................................................................................฀161 Chapter฀8:฀Working฀with฀Fields฀. .........................................................................

  ■ Creating฀Content฀Types฀................................................................................................. Creating฀a฀Custom฀Field฀................................................................................................ Summary฀.......................................................................................................................฀183

  Chapter฀9:฀The฀Theme฀System฀........................................................................ ■

  Themes฀........................................................................................................................ Installing฀an฀Off-the-Shelf฀Theme฀.............................................................................................

  The฀.info฀File฀................................................................................................................ Adding฀Regions฀to฀Your฀Theme฀.................................................................................................. Adding฀JavaScript฀Files฀.......................................................................................................

  Understanding฀Template฀Files฀....................................................................... The฀Big฀Picture฀............................................................................................................... Overriding฀Template฀Files฀..................................................................................................... Overriding฀Themable฀Items฀..................................................................................................... Adding฀and฀Manipulating฀Template฀Variables฀....................................................................................

  Summary฀....................................................................................................................... ■

  What฀Is฀a฀Block?฀................................................................................... Block฀Placement฀............................................................................................................... Using฀the฀Block฀Hooks฀.........................................................................................................

  Building฀a฀Block฀...................................................................................

  Block฀Visibility฀Examples฀.......................................................................... Displaying฀a฀Block฀to฀Logged-In฀Users฀Only฀....................................................................................

  Summary฀....................................................................................................................... ■

Understanding฀Form฀Processing฀....................................................................................฀239

  Initializing฀the฀Process฀...................................................................................................... Setting฀an฀ID฀................................................................................................................. Looking฀for฀a฀Validation฀Function฀............................................................................................. Allowing฀Modules฀to฀Alter฀the฀Form฀Before฀It’s฀Built฀.......................................................................... Allowing฀Functions฀to฀Alter฀the฀Form฀After฀It’s฀Built฀......................................................................... Finding฀a฀Theme฀Function฀for฀the฀Form฀......................................................................................... Rendering฀the฀Form฀............................................................................................................ Submitting฀the฀Form฀...........................................................................................................

Creating฀Basic฀Forms.....................................................................................................฀247

  Form฀Properties฀............................................................................................................... Fieldsets฀..................................................................................................................... Specifying฀Validation฀and฀Submission฀Functions฀with฀hook_forms()฀

  Writing฀a฀Validation฀Function฀................................................................................................. Writing฀a฀Submit฀Function฀..................................................................................................... Submitting฀Forms฀Programmatically฀with฀drupal_form_submit()฀

  Form฀API฀Properties฀................................................................................ Properties฀for฀the฀Root฀of฀the฀Form฀........................................................................................... Properties฀Allowed฀in฀All฀Elements฀............................................................................................

  Summary฀....................................................................................................................... ■

  Filters฀....................................................................................................................... Installing฀a฀Filter฀...........................................................................................................

  Creating฀a฀Custom฀Filter฀........................................................................... Implementing฀hook_filter_info()฀............................................................................................... Helper฀Function฀...............................................................................................................

  Summary฀....................................................................................................................... ■

Building฀a฀Custom฀Search฀Page฀....................................................................................฀307

  The฀Default฀Search฀Form฀....................................................................................................... Adding฀to฀the฀Search฀Form฀.....................................................................................................

  Using฀the฀Search฀HTML฀Indexer฀...................................................................... When฀to฀Use฀the฀Indexer฀.......................................................................................................

  Summary฀....................................................................................................................... ■

  Chapter฀14:฀Working฀with฀Files฀..................................................................... Managed฀and฀Unmanaged฀Drupal฀APIs฀..................................................................

  Public฀Files฀.................................................................................................................. PHP฀Settings฀..................................................................................................................

  Upload฀Field฀.................................................................................................................. File฀API฀......................................................................................................................

  Database฀Schema฀............................................................................................................... Authentication฀Hooks฀for฀Downloading฀..........................................................................................

  Summary฀....................................................................................................................... ■

  Chapter฀15:฀Working฀with฀Taxonomy฀.................................................................. Creating฀a฀Vocabulary฀..............................................................................

Assigning฀a฀Vocabulary฀to฀a฀Content฀Type฀.....................................................................฀344 Kinds฀of฀Taxonomy฀........................................................................................................฀345

  Flat฀......................................................................................................................... Multiple฀Hierarchical฀.........................................................................................................

  Viewing฀Content฀by฀Term฀............................................................................ Using฀AND฀and฀OR฀in฀URLs฀...................................................................................................... Automatic฀RSS฀Feeds฀...........................................................................................................

  Storing฀Taxonomies฀................................................................................. Creating฀a฀Module-Based฀Vocabulary฀............................................................................................

  Common฀Tasks฀....................................................................................... Displaying฀Taxonomy฀Terms฀Associated฀with฀a฀Node฀................................................... Using฀taxonomy_select_nodes()฀.................................................................................................

  Taxonomy฀Functions฀................................................................................. Retrieving฀Information฀About฀Vocabularies฀..................................................................................... Retrieving฀Information฀About฀Terms฀............................................................................................ Retrieving฀Information฀About฀Term฀Hierarchy฀...................................................................................

  Additional฀Resources฀............................................................................... Chapter฀16:฀Caching฀................................................................................

  ■ Knowing฀When฀to฀Cache฀..............................................................................

How฀Caching฀Is฀Used฀Within฀Drupal฀Core฀......................................................................฀368

  Menu฀System฀................................................................................................................... Administration฀Variables฀and฀Module฀Settings฀..................................................................................

  Blocks฀........................................................................................................................ Summary฀.......................................................................................................................

  ■ Chapter฀17:฀Sessions฀...............................................................................

  Usage฀........................................................................................................................ In฀.htaccess฀.................................................................................................................. In฀bootstrap.inc฀..............................................................................................................

  Storage฀....................................................................................................................... Session฀Conversations฀..............................................................................

  First฀Visit฀................................................................................................................... User฀with฀an฀Account฀..........................................................................................................

  Common฀Tasks฀....................................................................................... Changing฀the฀Length฀of฀Time฀Before฀a฀Cookie฀ Storing฀Data฀in฀the฀Session฀...................................................................................................

  Summary฀....................................................................................................................... ■

  Chapter฀18:฀Using฀jQuery฀........................................................................... The฀Old฀Way฀...................................................................................................................

  How฀jQuery฀Works฀................................................................................... Using฀a฀CSS฀ID฀Selector฀....................................................................................................... jQuery฀Within฀Drupal฀...............................................................................

  Your฀First฀jQuery฀Code฀........................................................................................................ Method฀Chaining฀............................................................................................................... Wrapping฀Existing฀Elements฀.................................................................................................... Where฀to฀Put฀JavaScript฀.......................................................................................................

  Building฀a฀jQuery฀Voting฀Widget฀.................................................................... Building฀the฀Module฀........................................................................................................... Ways฀to฀Extend฀This฀Module฀....................................................................................................

  Next฀Steps฀.................................................................................................................... Chapter฀19:฀Localization฀and฀Translation฀...........................................................

  ■

Enabling฀the฀Locale฀Module฀...........................................................................................฀417 User฀Interface฀Translation฀.............................................................................................฀417

  Strings฀....................................................................................................................... Replacing฀Built-In฀Strings฀with฀Custom฀Strings฀................................................................................

  Starting฀a฀New฀Translation฀......................................................................... Generating฀.pot฀Files฀with฀Translation฀Template฀Extractor฀.......................................... Creating฀.pot฀Files฀for฀an฀Entire฀Site฀........................................................................................

  Installing฀a฀Language฀Translation฀.................................................................. Setting฀Up฀a฀Translation฀at฀Install฀Time฀......................................................................................

  Right-to-Left฀Language฀Support฀..................................................................... Default฀....................................................................................................................... Path฀Prefix฀with฀Language฀Fallback฀............................................................................................

  Content฀Translation................................................................................. Introducing฀the฀Content฀Translation฀Module฀.................................................................................... Multilingual฀Support฀with฀Translation฀.........................................................................................

  Localization-฀and฀Translation-Related฀Files฀........................................................ Summary฀.......................................................................................................................

  ■ What฀Is฀XML-RPC?฀...................................................................................

XML-RPC฀Clients฀............................................................................................................฀452

  XML-RPC฀Client฀Example:฀Getting฀the฀Time฀......................................................................................

  XML-RPC฀Client฀Example:฀Getting฀the฀Name฀of฀a฀State฀................................................

  A฀Simple฀XML-RPC฀Server฀............................................................................ Mapping฀Your฀Method฀with฀hook_xmlrpc()฀........................................................................................

  Built-In฀XML-RPC฀Methods฀........................................................................... system.listMethods฀............................................................................................................ system.methodHelp฀............................................................................................................. system.multiCall฀..............................................................................................................

  Summary฀....................................................................................................................... ■

  Handling฀User฀Input฀................................................................................ Thinking฀About฀Data฀Types฀..................................................................................................... Using฀filter_xss()฀to฀Prevent฀Cross-Site฀Scripting฀Attacks฀.........................................

  Handling฀URLs฀Securely฀............................................................................. Keeping฀Private฀Data฀Private฀with฀hook_query_alter()฀............................................... Permissions฀and฀Page฀Callbacks฀..................................................................... File฀Security฀.................................................................................................................

  File฀Permissions฀.............................................................................................................. File฀Uploads฀..................................................................................................................

  Encoding฀Mail฀Headers฀..............................................................................

  Files฀for฀Production฀Environments฀................................................................................ Stand-Alone฀PHP฀. ......................................................................................................... Form฀API฀Security฀. ........................................................................................................ Summary฀. .....................................................................................................................

  ■ Coding฀Standards฀. ........................................................................................................

  Line฀Indention฀and฀Whitespace฀............................................................................................................ Casting฀. .........................................................................................................................

  Function฀Calls฀. ..................................................................................................................................... Function฀Names฀. .................................................................................................................................. Arrays฀...................................................................................................................................................

  String฀Concatenators฀............................................................................................................................

Comments฀.....................................................................................................................฀491

  Documentation฀Examples฀..................................................................................................................... Documenting฀Functions฀. ...................................................................................................................... Including฀Code฀......................................................................................................................................

  Semicolons฀. ....................................................................................................

  Example฀URLs฀.................................................................................................................. Naming฀Conventions฀................................................................................. Finding฀Your฀Way฀Around฀Code฀with฀grep฀.............................................................

  ■ Chapter฀23:฀Optimizing฀Drupal฀......................................................................

  Optimizing฀PHP฀..................................................................................... Setting฀PHP฀Opcode฀Cache฀File฀to฀/dev/zero฀....................................................................................

  Tuning฀Apache฀...................................................................................... mod_expires฀................................................................................................................... MPM฀Prefork฀vs.฀Apache฀MPM฀Worker฀............................................................................................. Decreasing฀Apache฀Timeout฀.....................................................................................................

  Using฀Nginx฀Instead฀of฀Apache฀...................................................................... Varnish฀......................................................................................................................

  Normalizing฀incoming฀requests฀for฀better฀Varnish฀hits฀.............................................. Boost฀........................................................................................................................

  Linux฀System฀Tuning฀for฀High฀Traffic฀Servers฀....................................................... Dedicated฀Servers฀vs.฀Virtual฀Servers฀.............................................................. Decreasing฀Server฀Timeouts฀.........................................................................

  Enabling฀MySQL’s฀Query฀Cache฀.................................................................................................. Drupal฀Performance฀.................................................................................

  Eliminating฀404฀Errors฀........................................................................................................ Drupal-Specific฀Optimizations฀......................................................................

  Page฀Caching฀.................................................................................................................. Pruning฀the฀Sessions฀Table฀.................................................................................................... Running฀cron฀..................................................................................................................

  Architectures฀................................................................................................................. Single฀Server฀................................................................................................................. Separate฀Database฀Server฀and฀a฀Web฀Server฀Cluster฀..................................................

  Finding฀the฀Bottleneck฀.............................................................................

  ■ Chapter฀24:฀Installation฀Profiles฀..................................................................

  The฀enhanced.info฀File฀........................................................................................................ The฀enhanced.install฀File฀.....................................................................................................

  Using฀hook_install_tasks฀and฀hook_install_tasks_alter ■

  Chapter฀25:฀Testing฀................................................................................ How฀Tests฀Are฀Defined฀.............................................................................. Test฀Assertions฀....................................................................................

  ■ Appendix฀A:฀Database฀Table฀Reference฀...............................................................

  ■ Appendix฀B:฀Resources฀..............................................................................

  The฀Drupal฀Source฀Code฀Repository฀on฀GIT฀...................................................................................... Drupal฀API฀Reference฀.......................................................................................................... Updating฀Modules฀..............................................................................................................

  Handbooks฀..........................................................................................

  Mailing฀Lists฀................................................................................................................. Development฀.................................................................................................................. Translations฀..................................................................................................................

  User฀Groups฀and฀Interest฀Groups฀.................................................................... North฀America฀................................................................................................................. Asia฀.........................................................................................................................

Oceania฀................................................................................................................................................฀629 Africa฀....................................................................................................................................................฀629

  Videocasts฀.................................................................................................................... Conferences฀........................................................................................

  ฀ Index฀..............................................................................................

Foreword

  Four฀years฀ago,฀I฀wrote฀the฀foreword฀for฀the฀first฀edition฀of฀this฀book.฀What฀was฀missing฀at฀that฀time฀was฀ a฀developer฀book฀for฀Drupal.฀Since฀then,฀Pro฀Drupal฀Development฀has฀made฀an฀incredible฀contribution฀ to฀Drupal’s฀steady฀growth.฀I฀don’t฀think฀I฀know฀a฀single฀Drupal฀developer฀who฀doesn’t฀own฀a฀copy฀of฀the฀

  Pro฀Drupal฀Development฀book.฀