IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Web development | Open source  >

使用开源软件设计、开发和部署协作型 Web 站点,第 14 部分: announcement 模块源代码

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

讨论

样例代码


级别: 中级

Alister Lewis-Bowen, 高级软件工程师, IBM 
Louis Weitzman, 高级软件工程师, IBM 
Stephen Evanchik, 软件工程师, IBM 

2007 年 9 月 14 日

在这个文章系列中,在 IBM Internet Technology Group 团队的带领下使用一套可免费获得的软件为虚构的 International Business Council(IBC) 公司设计、开发和部署一个外部网 Web 站点。在本文中,将研究整个系列中作为示例使用的 announcement 模块,展示此模块中的所有函数,这些函数可从一个文件中下载。在最后一期(第 15 部分)中,将简要回顾整个系列。

简介

本文研究在本系列中作为示例使用的 announcement 模块的源代码。这里讨论这个模块中的所有函数;大多数函数是第 6 部分 “在 Drupal 中构建定制模块” 中描述的 hook 接口的实现。这个模块是用 Drupal 4.7 编写的。下一篇文章(第 15 部分)将介绍如何将这个模块从 Drupal 4.7 迁移到 5.0。

announcement.module 的代码清单

announcement_help

这是 hook_help 的实现。这个函数让 announcement 模块能够向 Drupal 界面提供文档。(细节参见 http://api.drupal.org/api/HEAD/function/hook_help。)

输入参数:$section
决定界面的哪个部分正在请求帮助内容。在这里,我们在管理界面 admin/modules#description 下返回模块描述的内容,并在表单的顶部添加一个新的公告 node/add#announcement
返回值
一个包含帮助内容的字符串。

清单 1. hook_help 的实现
                
function announcement_help($section) {
 switch ($section) {
  case 'admin/modules#description':
    return t('Enables the creation of announcement pages ' .
    'that are presented on the home page.');
  case 'node/add#announcement':
    return t('An Announcement. Use this page to add an announcement page.');
  }
}
	

announcement_perm

这是 hook_perm 的实现。这个函数提供 announcement 模块定义的权限。可以在 Drupal 用户权限管理页面上选择这些权限,从而限制通过 announcement 模块执行的操作。(细节参见 http://api.drupal.org/api/HEAD/function/hook_perm。)

返回值
用来标识允许执行的操作的字符串数组。

清单 2. hook_perm 的实现
                
function announcement_perm() {
  return array('create announcement', 'edit announcement');
}
	

announcement_node_info

定义一个或多个节点类型的模块都需要这个函数。它使 Drupal 能够判断 announcement 模块节点类型的名称和属性。(细节参见 http://api.drupal.org/api/HEAD/function/hook_node_info。)

返回值
关于模块的节点类型的信息数组。至少需要返回可读的模块名、用来构建 hook 函数名的 Drupal 模块名以及对节点类型的简短描述。

清单 3. hook_node_info 的实现
                
function announcement_node_info() {
  return array('announcement' => array(
      'name'        => 'Announcement', 
      'description' => 'An Announcement. Use this page to add an announcement page.',
      'module'      => 'announcement'));
}
	

announcement_access

这是 hook_access 的实现。这个函数使 announcement 模块能够根据当前执行的操作和 Drupal 用户权限管理页面上定义的权限,限制对它定义的节点类型的访问。(细节参见 http://api.drupal.org/api/HEAD/function/hook_access。)

输入参数:$op
当前执行的 Drupal 操作。在这里,我们希望控制对 “create”、“view”、“update” 和 “delete” 操作的访问。
输入参数:$node
将执行此操作的节点对象。
返回值
一个布尔值,表示是否可以执行此操作。

清单 4. hook_access 的实现
                
function announcement_access($op, $node) {
	global $user;
	
	if ($op == 'create') {
	    return user_access('create announcement');
	}
	else if ($op == 'view') {
	  	return user_access('access content');
	}
	else if ($op == 'update' ||  $op == 'delete') {
	  	if($user->uid == $node->uid || user_access('edit announcement')) {
	    	return true;
		}
		else {
			return false;
		}
	}
  	else {
  		return false;
  	}
}
	

announcement_menu

这是 hook_menu 的实现。这个函数使 announcement 模块能够注册 URL 路径并判断如何处理这些请求。根据注册,可以将链接放在菜单中,也可以作为选项卡放在页面顶部。(细节参见 http://api.drupal.org/api/HEAD/function/hook_menu。)

注意:对于版本 5.X,不使用 hook_settings 函数在管理 UI 中生成论坛,而是需要注册 URL 路径 admin/settings/announcement 来映射到创建这个表单的回调函数。

输入参数:$may_cache
这是一个布尔值,用来决定注册的 URL 路径是否应该缓存。通常情况下,包含某些动态值的 URL 路径不应该缓存。
返回值
注册的 URL 路径对象的数组。其中至少包含注册的 URL 路径、用作路径标题的文本字符串、通过测试访问列表建立的访问标志、用来决定应该如何使用这个注册的类型以及在请求这个 URL 路径时应该调用的回调函数的名称。

清单 5. hook_menu 的实现
                
function announcement_menu($may_cache) {
 $items = array();
    if ($may_cache) {
 $items[] = array('path'     => 'announcements/add',
   'title'    => t('Add a new Announcement'), 
   'access'   => node_access('create', 'announcement'),
   'type'     => MENU_CALLBACK,
   'callback arguments' => array('announcement'),
   'callback' => 'node_add');	
						 
   $items[] = array('path'     => 'announcements',
     'title'    => t('Announcements'),
     'access'   => user_access('access content'),
	 'type'     => MENU_CALLBACK,
	 'callback' => 'announcement_all'); 
  	}
	else {
		
   $items[] = array('path'     => 'announcements/pager',
     'title'    => t('Announcements Pager Example'),
      'access'   => user_access('administer site'),
      'type'     => MENU_CALLBACK,
      'callback' => 'announcement_pager');	
		
      if(is_numeric(arg(1))) {			
		$node = node_load(arg(1));
			
   $items[] = array('path'     => 'announcements/' . arg(1),
	  'title'    => t('View an Announcement'),
	  'access'   => node_access('view', $node),
	   'type'     => MENU_CALLBACK,
	   'callback' => 'node_page');                      
							 
	$items[] = array('path'     => 'announcements/' . arg(1) . '/view',
		'title'    => t('View an Announcement'),
	    'access'   => node_access('view', $node),
	    'type'     => MENU_CALLBACK,
		'callback' => 'node_page');                      
							 
	 $items[] = array('path'     => 'announcements/' . arg(1) . '/edit',
		 'title'    => t('Edit an Announcement'),
		  'access'   => node_access('edit', $node),
		  'type'     => MENU_CALLBACK,
		  'callback' => 'node_page');          
							 
	  $items[] = array('path'     => 'announcements/' . arg(1) . '/delete',
	       'access'   => node_access('delete', $node),
	       'type'     => MENU_CALLBACK,
	       'callback' => 'node_delete_confirm');			
		}						 
	}
	
  	return $items;
}
	

announcement_pager

这个函数构建一套主题化的链接(称为 pager),它们链接到标明页号的公告列表的每一页。这常常放在每个标明页号的页面底部。

返回值
一个用来显示 pager 的 XHTML 字符串。

清单 6. announcement_pager 的实现
                
function announcement_pager() {
	$result = pager_query(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n " .
	             "WHERE type = 'announcement' ORDER BY n.created DESC"), 
	             variable_get('default_nodes_main', 10));
	while ($announcement = db_fetch_object($result)) {
		$output .= node_view(node_load($announcement->nid), 1);
    }
    
    $output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
    
    return $output;
}
	

announcement_cron

这是 hook_cron 的实现。这个函数使 announcement 模块能够在 cron.php 脚本运行(常常是通过 cron 系统)时插入自己的操作。这在执行周期性异步任务时很有用,比如在当前的情况中检查是否有公告过期了。我们使用这个 hook 将过期的公告标为未发布(unpublished),这样的话,非管理员用户就不能通过标准的节点机制在站点上看到它们。(细节参见 http://api.drupal.org/api/HEAD/function/hook_cron。)


清单 7. hook_cron 的实现
                
function announcement_cron() {
   $queryResult = db_query("UPDATE {node} AS n INNER JOIN {announcement} AS a " .
                           "ON n.nid = a.nid SET n.status = 0 " .
                           "WHERE n.type='announcement' AND n.status = 1 AND " .
                           "a.expiration_date < %d", time());

}
	

announcement_link

这是 hook_link 的实现。这个函数使 announcement 模块能够将自己的链接插入 Drupal 生成的内容的特定部分中。在这个示例中,根据当前用户的访问权限,将 Add、Edit 和 Delete 链接添加到 Drupal 显示的公告中。(细节参见 http://api.drupal.org/api/HEAD/function/hook_link。)

输入参数:$type
一个表示请求的链接类型的字符串。在这个示例中,就是放在公告节点下面的链接。
输入参数:$node
当前请求的节点对象。
输入参数:$teaser
一个布尔值,表示是显示整个公告,还是显示它的摘要。
返回值
l() 函数创建的链接对象的数组。

清单 8. hook_link 的实现
                
function announcement_link($type, $node = NULL, $teaser = FALSE) {
global $user;
	
$links = array();

	if($type == 'node' && $node->type == 'announcement') {
	
	if(node_access('create', 'announcement')) {			
$links[] = l(t('Add'), "node/add/announcement",
	  array('title' => t('Add a new announcement')));
		}
		
	if(node_access('update', $node)) {
$links[] = l(t('Edit'), "announcements/$node->nid/edit",
		array('title' => t('Edit Announcement ') . $node->title)); 

$links[] = l(t('Delete'), "announcements/$node->nid/delete",
		array('title' => t('Delete Announcement ') . $node->title)); 
		}
	}

	return $links;
}
	

announcement_settings

这是 hook_settings 的实现。这个函数提供一个管理界面,用来控制 announcement 模块的各种设置。(细节参见 http://api.drupal.org/api/4.7/function/hook_settings。)

注意:Drupal V5 中不使用这个 hook(http://drupal.org/node/64279#hook-settings)。

返回值
一个 Drupal Forms API 格式的元素数组描述,用来呈现设置界面。

清单 9. hook_settings 的实现
                
function announcement_settings() {
$form = array();
$form['announcement_block_max_list_count'] = array('#type' => 'textfield',
'#title'         => t('Maximum number of block announcements'),
'#default_value' => variable_get('announcement_block_max_list_count', 3),
'#description'   => t('The maximum number of items listed in the announcement block'),
'#required'      => FALSE, 
'#weight'        => 0
	);
 $form['announcement_display_classification'] = array('#type' => 'checkbox',
 '#title'         => t('Display additional announcement classification'),
 '#default_value' => variable_get('announcement_display_classification', 1),
 '#description'  => t('Insert the additional classification in the announcement modules'),
 '#required'      => FALSE, 
 '#weight'        => 0
	);
	return $form; 
}
	

announcement_form

这是 hook_form 的实现。当要创建或编辑公告时,调用这个函数来创建要显示的表单。(细节参见 http://api.drupal.org/api/HEAD/function/hook_form。)

输入参数:$node
要创建或编辑的节点。
返回值
一个 Drupal Forms API 格式的元素数组描述,用来呈现公告表单。

清单 10. hook_form 的实现
                
function announcement_form(&$node) {
	
    if ($node->expiration_date == NULL) {
        $node->expiration_date = time() + (365 * 86400);
    }

    if ($node->publish_date == NULL) {
        $node->publish_date = time();
    }
	
    $form['title'] = array('#type' => 'textfield',
        '#title'         => t('Title'),
        '#default_value' => $node->title,
        '#description'   => t('Title of the announcement'),
        '#required'      => TRUE, 
        '#weight'        => 1
    );
	
    $form['publication'] = array('#type'=> 'fieldset',
        '#collapsible'   => FALSE,
        '#title'         => t('Publication dates'),
        '#weight'        => 5 
    );
	 
    $form['publication']['publish_date'] = array(
        '#prefix'        => '<div class="date_widget">',
        '#suffix'        => '</div>',
        '#type'          => 'date',
        '#title'         => t('Publication date'),
        '#default_value' => _announcement_unixtime2drupaldate($node->publish_date)
    );

    $form['publication']['expiration_date'] = array(
        '#prefix'        => '<div class="date_widget">',
        '#suffix'        => '</div>',	
        '#type'          => 'date',
        '#title'         => t('Expiration date'),
        '#default_value' => _announcement_unixtime2drupaldate($node->expiration_date)
    );
	
    $form['abstract'] = array('#type' => 'textarea',
		'#title'         => t('Abstract'),
		'#default_value' => $node->abstract,
		'#rows'          => 3,
		'#description'   => t('Short summary of the full announcement'),
		'#required'      => TRUE,
		'#weight'        => 9 
    );
	
    $form['body'] = array('#type' => 'textarea',
        '#title'         => t('Body'),
        '#default_value' => $node->body,
        '#description'   => t('Full content for the announcement which is shown ' .
                                 'with the abstract on the details page'),
        '#required'      => TRUE, 
        '#weight' => 10 
    );
	
    return $form;
}
	

announcement_all

这个函数创建一个主题化的公告列表。对于一般用户,只显示没有过期的公告。如果用户有权编辑公告,则显示所有公告。

返回值
显示所有公告的格式化内容。

清单 11. 显示所有公告的函数
                
function announcement_all() {
	
    if (user_access('edit announcement')) {
       $queryResult = db_query(
            "SELECT n.nid FROM node n INNER JOIN announcement a ON n.nid = a.nid " .
            "WHERE n.type='announcement' ORDER BY n.sticky DESC, A.publish_date DESC");
    }
    else {
        $queryResult = db_query(
            "SELECT n.nid FROM node n INNER JOIN announcement a ON n.nid = a.nid " .
            "WHERE n.type='announcement' AND a.expiration_date > %d " .
            "ORDER BY n.sticky DESC, a.publish_date DESC", date("U"));
	}
	
    $page_content = array();
    $page_content[] = "<h2 class='category'>Announcements</h2>";
    while ($announcement = db_fetch_object($queryResult)) {
        $announcement = node_load($announcement->nid);
        $announcement->url = url('announcements/' . $announcement->nid);
        $page_content[] = theme('announcement_compact', $announcement);
    }
	
    return implode('', $page_content);
}
	

announcement_view

这是 hook_view 的实现。这个函数使 announcement 模块能够在 Drupal 系统显示任何公告节点之前添加额外的变量。在这里,我们将公告细节的 URL 插入公告节点对象。(细节参见 http://api.drupal.org/api/HEAD/function/hook_view。)

输入参数:$node
要显示的节点。
输入参数:$teaser
是生成摘要,还是整个节点。
输入参数:$page
节点是否显示为单独的页面,也就是是否应该显示页面标题。
返回值
修改后的节点对象。

清单 12. hook_view 的实现
                
function announcement_view(&$node, $teaser = FALSE, $page = FALSE) {
    if ($page) {
        $node->url = url('announcements/' . $node->nid);
    }
}
	

announcement_validate

这是 hook_validate 的实现。当用户提交了创建或编辑表单之后,调用这个函数。在这里,我们检查过期日期是否在发布日期之后。(细节参见 http://api.drupal.org/api/HEAD/function/hook_validate。)

输入参数:$node
要检验的节点。

清单 13. hook_validate 的实现
                
function announcement_validate($node) {
   if ($node) {
      $publish_date    = _announcement_drupaldate2unixtime($node->publish_date);
      $expiration_date = _announcement_drupaldate2unixtime($node->expiration_date);
      if ($publish_date >= $expiration_date) {
         form_set_error('publish_date',    
           t('The publish date of an announcement must be before its expiration date.'));
      }
   }
} 
	

announcement_submit

这是 hook_submit 的实现。这个函数使 announcement 模块能够在将数据保存到数据库中之前修改节点对象信息。在这里,我们将日期值转换为整数,并确保公告按照分类法正确地分类。(细节参见 http://api.drupal.org/api/HEAD/function/hook_submit。)

输入参数:$node
要提交到数据库的节点。

清单 14. hook_submit 的实现
                
function announcement_submit(&$node) {
    $node->publish_date    = _announcement_drupaldate2unixtime($node->publish_date);
    $node->expiration_date = _announcement_drupaldate2unixtime($node->expiration_date);
	
    $now = time();
    if($now > $node->publish_date && $now < $node->expiration_date) {
        $node->status = 1;
    }
    else {
        $node->status = 0;
    }
	
    $vocab = announcement_get_vocabulary_by_name('IBC');
    $term  = taxonomy_get_term_by_name('announcements');
    $node->taxonomy = _announcement_merge_tid($vocab->vid, 
                                              $term[0]->tid, 
                                              $node->taxonomy);
}
	

announcement_get_vocabulary_by_name

这个 helper 函数返回与给定的词汇表名称对应的词汇表对象。

输入参数:$name
要获取的词汇表的名称。
返回值
词汇表对象。

清单 15. 按名称寻找词汇表
                
function announcement_get_vocabulary_by_name ($name) {
	$results = db_query('SELECT * FROM {vocabulary} WHERE name = "%s"', $name);
	if (db_num_rows($results) > 0) {
	 	return db_fetch_object($results);
	}
	else {
		return null;
	}
}
	

_announcement_merge_tid

这是一个本地函数(由函数名前面的下划线表示),它合并词汇表中的词汇。

输入参数:$vid
词汇表 id。
输入参数:$tid
词汇 id。
输入参数:$taxonomy
词汇所属的分类法。
返回值
更新后的分类法。

清单 16. 合并词汇表的词汇
                
function _announcement_merge_tid($vid, $tid, $taxonomy) {
    $values = array_values($taxonomy[$vid]);     // get all tid values for vocabulary
    if (!in_array($tid, $values)) {              // if the tid is not there
        $taxonomy[] = $tid;                      // add it 
    }
    return $taxonomy;
}
	

announcement_load

这是 hook_load 的实现。这个函数使 announcement 模块能够在公告节点对象中添加额外的数据。在这里,我们合并来自 announcement 表的相关日期。(细节参见 http://api.drupal.org/api/HEAD/function/hook_load。)

输入参数:$node
要从数据库装载的节点。
返回值
返回来自数据库的任何额外值,这些值将合并进节点中。

清单 17. hook_load 的实现
                
function announcement_load(&$node) {
	$additions = db_fetch_object(db_query('SELECT * FROM {announcement} ' .
	                                      'WHERE nid = %d', $node->nid));
  	return $additions;
}
	

announcement_insert

这是 hook_insert 的实现。这个函数使 announcement 模块能够在将新节点插入数据库时执行操作。在这里,我们使用节点对象中的数据在 announcement 表中插入一个新记录。(细节参见 http://api.drupal.org/api/HEAD/function/hook_insert。)

输入参数:$node
要插入数据库中的节点。

清单 18. hook_insert 的实现
                
function announcement_insert($node) {
	db_query("INSERT INTO {announcement} (nid, abstract, publish_date, expiration_date) " .
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error:  The previous line is longer than the max of 90 characters ---------|
	         "VALUES (%d, '%s', '%d', '%d')", $node->nid, $node->abstract, 
	         $node->publish_date, $node->expiration_date);
	
} 
	

announcement_update

这是 hook_update 的实现。这个函数使 announcement 模块能够在数据库更新现有的公告节点时执行操作。在这里,我们执行自己的数据库更新,比如将信息放进 announcement 表中。(细节参见 http://api.drupal.org/api/HEAD/function/hook_update。)

输入参数:$node
数据库中要更新的节点。

清单 19. hook_update 的实现
                
function announcement_update($node) {
	db_query("UPDATE {announcement} SET abstract='%s', publish_date = '%s', " .
	         "expiration_date = '%s' WHERE nid = %d", $node->abstract, 
	         $node->publish_date, $node->expiration_date, $node->nid);
} 
	

announcement_delete

这是 hook_delete 的实现。这个函数使 announcement 模块能够在数据库中删除公告节点时执行操作。(细节参见 http://api.drupal.org/api/HEAD/function/hook_delete。)

输入参数:$node
要从数据库中删除的节点。

清单 20. hook_delete 的实现
                
function announcement_delete($node) {
  	db_query('DELETE FROM {announcement} WHERE nid = %d', $node->nid);
}
	

announcement_block

这是 hook_block 的实现。这个函数定义两个提供给 Drupal 系统的区块。站点管理员可以使用 Drupal 界面根据需要选择将它们放在页面上的什么位置。第一个区块列出最近更新的公告,第二个区块使用第 11 部分 “在 Drupal 中使用分类法” 中描述的 IBC 词汇表按类别列出公告。(细节参见 http://api.drupal.org/api/HEAD/function/hook_block。)

输入参数:$op
要获取的关于公告区块的信息种类。
输入参数:$delta
要返回的区块号。
输入参数:$edit
如果 $op 是 ‘save’,那么这个变量包含提交的区块配置表单数据。
返回值
如果 $op 是 ‘list’,那么它返回一个数组的数组,每个子数组必须定义一个描述区块的 info 元素。如果 $op 是 ‘view’,那么它返回一个数组,这个数组定义 ‘subject’ 和 ‘content’ 元素,这些元素定义以 $delta 为索引的区块。

清单 21. hook_block 的实现
                
function announcement_block($op = 'list', $delta = 0, $edit = array()) {
    global $user;
    if ($op == 'list') {
        $blocks[0]['info'] = t('Recently updated announcements');	
        $blocks[1]["info"] = t('List nodes in the IBC vocabulary');
        return $blocks;
    }
    else if ($op == 'view')	{
        $block	= array();
        switch ($delta) {
            case 0:
                $announcement_items	= array();
                if (user_access('access content')) {
                    $q = 'SELECT N.uid,N.nid,N.title,A.publish_date,N.status '.
                         'FROM {node} N JOIN {announcement} A USING(nid) '.
                         "WHERE N.type='announcement' ".
                         'AND N.status = 1 '.
                         'AND A.publish_date < %d ' .
                         'AND A.expiration_date > %d ' .
                         'ORDER BY A.publish_date DESC ';

                    $now = time();
                    $items = variable_get('announcement_block_max_list_count', 3);
                    $announcements = db_query_range($q, $now, $now, 0, $items);
                    while (db_num_rows($announcements) > 0 and 
                           $announcement = db_fetch_object($announcements)) {	
                        $announcement_items[] = $announcement;			
                    }
                }
                $block['subject'] = t('Announcements');
                $block['content'] = theme('announcement_block_list', 
                                          $announcement_items);
                break;
            case 1:
                if (user_access("access content")) {
                    $vocabulary = announcement_get_vocabulary_by_name('IBC');
                    $block["subject"]= t('IBC');
                    $block["content"]= announcement_vocab_vert($vocabulary->vid);
                }
        }
        return $block;
    }
}
	

announcement_vocab_vert

这个函数来自 taxonomy_dhtml 模块,用来构建在按照词汇表分类的节点区块中显示的内容。它构建一个数组,其中包含当前词汇的所有子词汇。在 HREF 中构建正确的 or 值时需要这个函数。

输入参数:$vocabulary_id
词汇表的 ID。
输入参数:$op
一个可以添加进列出的节点 URL 的操作。
返回值
用来显示区块的内容。

清单 22. 显示按照词汇表词汇分类的节点
                
function announcement_vocab_vert($vocabulary_id, $op = NULL) {
    $tree = taxonomy_get_tree($vocabulary_id);
    foreach ($tree as $term) {
        $url = "taxonomy/term/$term->tid";
        if ($op) {
            $url .= "/$op";
        }
        $link = l(t($term->name), $url, array("title" => t($term->description)));
        $out .= _taxonomy_depth($term->depth, "&nbsp;")."- $link";
        $count = taxonomy_term_count_nodes($term->tid);
        if ($count) {
            $out .= " ($count)";
            $out .= _announcement_by_terms($term->tid);
        }
        else {
            $out .= " (0)";
        }
        $out .= "<br/>";
    }
    return $out;
}
	

_announcement_by_terms

这个本地函数返回一个主题化的链接列表,它们链接到与给定的词汇表词汇对应的公告。

输入参数:$tid
要呈现的词汇的 ID。
返回值
要输出的词汇。

清单 23. 输出词汇的显示
                
function _announcement_by_terms($tid) {
	$result = '';
	$tids   = array( $tid );
	$nodes  = taxonomy_select_nodes($tids, 'or', 0, FALSE);
	while ($r = db_fetch_object($nodes)) {
		$url = "announcements/". $r->nid;
		$result .= "
&nbsp; - &nbsp;" . l($r->title, $url, array("title" => t($r->title))); } return $result; }

announcement_nodeapi

这是 hook_nodeapi 的实现。这个函数使 announcement 模块能够在 Drupal 意识到要执行特定操作时执行适当操作。在这里,如果当前的 Drupal 操作是 “update index”,就将这个公告的摘要添加到搜索索引中。(细节参见 http://api.drupal.org/api/HEAD/function/hook_nodeapi。)

输入参数:$node
要处理的节点。
输入参数:$op
节点上要执行的操作,比如 “delete”、“update index”。
返回值
这取决于我们需要的操作,在我们的示例中返回要添加进索引的节点信息。

清单 24. hook_nodeapi 的实现
                
function announcement_nodeapi(&$node, $op) {
    switch ($op) {
        case 'update index':
            if ($node->type == 'announcement') {
                $text = ''; 
                $q = db_query(
                    'SELECT a.abstract FROM node n LEFT JOIN announcement a ON '.
                    'n.nid = a.nid WHERE n.nid = %d', $node->nid);
                if ($r = db_fetch_object($q)) {
                    $text = $r->abstract;
                }
                return $text;
            }
    }
}
	

主题函数

主题设计人员可以使用以下函数改变这个模块生成数据的方式。有两类主题函数:

theme_announcement
泛型的主题函数,适用于所有主题和主题引擎
phptemplate_announcement
由 phptemplate 引擎使用的主题函数

对于本系列来说,我们不在默认主题函数中插入任何数据构造代码,而是关注如何覆盖 phptemplate 主题函数来构造数据。通常情况下,这些 phptemplate 函数放在主题目录中的 phptemplate.php 文件中。


清单 25. 主题函数
                
function theme_announcement($announcement) {
	return '';
}

function theme_announcement_compact($announcement) {
	return '';
}

function theme_announcement_block_list($announcement_list) {
	return '';
}

function phptemplate_announcement($announcement) {
 return _theme_phptemplate_announcement($announcement, 'announcement');
}

function phptemplate_announcement_compact($announcement) {
 return _theme_phptemplate_announcement
 ($announcement, 'announcement_compact');
}

function phptemplate_announcement_block_list($announcement_list) {
 global $user;
	return _phptemplate_callback('announcement_block_list', 
	  array('announcements' => $announcement_list, 
	          'user'=> $user));	
}

function _theme_phptemplate_announcement
($announcement, $announcement_template) {
	$expired = FALSE;
	if ($announcement->expiration_date < time()) {
	$expired = TRUE;		
	}
	$variables = array(
'title'      => $announcement->title,
'body'    => $announcement->body,
'links'     => $announcement->links ? theme('links', $announcement->links) : '',
'abstract'  => $announcement->abstract,
'published' => format_date($announcement->publish_date,'custom','j M, Y'),
'expires'   => format_date($announcement->expiration_date,'custom','j M, Y'), 
'expired'  => $expired,
'node'      => $announcement
	);
return _phptemplate_callback($announcement_template, $variables);	
}
	

_announcement_drupaldate2unixtime

这是一个本地实用程序函数,它将一个包含日期的结构化数据数组转换为整数。

输入参数:$drupal_date
一个用数组表示的日期,数组中包含日、月和年信息。
返回值
日期的整数表示。

清单 26. 将日期由 Drupal 内部表示转换为整数
                
function _announcement_drupaldate2unixtime($drupal_date) {

	$year  = $drupal_date["year"];
	$month = $drupal_date["month"];
	$day   = $drupal_date["day"];
	
	return mktime(0,0,0, (int)$month, (int)$day, (int)$year);
}
	

_announcement_unixtime2drupaldate

这是一个本地实用程序函数,它将日期的整数表示转换为结构化数据数组。

输入参数:$unixtime
日期的整数表示。
返回值
一个用数组表示的日期,数组中包含日、月和年信息。

清单 27. 将日期由整数转换为 Drupal 内部表示
                
function _announcement_unixtime2drupaldate($unixtime) {
    return array('day'   => format_date($unixtime, 'custom', 'j'),
                 'month' => format_date($unixtime, 'custom', 'n'),
                 'year'  => format_date($unixtime, 'custom', 'Y'));
	
}
	

结束语

本文介绍了 announcement 模块。除了提供下载文件之外,还描述了每个函数,提供了关于所使用的 Drupal hook 函数的更多信息。我们希望本文能够回答关于 announcement 模块源代码的一些常见问题。

下一篇文章是本系列的最后一篇,将总结已经学到的知识并展望 Drupal 5 的发展方向。






回页首


下载

描述名字大小下载方法
announcement 模块源代码announcement.module24KBHTTP
关于下载方法的信息


参考资料

学习

获得产品和技术

讨论


作者简介

Alister's photo

Alister Lewis-Bowen 是 IBM 的 Internet Technology Group 的高级软件工程师。他从 1993 年开始作为 IBM 英国职员从事互联网和 Web 技术方面的工作。Alister 后来到美国为 IBM 赞助的体育活动的 Web 站点工作,之后成为 ibm.com 的高级网管。他当前正在帮助创建语义 Web 原型。可以通过 alister@us.ibm.com 联系 Alister。


Louie's photo

Louis Weitzman 是 IBM 的 Internet Technology Group 的高级软件工程师。他从事设计和计算已经有 30 年了。他曾经帮助开发 ibm.com 使用的基于 XML 片段的内容管理系统,当前正在从事将设计过程融入新项目的工作。可以通过 louisw@us.ibm.com 联系 Louis。


Stephen's photo

Stephen Evanchik 是 IBM 的 Internet Technology Group 的软件工程师。他是许多开放源码软件项目的代码贡献者,其中最著名的是 Linux 内核中的 IBM TrackPoint 驱动程序。Stephen 当前从事语义 Web 技术。可以通过 evanchik@us.ibm.com 联系 Stephen。




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款