作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
我们前面讲过contextual_pre_render_links里面,提供了hook_contextual_links_view_alter这个钩子函数。在上下文,链接呈现前,通过这个钩子函数,可以修改上下文链接,也就是说,可以伪造模拟出来一个链接。可能很多人不明白,为什么。在前面,我们看到这样的代码:
$types['contextual_links'] = array(
'#pre_render' => array('contextual_pre_render_links'),
….
这里为contextual_links元素,指定了一个预呈现回调函数contextual_pre_render_links,就是说,在呈现上下文链接的时候,会调用这个函数,而在contextual_pre_render_links里面,通过“drupal_alter('contextual_links_view', $element, $items);”,就为我们提供了一个钩子函数,来修改上下文链接。
好了,我们来看一下,具体的实现代码:
/**
* Implements hook_contextual_links_view_alter().
*/
function breadcrumb2_contextual_links_view_alter(&$element, &$items) {
if (isset($element['#contextual_links']['breadcrumb2']) && empty($items)) {
$current_path = current_path();
$element['#links'] = array(
array('title' => t('Add breadcrumb'), 'href' => 'breadcrumb/add', "query" => array('path' => $current_path, drupal_get_destination())),
);
}
}
在这里,我们直接为$element['#links']设置了一个链接。清除缓存,现在,在没有面包屑实体对象的情况下,也有上下文链接了:
我们在这里面,为链接提供了一个"query"参数,它是这样设置的;
"query" => array('path' => $current_path, drupal_get_destination())
这里面,drupal_get_destination()返回的本身就是一个数组。除了它以外,我们还提供了'path',这里的目的是,通过URL传递参数。这样,用户在添加面包屑对象的时候,就不需要输入刚才的路径了。修改文件里面的:
function breadcrumb2_add(){
$breadcrumb = entity_get_controller('breadcrumb2')->create();
//drupal_set_title(t('Create breadcrumb'));
if (isset($_GET['path'])) {
$breadcrumb->path = $_GET['path'];
}
$output = drupal_get_form('breadcrumb2_form', $breadcrumb);
return $output;
}
粗体为我们新增的代码。这里我们直接尝试从URL获取path参数,并将它赋值给$breadcrumb->path。这样用户就不用输入路径了。
当然,还有一点不足,那就是用户对于这个路径还是可以编辑的,实际上,我们应该不允许用户编辑这个路径。当路径已经存在的情况下,就不允许编辑了。因为路径是唯一的。
function breadcrumb2_form($form, &$form_state, $breadcrumb) {
……
$form['path'] = array(
'#type' => 'textfield',
'#title' => t('Path'),
'#maxlength' => 60,
'#default_value' => !empty($breadcrumb->path) ? $breadcrumb->path : '',
'#weight' => -10,
);
if (!empty($breadcrumb->path)) {
$form['path']['#disabled'] = TRUE;
}
……
在breadcrumb2_form中追加上面的粗体代码即可。这是现在的效果图:
还不错吧。还有值得改进的地方,实际上Drupal本身的面包屑,总是存在的。所以我们这里的上下文链接,不应该叫做添加面包屑。此外,删除面包屑,对我们来说也没有什么用,所以删除链接,也可以不要。最终,我们将编辑、添加面包屑,统一成为配置面包屑。下面是修改后的代码。
/**
* Implements MODULE_preprocess_HOOK().
*/
function breadcrumb2_preprocess_breadcrumb(&$variables) {
if (user_access('administer breadcrumbs') && user_access('access contextual links')) {
$contextual_links_element = array(
'#contextual_links' => array(
'breadcrumb2' => array('breadcrumb', array('0')),
)
);
$contextual_links = array(
'#type' => 'contextual_links',
'#contextual_links' => $contextual_links_element['#contextual_links'],
'#element' => $contextual_links_element,
);
$variables['contextual_links'] = drupal_render($contextual_links);
}
}
/**
* Implements hook_contextual_links_view_alter().
*/
function breadcrumb2_contextual_links_view_alter(&$element, &$items) {
if (isset($element['#contextual_links']['breadcrumb2']) && empty($items)) {
$current_path = current_path();
$breadcrumb = breadcrumb2_load_by_path($current_path);
if (!empty($breadcrumb)) {
$contextual_links_element['#contextual_links']['breadcrumb2'] = array('breadcrumb', array($breadcrumb->bid));
$element['#links'] = array(
array('title' => t('Config breadcrumb'), 'href' => 'breadcrumb/' . $breadcrumb->bid . '/edit', "query" => drupal_get_destination()),
);
}
else {
$element['#links'] = array(
array('title' => t('Config breadcrumb'), 'href' => 'breadcrumb/add', "query" => array('path' => $current_path, drupal_get_destination())),
);
}
}
}
我们这里只是构建了一个不存在的上下文链接,相当于占位符吧,然后在hook_contextual_links_view_alter里面,模拟出来上下文链接。
还有一个很小的问题,在IE8里面,鼠标常常放不到这个链接上,快移上去时,链接就会消失。后来我想到了一个办法,外面又加了层div,并为div设置了高度。这是修改后的代码:
<?php if (!empty($breadcrumb)): ?>
<div class="breadcrumb-wrapper contextual-links-region">
<h2 class="element-invisible"> <?php print t('You are here'); ?> </h2>
<?php if (!empty($breadcrumb)): ?>
<div style='height:10px'> <?php print $contextual_links; ?> </div>
<?php endif; ?>
<?php //print drupal_render($contextual_link); ?>
<div class="breadcrumb"> <?php print implode(' » ', $breadcrumb); ?> </div>
</div>
<?php endif; ?>
这里面可是有个bug哦,细心的朋友一眼可能就看出来了。到目前为止,我们已经完成了breadcrumb2模块项目的beta2版里面的所有代码了。同时还解决了Views的一个问题。我们这里也顺带的介绍一下,从beta2到beta4里面所解决的问题。以及在实践当中遇到的其它问题。