Creating a Node Module

Traditionally, when you wanted to create a new content type in Drupal, you would write a node module that takes responsibility for providing the new and interesting things your content type needs. We say traditionally, because recent advents within the Drupal framework allow you to create content types within the administrative interface and extend their functionality with contributed modules rather than writing a node module from scratch. We'll cover both solutions within this chapter. Let's...

Customizing the Node Form for Our Node Type

So far you've got the metadata defined for your new node type, and the menu callback and access permissions defined. Next you need to build the node form so that users can enter jokes. You do that by implementing hook_form() ** (we use it for labeling title and body fields). We defined this in joke_node_info(). type node_get_types('type', node) form 'title' array( ' type' > 'textfield', ' title' > check_plain( type-> title_label), ' required' > TRUE, ' default_value' > node-> title,...

How the Indexer Works

The indexer has a preprocessing mode where text is filtered through a set of rules to assign scores. Such rules include dealing with acronyms, URLs, and numerical data. During the preprocessing phase, other modules have a chance to add logic to this process in order to perform their own data manipulations. This comes in handy during language-specific tweaking, as shown here using the contributed Porter-Stemmer module resume > resume (accent removal) Another such language preprocessing example...

Listing Your Module on the Administration Page

Drupal's administration page presents the various site configuration options to the site administrator. You want your module to have a place on this configuration page, so that the site administrator can adjust the settings for your module. Let's add some more configuration options to the node annotation module we built in the previous chapter. We need to provide a link on the administration page so that the site administrator can get to the screen where our settings can be changed. We put the...

D

D option, checkout command, 326 d option, cvs command, 326 d option, update command, 329 d placeholder, 52 dynamic queries, 312 storing data in database table, 20 data column, cache table, 244 data component, user object, 65 data entry form, adding, 16-21 data parameter, cache_set function, 251 data types handling security of user input, 302-303 HTML text, 303 plain text, 302 rich text, 303 URL, 303 database abstraction layer, 49-51 allowing MySQL PostgreSQL database bottlenecks, 344-348...

Connecting to Multiple Databases Within Drupal

While the database abstraction layer makes remembering function names easier, it also adds built-in security to queries. Sometimes we need to connect to third-party or legacy databases, and it would be great to use Drupal's database API for this need as well and get the security benefits. The good news is, we can In the settings.php file, db_url can be either a string as it usually is or an array composed of multiple database connection strings. Here's the default syntax, specifying a single...

Access Control

In our examples so far, we've simply set the access key of the menu item to TRUE, meaning that anyone can access our menu. Usually menu access is controlled by defining permissions inside the module using hook_perm and testing those permissions using user_access . Let's define a permission called receive greeting, if a user does not have a role that has been granted this permission, the user will receive an Access denied message if he or she tries to go to http example. Implementation of...

Getting pot Files for Drupal

The definitive .pot files for Drupal can be downloaded from http drupal.org project drupal- pot. After downloading and extracting the .tar.gz file for the branch of Drupal you are interested in, you should have a directory full of .pot files corresponding to Drupal files. For example, aggregator-module.pot contains the translatable strings from Drupal's aggregator module. gunzip drupal-pot-5.x-1.x-dev.tar.gz tar -xf drupal-pot-5.x-1.x-dev.tar ls drupal-pot You'll notice a few other files in the...

Building a Block

For this example, you'll create two blocks that make content moderation easier to manage. First, you'll create a block to list comments being held pending approval, then you'll create a block to list unpublished nodes. Both blocks will also provide links to the edit form for each piece of moderated content. Let's create a new module named approval. module to hold our block code. Create a new folder named approval within sites all modules custom you might need to create the modules and custom...

Limiting Access to a Node Type with hookaccess

Node modules can also limit access to the node types they define using hook_access . The superuser user ID 1 will always bypass any access check, so this hook isn't called in that case. If this hook isn't defined for your node type, all access checks will fail, so only the superuser and those with administer nodes permissions will be able to see content of that type. Implementation of hook_access . function joke_access op, node global user if op 'create' return user_access 'create joke' if op...

Adding the Data Entry Form

In order for the user to enter notes about a web page, we're going to need to provide a place for the notes to be entered. Let's add a form for notes function annotate_nodeapi amp node, op, teaser, page switch op case 'view' global user If only the node summary is being displayed, or if the user is an anonymous user not logged in , abort. if teaser user- gt uid 0 break types_to_annotate variable_get 'annotate_nodetypes', array 'story' if in_array node- gt type, types_to_annotate break Add our...

JQuery Within Drupal

Using jQuery within Drupal is easy because jQuery is preinstalled with Drupal. Log into your Drupal site as user 1 the administrative account and create a new node of type page. On the node creation form select PHP code under the Input formats section. Enter Testing jQuery as the title and add the following to the body section of the form ' document .ready function lt p id one gt Paragraph one lt p gt lt p gt Paragraph two lt p gt lt p gt Paragraph three lt p gt Hit Submit and then reload the...

Callback Mapping

When a web browser makes a request to Drupal, it gives Drupal a URL. From this information, Drupal must figure out what code to run and how to handle the request. This is commonly known as dispatching. Drupal trims off the base part of the URL and uses the latter part, called the path. For example, if the URL is http example.com q node 3, the Drupal path is node 3. The general approach taken is as follows Drupal asks all its modules to provide an array of menu items that is, a path and some...

Replacing Builtin Strings with Custom Strings

Suppose the term blog bothers you, so you want to change it to journal without modifying any code. You can use the locale module to change it. The approach is to create a language containing only the string s we want replaced. First, let's add a custom language to hold our custom strings. The interface for doing that is shown in Figure 18-2. We'll call it English-custom and use en-US for the language code. Tip If you intend to have multiple languages simultaneously enabled on your site and will...

Making Queries Secure with dbquery

A common way of exploiting web sites is called SQL injection. Let's examine a module written by someone not thinking about security. This person just wants a simple way to list titles of all nodes of a certain type function insecure_menu may_cache items array if may_cache items array 'path' gt 'insecure', 'title' gt t 'Insecure Module' , 'description' gt t 'Example of how not to do things.' , 'callback' gt 'insecure_code', 'access' gt user_access 'access content' Menu callback, called when user...

External Authentication with Server Provided

When a user signs in with a username in the form of joe example.com, we have more information to go by. Drupal core contains drupal. module, which provides an XML-RPC client that contacts another server for authentication. For example, on the site http groups.drupal.org, you can log in with your http drupal.org username and password. Here's what happens when I do that for the first time 1. I log in to groups.drupal.org with the username jvandyk drupal.org and my password. 2. groups. drupal .org...

Separate Database Server and a Web Server Cluster

Multiple web servers provide failover and can handle more traffic. The minimum number of computers needed for a cluster is two web servers. Additionally, you need a way to switch traffic between the machines. Should one of the machines stop responding, the rest of the cluster should be able to handle the load. Load balancers distribute web traffic among web servers. There are other kinds of load balancers for distributing other resources such as a hard disks and databases, but we'll cover those...

Understanding Template Files

Drupal Template Files Diagram

Some themes have all sorts of template files, while others only have page.tpl. php. So how do you know which template files you can create and have be recognized in Drupal What naming conventions surround the creation of template files You'll learn the ins and out of working with template files in the following section. page.tpl.php is the granddaddy of all template files, and provides the overall page layout for the site. Other template files are inserted into page.tpl.php, as the diagram in...

The punchline hookview

Now you have a complete system to enter and edit jokes. However, your users will be frustrated because although punchlines can be entered on the node submittal form, you haven't provided a way to make your module-provided punchline field visible when viewing the joke Let's do that now with hook_view Implementation of hook_view . function joke_view node, teaser FALSE, page FALSE if teaser Use Drupal's default node view. node node_prepare node, teaser Add a random number of Ha's to simulate a...

Technology Stack

Drupal Technology Stack

Drupal's design goals include both being able to run well on inexpensive web hosting accounts and being able to scale up to massive distributed sites. The former goal means using the most popular technology, and the latter means careful, tight coding. Drupal's technology stack is illustrated in Figure 1-1. Figure 1-1. Drupal's technology stack Figure 1-1. Drupal's technology stack The operating system is at such a low level in the stack that Drupal does not care much about it. Drupal runs...

Indexing Content That Isnt a Node hookupdateindex

In the case that you need to wrap the search engine around content that isn't made up of Drupal nodes, you can hook right into the indexer and feed it any textual data you need, thus making it searchable within Drupal. Suppose your group supports a legacy application that has been used for entering and viewing technical notes about products for the last several years. For political reasons you cannot yet replace it with a Drupal solution, but you'd love to be able to search those technical...

Using filterxss

Cross Site Scripting XSS is a common form of attack on a web site where the attacker is able to insert his or her own code into a web page, which can then be used for all sorts of mischief. Note For examples of XSS attacks, see http ha.ckers.org xss.html. Suppose that you allow users to enter HTML on your web site, expecting them to enter lt em gt Hi lt em gt My name is Sally, and I but instead they enter lt script Whoops Again, the lesson is never trust user input. Here is the function...

Overriding Theme Functions

The core philosophy behind Drupal's theme system is similar to that of the hook system. By adhering to a naming convention, functions can identify themselves as theme-related functions that are responsible for formatting and returning your site's content. Themeable functions are identifiable by their function names, which all begin with theme_. This naming convention gives Drupal the ability to create a function-override mechanism for all themeable functions. Designers can instruct Drupal to...

Xmlrpc Client Example Getting the Time

The site that hosts the XML-RPC specification http www.xmlrpc.com also hosts some test implementations. In our first example, let's ask the site for the current time via XML-RPC time xmlrpc 'http time.xmlrpc.com RPC2', 'currentTime.getCurrentTime' You're calling Drupal's xmlrpc function, telling it to contact the server time.xmlrpc.com with the path RPC2, and to ask that server to execute a method called currentTime.getCurrentTime . You're not sending any parameters along with the call. Drupal...

Adding Metadata to Nodes nodeapiupdate index

When Drupal indexes a node for faster searching, it first runs the node object through node_view to generate the same output you would see in your web browser. This means any parts of the node that are visible will be indexed. For example, assume we have a node with an ID of 26. The parts of the node that are visible when viewing the URL http example.com q node 26 are what the indexer also sees. What if we have a custom node type that contains hidden data that needs to influence search results...

Fastpath The Hidden Cache Setting

The fastpath cache setting is not configurable from within the Drupal administration interface because of its highly advanced nature fastpath gives developers the ability to bypass Drupal to implement a highly customized cache solution, such as memory or file-based caching see Figure 15-3. Figure 15-3. The request life cycle of anonymous user page caching under Drupal's fastpath cache setting Figure 15-3. The request life cycle of anonymous user page caching under Drupal's fastpath cache...

Simple External Authentication

Let's implement a very simple external authentication module that might be used inside a company where simple usernames are used. Suppose your company only hires people named Dave, and usernames are assigned based on first and last names. This module authenticates anyone whose username begins with the string dave, so the users davebrown, davesmith, and davejones will all successfully log in. Implementation of hook_auth function authdave_auth username, pass, server Does username begin with...

How Caching Works

Module developers can store a cache of their data into one of the tables reserved for caching within the Drupal database, or they can create a new table for cache storage. The next time this information is needed, it can be quickly retrieved with a single query and bypass expensive data manipulations. The default table to which your module can write cached information is named cache. Using this table is the best option when storing only a couple rows of cached information. If you're caching...

Pruning the Sessions Table

Drupal stores user sessions in its database rather than in files see Chapter 16 . This makes Drupal easier to set up across multiple machines, but it also adds overhead to the database for managing each user's session information. If a site is getting tens of thousands of visitors a day, it's easy to see how quickly this table can become very large. PHP gives you control over how often it should prune old session entries. Drupal has exposed this configuration in its settings. php file. ini_set...

Multipage Forms

We've been looking at simple one-page forms. But you may need to have users fill out a form that spans several pages or has several different steps for data entry. Let's build a short module that demonstrates the multipage form technique by collecting three ingredients from the user in three separate steps. Our approach will be to pass values forward in hidden form fields. We'll call the module formwizard.module. Of course, we'll need a formwizard.info file. description An example of a...

Building a jQuery Voting Widget

Let's write our first jQuery-enabled Drupal module. We'll build an Ajax voting widget as shown in Figure 17-2, which lets users add a single point to a post they like. We'll use jQuery to cast the vote and change the total vote score without reloading the entire page. We'll also add a role-based permission so only users with the rate content permission are allowed to vote. Because users can only add one point per vote, let's name the module plusl. We'll have to get some basic module building...

Building the Module

Drupal Plus1 Css

Open up the empty plus1. module in a text editor and add the standard Drupal header documentation Next you'll start knocking off the Drupal hooks you're going to use. An easy one is the use of hook_perm , which lets you add the rate content permission to Drupal's role-based access control page. You'll use this permission to prevent anonymous users from voting without first creating an account or logging in. Implementation of hook_perm . function plus1_perm return array 'rate content' Now you'll...