Moodle API文档 —— Navigation API

概述

Moodle Navigation API提供了用于对Moodle的导航系统进行设置的一些接口。

导航栏(Navigaton)是什么

理解moodle中的导航栏是非常重要的。从moodle2.0开始,我们就致力于把导航栏变得规范化,使其贯穿moodle系统的始终,并且使moodle具有更好的层次结构。导航栏可以通过页面对象$PAGE获取,也就是你用来设置页面的标题、页眉、和javaScript请求等东西的对象。导航栏利用$PAGE中包含的信息来为网站生成一个导航结构。

导航结构可以通过三个变量获取:

  • $PAGE->navigation : 主导航结构,其中包含允许用户浏览的一些其他的可访问的页面
  • $PAGE->settingsnav : ‘设置’导航结构,其中包含允许用户编辑的设置
  • $PAGE->navbar : 导航条(navbar)是一个用于面包屑导航(breadcrumbs)的特殊的结构

导航栏不是什么

导航栏不是导航栏版块(navigation block)或设置版块(setting block)!这两个版块是用于展示导航栏结构的,导航栏板块其实是$PAGE->navigation,设置板块是$PAGE->settingsnav,这两个板块都是以板块(blocks)的形式开发、渲染的。

  1. 导航栏是一个后端(back-end)结构,不能直接展示到页面上。
  2. 导航栏板块和设置板块将后端的导航栏结构展示出来,但是不会对它进行修改。

在MVC(model-view-controller)模型中, $PAGE->navigation, $PAGE->settingsnav, 和 $PAGE->navbar 都属于models, 板块(blocks)属于views。

导航栏的运行机制

主导航结构可以通过$PAGE->navigation访问。主导航板块和设置板块都与你当前访问的页面上下文有关,它取决于$PAGE对象的属性:

  • $PAGE->context moodle上下文,可以直接概括出用户当前所在页面的性质
  • $PAGE->course 是当前用户浏览的页面所属的课程。如果当前的context是CONTEXT_COURSE或者更高层级的上下文,那么这个属性是必不可少的。当然,这个属性在context是其他层级的时候也有可能会用到,例如CONTEXT_USER
  • $PAGE->cm 当前所在的课程模块, 这个属性在context是CONTEXT_MODULE或者更高层级的上下文时是必不可少的。
  • $PAGE->url 用于匹配当前活动的导航条目

几乎每个页面都通过函数$PAGE->url()来设置$PAGE->url,然而,许多页面都不显式的设定$PAGE的context,course和cm。当你调用require_login()函数并给它传入course或cm时,它会自动的进行下述设置:

1
2
3
4
if ($cm) {
$PAGE->set_cm($cm, $course); // sets up global $COURSE
} else {
$PAGE->set_course($course);// sets up global $COURSE

一个页面只有在以下几种情况下才必须要显式的设置context,course或cm:

  1. require_login() 调用出错
  2. 当且页面使用的context为 CONTEXT_SYSTEM, CONTEXT_COURSECAT, or CONTEXT_USER(调用$PAGE->set_context()
  3. 当且页面在使用课程或课程模块,但是它也使用了上述的context(调用 $PAGE->set_course()$PAGE->set_cm()

在对$PAGE对象进行设置之前无法生成导航结构。它只有在第一次使用的时候或有东西要访问它的时候或代码尝试向里面添加东西的时候才会生成。导航结构以一种特定的顺序进行初始化:

  1. 主导航结构
  2. ‘设置’导航结构
  3. 导航条(不需要生成,因为它仅包含简单的文本和渲染效果)

导航栏扩展

代码扩展(Code extension)

这种方式是指在运行时通过代码对其进行扩展。这意味着你在任何地方都可以很容易的对导航栏进行扩展。当然,只有你的代码被执行的时候,这个扩展才会被显示到网页上。(你应该将代码放在lib.php的函数中)

下面的这些例子是从moodle论坛中的 General Developer Forum: Moodle 2 - how to set up breadcrumbs for a module page这篇帖子中截取的,其中包含了许多moodle的开发方法,很值得一读。

主导航板块(Navigation)

这是对主导航结构做的扩展

1
2
3
$previewnode = $PAGE->navigation->add(get_string('preview'), new moodle_url('/a/link/if/you/want/one.php'), navigation_node::TYPE_CONTAINER);
$thingnode = $previewnode->add(get_string('name of thing'), new moodle_url('/a/link/if/you/want/one.php'));
$thingnode->make_active();

上面几行代码在主导航栏的底部增加了预览节点,并且增加了该节点下的子节点thingnode。最后一行代码使该thingnode变得活跃,这是为了在用户访问的url与你给出的url相同时,会自动的更新导航条

下面的是对课程导航结构做的扩展。你需要首先知道 课程id并保证已经调用过require_login($courseorid),这是为了使主导航板块切换到课程的导航结构。

1
2
3
$coursenode = $PAGE->navigation->find($courseid, navigation_node::TYPE_COURSE);
$thingnode = $coursenode->add(get_string('Name of thing'), new moodle_url('/a/link/if/you/want/one.php'));
$thingnode->make_active();

第一行代码通过传入参数courseid和导航节点类型TYPE_COURSE在导航结构中找到了课程节点(course node)。我们在这里做的事是向课程节点下添加一个新节点。

需要注意的是,moodle中按照字典序来加载插件,因此插件b可以看到插件a新建的节点,而插件a不能看到插件b新建的节点。

设置板块(seeting Navigation)

向设置板块中添加内容和主导航板块非常相似。

1
2
3
$settingnode = $PAGE->settingsnav->add(get_string('setting'), new moodle_url('/a/link/if/you/want/one.php'), navigation_node::TYPE_CONTAINER);
$thingnode = $settingnode->add(get_string('Name of thing'), new moodle_url('/a/link/if/you/want/one.php'));
$thingnode->make_active();

向主导航板块中添加设置节点(setting folder)

一个设置节点的例子可以在网站的administration / Plugins / Activity modules / Assignment中看到。

pic1

向一个板块(block)的setting.php文件中添加带有设置节点(setting folder)的导航节点(navigation folder)的例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
defined('MOODLE_INTERNAL') || die;
// Create folder / submenu in block menu, modsettings for activity modules, localplugins for Local plugins.
// The default folders are defined in admin/settings/plugins.php.
$ADMIN->add('blocksettings', new admin_category('blocksamplefolder',
get_string('pluginname', 'mod_sample')));
// Create settings block.
$settings = new admin_settingpage($section, get_string('settings', 'block_sample'));
if ($ADMIN->fulltree) {
$settings->add(new admin_setting_configcheckbox('block_sample_checkbox', get_string('checkbox', 'block_sample'),
get_string('checkboxdescription', 'block_kronoshtml'), 0));
}
// This adds the settings link to the folder/submenu.
$ADMIN->add('blocksamplefolder', $settings);
// This adds a link to an external page.
$ADMIN->add('blocksamplefolder', new admin_externalpage('block_sample_page', get_string('externalpage', 'block_sample'),
$CFG->wwwroot.'/blocks/sample/sample.php'));
// Prevent Moodle from adding settings block in standard location.
$settings = null;

导航条(Navbar)

下面是对导航条的扩展

1
2
3
$PAGE->navbar->ignore_active();
$PAGE->navbar->add(get_string('preview'), new moodle_url('/a/link/if/you/want/one.php'));
$PAGE->navbar->add(get_string('name of thing'), new moodle_url('/a/link/if/you/want/one.php'));

上述代码使导航条忽略当前所在的真实页面,而使用你刚刚在主导航板块添加的导航结构

插件的回调函数(Plugin Callbacks)

有一些特定的插件中的函数可以使导航栏寻找并调用,目前只有三种插件支持这种通过回调函数实现的扩展方式。

理想情况下,在”Administration / Site administration”结构树中的所有条目都应该在setting.php中被实现,但是有时一些条目会被更早的通过直接修改导航结构的方式添加到admin setting树中。(例如添加外部页面的链接)

课程模块(Module,也叫活动模块(Activity Module))

课程模块有两个回调函数,第一个是对主导航板块的扩展,第二个是对设置板块的扩展。这些回调函数在用户访问该课程模块下的页面是会被调用,并且只会对该课程模块下的导航结构进行扩展。

1
2
function {modulename}_extend_navigation(${modulename}node, $course, $module, $cm)
function {modulename}_extend_settings_navigation($settings, ${modulename}node)

课程格式(Course Formats)

课程格式可以完全重定义一个课程的导航结构,当然,有一些相应的函数来确保课程的导航结构会被正确的生成。

课程报告(Course Reports)

默认的课程报告没有添加在主导航板块中,然而,一些回调函数允许他们这样做。

新的回调函数

新版本(Moodle3.0)添加了一些新的回调函数,这里暂时不予介绍。

问题和解决方案

我的当前页面已经添加到了导航栏中,但是为什么没有找到对应的条目?

首先你需要检查你为当前页面设置的url,它必须和你在导航栏中添加的节点的url保持一致。如果不一致的话,你有两种解决方法:

  • 使用$PAGE->set_url()修改你当前页面的url
  • 按照如下格式重新设置导航栏中相应节点的url
1
navigation_node::override_active_url(new moodle_url('/your/url/here.php', array('param'=>'value')));