作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
我们在前面的代码中,morelink的标签t(‘More’)是写死在里面的,通过翻译机制我们可以将其翻译成任意的中文。但是如果这一文本,能够配置的话,那么这个模块就会更通用一点。如果你觉得现在已经足够好的话,那么也无需改进,我们这里仅仅是作为一个例子,让大家接触更多的钩子和API函数。
/**
* Implements hook_menu().
*/
function block_morelink_menu() {
// Block settings.
$items['admin/config/block'] = array(
'title' => 'Block',
'description' => 'Block configuration.',
'position' => 'left',
'weight' => -10,
'page callback' => 'system_admin_menu_block_page',
'access arguments' => array('access administration pages'),
'file' => 'system.admin.inc',
'file path' => drupal_get_path('module', 'system'),
);
$items['admin/config/block/morelink'] = array(
'title' => 'More link',
'description' => 'the more link lable of block.',
'page callback' => 'drupal_get_form',
'page arguments' => array('block_morelink_label_settings'),
'access arguments' => array('administer site configuration'),
'weight' => -10,
// 'file' => 'block_morelink.admin.inc',
);
return $items;
}
这里我们实现了hook_menu(),它返回一个包含菜单项的数组。这里面每一项都以路径为键,在这里就是admin/config/block和admin/config/block/morelink。菜单项的值是一个数组,里面包含的键和值,描述了Drupal在处理该路径下的回调函数时可以做些什么。有关菜单方面的更多详细,可参看菜单系统一章。
Drupal的配置页面有多个类别,比如内容、用户、系统,都出现在主配置页面上。我们的配置是关于区块的,并没有一个类别特别适合我们。所以在这里,我们创建一个名为“Block”的新类别。
图2-4 显示在主配置页面的“Block”的新类别
在第二个菜单项中,我们将我们的配置页面放在“Block”类别的下面。这段代码说,“当用户访问页http://example.com/admin/config/block/morelink 时,调用函数drupal_get_form, 并向它传递一个表单ID block_morelink_label_settings作为参数。只有具有管理站点配置权限的用户才有权查看这个菜单。”当需要显示表单时,Drupal就会让我们提供一个表单定义。当有人访问这个路径时,Drupal就会将其映射到表单定义函数上。
function block_morelink_label_settings(){
$form['block_morelink_label'] = array(
'#type' => 'textfield',
'#title' => t('More Link lable'),
'#maxlength' => 40,
'#description' => t('The More Link lable of the block as shown to the user.') ,
'#default_value' => variable_get('block_morelink_label', t('More')),
'#weight' => -17,
);
return system_settings_form($form, TRUE);
}
注意这个表单定义函数,我们现在将其放在了module文件中,我们也可以创建一个block_morelink.admin.inc文件,然后将这个函数放在该文件中。此时需要取消“'file' => 'block_morelink.admin.inc',”前面的注释符号。Module文件中,通常只放置钩子函数和API函数,其它逻辑处理,通常都放在inc文件中。对于每个页面请求,Drupal通常都会加载所有的module文件,把相关文件放在inc文件中,有利于降低module文件的大小,可以实现缓加载,从而提升性能。但是我们的这个函数,代码量非常少,新增一个inc文件,也是有性能成本的。此时所带来的性能提升,可能还抵消不了新引入的性能成本。
在这个表单函数中,我们添加了一个文本输入框,允许用户输入更多链接的标签。在这里,我们自己没有管理表单的处理流程,而是使用了函数system_settings_form()来让系统模块为表单添加一些按钮,并让它来管理表单的验证和提交。图2-5给出了的当前表单的样子。
图2-5 block_morelink的配置页面
在前面的例子中,修改配置并点击“保存配置”按钮,就可以正常工作。下面部分将描述如何实现这一点。Drupal在数据库中有一个variable表,用来存储“名-值”对。使用variable_set($key,$value)来存储“名-值”对,使用variable_get($key,$default)来取回“名-值”对。在前面的代码中,
variable_get('block_morelink_label', t('More')),
用来取回名为block_morelink_label的变量的值,如果这个值为空,则使用默认值t('More')。
可能有读者会问,这个变量是怎么保存到数据库中的?由于我们调用了system_settings_form,我们的表单提交时,会调用system_settings_form_submit函数,在这个函数中,有以下代码:
foreach ($form_state['values'] as $key => $value) {
if ($op == t('Reset to defaults')) {
variable_del($key);
}
else {
if (is_array($value) && isset($form_state['values']['array_filter'])) {
$value = array_keys(array_filter($value));
}
variable_set($key, $value);
}
}
它会按照表单元素的名字,来保存变量的值。所以我们要保证,表单元素的名称和variable_get里面的名称保持一致。在variable表中存储和取回设置时,为了避免命名空间的冲突,前面应该以模块名字开头。表单字段和变量的键应使用同一名字。
现在,我们可以把theme_block_morelink_link($variables)函数中的相应代码替换掉了,将
$morelink_label = t('More');
替换为
$morelink_label = variable_get('block_morelink_label', 'more');
最后,由于我们在模块中,新增了一个变量,除了我们需要维护这个变量的读取与存储以外,我们还需要在这个模块被卸载时,能够删除它所定义的变量。在install文件中增加以下代码:
function block_morelink_uninstall(){
variable_del('block_morelink_label');
}
这里我们实现了hook_uninstall钩子,在这个钩子中,在这个模块被卸载时,使用variable_del函数删除变量block_morelink_label。