Thứ Sáu, 30 tháng 5, 2014

What Is a Block? [Working with Blocks]

A block is essentially a stand-alone container that can be used to house virtually anything you can think of. It might be
easiest to understand wha a block is by examining a few examples (see table 10-1). The following list represents
some of the standard blocks that ship with Drupal.

Table 10-1. Standard Blocks
Block
Description
Login form
The form displayed on a site that allows a visitor to log in, register for a new account, or reset his or her password
Who’s online
A block that lists all of the users who are currently logged onto the site
Whos new
A block that displays a list of the newest users on the web site
Search form
The search form is contained within a block.
Recent comments
A list of the most recent comments posted on the site
Main menu and  secondary menu
Both menus are available as a block.
Recent content
A list of the most recent nodes posted on the site
Most recent poll
The last poll created on the site is displayed as a block (requires that the Poll module be enabled).
Active forum topics
A list of forum topics that have recent activity  (requires that the Forum module be enabled)


Several contributed modules include blocks as a component of the functional solution they deliver. Ubercart, for example,
provides numerous blocks  that are used to display things like the visitor’s shopping cart status. With the Block API and
the block administration interface, you have the ability to create your own custom blocks  for virtually any purpose you
can think of (see table 10-2). Examples of custom blocks  that I’ve recently created include the following:

Table 10-2. Examples of Custom Blocks
Block
Description
Recent Bloggers
A block that displays a gallery of avatars for the last bloggers who have posted to the site
Slideshow of upcoming events
A block that displays the node teasers for upcoming events as a slideshow
A chat  form
A block that incorporates the Meebo chat  widget  and  displays the chat widget  in a right or left sidebar
A donate now feature
A block that displays a button that allows a visitor to click through to PayPal, allowing the visitor to make a donation
A list of new books added to a library’s collection
A block that displays a mini  version of a book jacket,  the book’s title, author, and  reserve it button
A contact us form
A block that displays a simple contact request form
A list of postings on multiple social networking sites
A block that displays feeds from several social networking sites as a mashup in a single list
A Google map showing recent postings
A block that renders markers on a Google map for nodes that include geographic information in their body

Blocks are defined either through Drupal’s web interface (see figure 10-1) or program matically through the block API
(module-provided blocks)How do you know which method to use when creating a block? A one-off block such as a
bit of static HTML related to the site is a good candidate for a custoblock. Blocks that are dynamic in nature, related to a module you’ve written, or that consist of mostly PHP code  are excellent candidates for using the block API and  for
being implemented within a module. Try to avoid storing PHP code  in custom blocks,  ascode  in the database is harder to maintain than code written in a module. A site editor can come along  and  accidentally delete all that hard work too easily.
Rather, if it doesn’t make sense to create a block at the module level, just call a custom function from withinthe block and store all that PHP code  else where.



Figure 10-1. The block overview page

 Although the block API is relatively simple, don’t  disregard the complexity of what  you can do within that framework. Blocks can display just about anything you want  (that is, they are written in PHP and thus are not limited in what  they can do), but they
usually play a supporting role to the main content of the site. For example, you could create a custom navigation block for each user
role, or you could expose a block that lists comments pending approval.

Block Configuration Options

A common configuration option that you’ll want  to become familiar with is setting the block visibility options on the configuration
page for a block. Block visibility defines when a block should and  should not be displayed on a page based on criteria youspecify
using  the interface shown in Figure  10-2. Using the User Login block as an example, you can control whether the block is
displayed through the following options:
     Page-specific visibility settings: Administrators can choose to make a block be visible or hidden on a certain
page or range of pages or when your custom PHP code  determines that certain conditions are true.

     Content types visibility settings: Administrators can choose to display this block only on pages that display a specific content
type—for example, display this block only if the page displays a forum topic.

     Role-specific visibility settings: Administrators can choose to make a block be visible to only those users within certain roles.

     User-specific visibility settings: Administrators can allow individual users to customize the visibility of a given block for that
user  within his or her account settings. Users would click their “My account” link to modify block visibility.


Figure 10-2. Configuration screen of a block in the administrative interface

Block Placement


I mentioned previously that the block administration page gives site administrators a choice of regions where blocks  can
appear. On the same page,  they can also choose in what  order the blocks  are displayed within a region, as shown in
Figure 10-1. Regionare defined by the theme layer in the theme’s .info file, rather than through the block API,
and  different themes may expose different regions. Please see Chapter 8 for more information on creating regions.

Defining a Block

Blocks are defined within modules by using hook_block_info(), and  a module can implement multiple blocks  within this
single hook.  Once  a block is defined, it will be shown on the block administration page.  Additionally, a site administrator can manually create custom blocks  through the web interface. In this section, we’ll mostly focus on program matically creating blocks Lets take a look at the database schema for blocks, shown in Figure  10-3.


Figure 10-3. Database schema for blocks
Block properties for every block are stored in the blocks table. Additional data for blockcreated from within the block
configuration interface is stored in other supporting tables, as listed  in Figure  10-3.
The following properties are defined within the columns of the block table:

bid: This is the unique ID of each  block.
module: This column contains the name of the module that defined the block. The user login block was created by the
user module, and  so on. Custom blocks created by the administrator at Structure -> Blocks -> Add Blocks are considered to have been created by the block module.

delta: Because modules can define multiple blocks  within hook_block_info(), the delta column stores a key for each  block
that’s  unique only for each implementation of hook_block_info(), and  not for all blocks  across the board. Adelta should
be a string.
theme: Blocks can be defined for multiple themes. Drupal therefore needs to store the name of the theme for which the
block is enabled. Every theme for which the block is enabled will have its own row in the database. Configuration options are not shared across themes.
status: This tracks whether the block is enabled. A value of 1 means that it’s enabled, while 0 means it’s disabled. When  a
block doesn’t have a region associated with it, Drupal sets the status flag to 0.
weight: The weight  of the block determines its position relative to other blocks within a region.
region: This is the name of the region in which the block will appear, for example, footer.
custom: This is the value of the user-specific visibility settings for this block (see Figure  10-2). A value of 0 means that
users cannot control the visibility of this block; a value of 1 means that the block is shown by default but userscan hide it; a value of 2 means that the block is hidden by default but users can choose to display it.
visibility: This value represents how the block’s visibility is determined. A value of 0 means the block will be shown on all
pages except listed  pages; a value of 1 means the block will be shown only on listed  pages; a value of 2means that Drupal will execute custom PHP code  defined by the administrator to determine visibility.
pages: The contents of this field depend on the setting in the visibility field. If the value of the visibility field is 0 or 1,
this field will contain a list of Drupal paths. If the value of the visibility field is 2, the pages field will contain
custom PHP code  to be evaluated to determine whether to display the block.

title: This is a custom title for the block. If this field is empty, the block’s default title (provided by the module that
provides the block) will be used. If the field contains <none>, no title will be displayed for the block. Otherwise, text in
this field is used for the blocks title.
cache: This value determines how Drupal will cache this block. A value of –1 means the block will not be cached.
A value of 1 means that the block will be cached for each  role, and  this is Drupal’s default setting for blocks  that do not
specify a cache setting. A value of 2 means the block will be cached for each user. A value of 4 means that the block will
be cached for each  page.  A value of means that the block will be cached but  will be cached the same wafor everyone
regardless of role, user,  or page.

Using the Block Hooks

The block hooks—hook_block_info(), hook_block_configure(), hook_block_save(), and hook_block_view()—handle all the logic for programmatically creating blocks.  Using these hooks, you can declare a single block or a set of
blocks.  Any module canimplement these hooks to create blocks. Let’s take a look at eac of the hooks:
hook_block_info(): This defines all blocks  provided by a module.

hook_block_configure($delta  = ''): The configuration form for a block. The

$delta parameter is the ID of the block to return. You can use an integer or a string value for $delta. This same parameter is used in the hook_block_save and hook_block_view hooks.

hook_block_save($delta  = '', $edit  = array()): This saves the configuration options for a block. The $edit  parameter contains the submitted form data from the block configuration form.

hook_block_view($delta  = ''): This processes the block when enabled in a region in order to view its contents

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, and  then you’ll create a block to list unpublished nodes. Both blocks  will alsoprovide links tothe edit form for each  piece  of moderated content. Lets 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 folders if they dont exist). Next, add approval.info to the folder:
name  = Approval
description  = Blocks  for  facilitating  pending  content  workflow.
package = Pro  Drupal  Development core  = 7.x
version  = VERSION
files[]  = approval.module
Then, add approval.module as well:
<?php
/**
*   @file
*   Implements  various  blocks  to  improve  pending  content  workflow.
*/
Once you’ve created these files, enable the module via the Modules page.  You’ll continue to work within approval.
module, so keep your text editor open. Lets add our hook_block_info so our block appears in the list of blocks  on the block administration page (see Figure  10-4). I’ll define the title that appears for the block through the info attribute,
the statuset to True so that it is automatically enabled, region set to sidebar_first, weight set to 0, and  visibility set to 1 (visible).

/**
*   Implements hook_block_info().
*/
function approval_block_info() {
$blocks['pending_comments'] = array( 'info'  => t('Pending Comments'), 'status'   => TRUE, 'region' => 'sidebar_first', 'weight' => 0,'visibility' => 1,);
return  $blocks;}


Figure 10-4. Pending comments” is now a block listed on the block overview page under the Sidebar  First region heading.

Note that the value of info isn’t the title of the block that shows up to users once the block is enabled; rather, info is a description that appears only in the list of blocks  the administrator can configure. You’ll implement the actual block title
later inhook_block_view. First, though, you’re going to set up additional configuration options. To do this, implement
the hook_block_configure  function as shown in the following code snippet                  . You create a new form field that’s  visibleafter clicking  the configurelink next to the block on the block administration page,  shown in Figure  10-5.
/**
*   Implements hook_block_configure().
*/
function approval_block_configure($delta) {
$form = array(); switch($delta) {
case  'pending_comments': $form['pending_comment_count']   = array( '#type' => 'textfield',
'#title' => t('Configure Number  of  Comments  to  Display'), '#size' => 6,
'#description' => t('Enter the  number  of  pending  comments that   will appear  in  the block.'),
'#default_value' => variable_get('pending_comment_count',   5),); break;}
return  $form;}


Figure 10-5. Block configuration form with the block’s custom fields

 When  the block configuration form shown in Figure  10-5 is submitted, it will trigger hook_block_save().
You’ll use this next phase to save the value of the form field:
/**
*   Implements hook_block_save().
*/
function  approval_block_save($delta = '', $edit = array()) { switch($delta) {
case  'pending_comments': variable_set('pending_comment_count', (int)$edit['pending_comment_count']); break;
} return;
}

You save the number of pending comments to display using Drupal’s built-in variable system with variable_set().
Note how we typecast the value to an integer as a sanity check. Finally, add the view operation using hook_block_view and  a
custofunction that returns a list of pending comments when the block is viewed:
/**
*   Implements hook_block_view().
*/
function  approval_block_view($delta = '') {
switch   ($delta) {
case  'pending_comments':
$block['subject'] = t('Pending Comments');
$block['content'] = approval_block_contents($delta); return  $block;
break;}}
/**
*    module-defined   block  content function.
*/
function approval_block_contents($delta) { switch   ($delta) {
case  'pending_comments':
if (user_access('administer comments'))  {
$nbr_comments  = variable_get('pending_comment_count');
$result = db_query("SELECT  cid,  subject FROM   {comment} WHERE   status = 0  limit$nbr_comments");
$items  = array();
foreach   ($result as  $row)  {
$items[] = l($row->subject, 'comment/'  . $row->cid  . '/edit');
}
return  array('#markup'  => theme('item_list',  array('items' => $items)));}
break;}
}
Here,  we’re querying the database for the comments that need approval and  displaying the comment titles as links for each  comment, as shown in Figure  10-6. You also set the title of the block with the following line:
$block['subject'] = t('Pending  comments');


Figure 10-6. The “Pending comments” listin block after it has been enabled;  it shows two pending comments.

Now that the Pending comments block is finished, let’s define another block within this approval_block_info() function—one that lists all unpublished nodes and  provides a link to their edit page:
/**
*   Implements hook_block_info().
*/
function approval_block_info() {
$blocks['pending_comments'] = array( 'info' => t('Pending  comments'), 'status'  => TRUE,'region'  => 'sidebar_first',
'weight'=> 0,'visibility' => 1,);
$blocks['unpublished_nodes'] = array( 'info' => t('Unpublished nodes'), 'status'=> TRUE,'region'  => 'sidebar_first',
'weight' => 0, 'visibility' => 1,);
return  $blocks;
}
Notice how the blocks  are each  assigned a key ($blocks['pending_comments'],
$blocks['unpublished_nodes'], . . . $blocks['xxxxxx']). The block module will subsequently use these keys as the $delta 
parameter. I’ll update the hook_block_configure and  hook_block_save functions by adding the form for setting the number of
nodes to display and  saving the value entered on the form by a site administrator.
/**
*   Implements hook_block_configure().
*/
function approval_block_configure($delta) {
$form = array(); switch($delta) {
case  'pending_comments':
$form['pending_comment_count']   = array( '#type' => 'textfield',
'#title' => t('Configure number  of  comments to  display'),
'#size' => 6,
'#description' => t('Enter the  number  of  pending  comments that   will appear  in  the block.'),
'#default_value' => variable_get('pending_comment_count',   5),); break;
case  'unpublished_nodes':
$form['unpublished_node_count'] = array( '#type' => 'textfield',
'#title' => t('Configure Number  of  Nodes to  Display'), '#size' => 6,
'#description' => t('Enter the  number  of  unpublished  nodes  that   will appear  in  the block.'),
'#default_value' => variable_get('unpublished_node_count',   5),); break;
}
return  $form;}

/**
*   Implements hook_block_save().
*/
function  approval_block_save($delta = '', $edit = array()) {
switch($delta) {case  'pending_comments':
variable_set('pending_comment_count', (int)$edit['pending_comment_count']); break;
case  'unpublished_nodes':
variable_set('unpublished_nodes_count', (int)$edit['unpublished_node_count']); break;
}
return;}
I’ll then update the hook_block_view and  approval_block_content functions to address displaying unpublished nodes.
/**
*   Implements hook_block_view().
*/
function  approval_block_view($delta = '') {
switch   ($delta) {
case  'pending_comments':
$block['subject'] = t('Pending Comments');
$block['content'] = approval_block_contents($delta); return  $block;
break;
case  'unpublished_nodes':
$block['subject'] = t('Unpublished Nodes');
$block['content'] = approval_block_contents($delta); return  $block;
break;}}
/**
*    module-defined   block  content function.
*/
function approval_block_contents($delta) { switch   ($delta) {
case  'pending_comments':
if (user_access('administer comments'))  {
$nbr_comments  = variable_get('pending_comment_count', 5);
$result = db_query_range('SELECT  cid,  subject FROM   {comment} WHERE status = 0', 0, $nbr_comments);
$items  = array();
foreach   ($result as  $row)  {
$items[] = l($row->subject, 'comment/'.$row->cid.'/edit');
}
return  array('#markup'  => theme('item_list',  array('items' => $items)));
}
break;
case  'unpublished_nodes':
if (user_access('administer nodes')) {
$nbr_nodes = variable_get('unpublished_node_count', 5);
$result = db_query_range('SELECT  nid, title  FROM   {node}  WHERE status = 0',  0, $nbr_nodes);
$items  = array();
foreach   ($result as  $row)  {$items[] = l($row->title, 'node/'.$row->nid.'/edit');}
return  array('#markup'  => theme('item_list',  array('items' => $items)));
}
break;}} 

The result of your new unpublished nodes block is shown in Figure  10-7.


Figure 10-7. A block listing  unpublished nodes


Enabling a Block When a Module Is Installed

In the approval module, we automatically enabled the blocks  and  assigned them to a region of the theme. For example, I created the Pending Comments block and  automatically enabled it (status = TRUE) and  assigned it to the sidebar_first region.

$blocks['pending_comments'] = array('info'  => t('Pending Comments'), 'status'  => TRUE,
'region'  => 'sidebar_first', 'weight'=> 0,);
In some cases,  you may want  to allow a site administrator to determine whether the blocks  should be enabled and  which region
they are assigned to in the theme. In that case, set the status attribute to FALSE and  do not assign a region to the block.The
following example demonstrates creating a new Pending Users block that is not automatically enabled and  is not assigned to a region.

$blocks['pending_users'] = array('info'=> t('Pending Users'), 'status'  => FALSE,'weight' => 0,);

Block Visibility Examples

Within the block administrative interface, you can enter snippets of PHP code  in the Page visibility settings” section of the block
configuration page.  When  a page is being built,  Drupal will run  the PHP snippet to determine whether a block will be displayed.
Examples of some of the most common snippets follow; each  snippet should return TRUE or FALSE to indicate whether the block
should be visible for that particular request.

Displaying a Block to Logged-In Users Only

Only return TRUE when $user->uid is not 0.
<?php
global $user;
return  (bool)  $user->uid;?>

Displaying a Block to Anonymous Users Only

Only return TRUE when $user->uid is 0.
<?php
global $user;
return  !(bool)  $user->uid;
?>

Summary

In this chapter, you learned the following:

     What blocks  are and  how they differ from nodes.

     How block visibility and  placement settings work.

     How to define a block or multiple blocks.

     How to enable a block by default.

Không có nhận xét nào:

Đăng nhận xét