Moodle开发笔记2-Block开发
来源:互联网 发布:新手单反相机推荐知乎 编辑:程序博客网 时间:2024/06/05 00:13
Block是以一个长方形区域出现在moodlesite的page的左列或右列。Block是最简单、也是最常用的moodle plugin。
下面讲解如何开发一个hello world moodle block “helloworld”
1. create “helloworld” folder (目录名来自你的modulename) in ”moodle/blocks” folder
2. 在”helloworld”目录下创建blockpage “block_helloworld.php” (命名格式是 [module-type]_[module-name].php)
Block php file要创建一个同名的class,该class extends “block_base”class。同时需要有2个基本的函数:”init” and “get_content”
<?php
class block_helloworld extends block_base {
functioninit() {
$this->title= get_string('helloworld', 'block_helloworld');
$this->version= 2009050700;
}
functionget_content() {
if($this->content !== NULL) {
return$this->content;
}
$this->content= new stdClass;
$this->content->text= 'Hello World!';
return$this->content;
}
}
?>
Init函数至少要设置2个变量:block title andblock version。
block title将会显示在block区域的最上端。
block version 注意:你每次upload你的plugin to moodle system,即将上传的version必须大于当前存在于moodle的plugin version。version的格式为:YYYYMMDD##。最后2位是YYYYMMDD当天的第n个版本。例如 2010062903,表示2010年6月29日第3个update version
get_content函数所返回值就会作为blockpage显示的content。同时它会存储在$this->content变量里。
以上2步就完成了最简单的helloworld block。
如何激活?
用admin account login,然后click “Notifications”in “Site Administration” block,moodle 就会即时check and install new plugin。
安装好之后如何使用?
用admin account login,然后在你要添加helloworld的page里启动edit mode,然后in “Blocks” pull downlist,select “helloworld” block即可
上面的2步是必须的,下面的步骤是可选的
3. (Optional) Add language file(like java message properties file)。在”helloworld”目录下创建一个”lang”目录,然后在”lang”下创建一个”en_utf8”,它表示这是一个language folder for Englist with Unicode encoding。如果你希望有一个for US 方言的englist language pack,那么就在”en_utf8”目录下创建一个”en_us_utf8”目录。在Moodle里,child language会继承parent language的所有string message。
然后在”en_utf8”里创建一个与block page同名的php file:“block_helloworld.php”,然后把所有要用到的message都放到该文件里。其格式是把这些messages都存储在”$string”数组变量里。
下面一个language php file的例子:
<?PHP
$string['helloworld'] = 'Hello World';
$string['helloworld:view']= 'View Hello World Block';
$string['blockname']= 'HelloWorld';
?>
回顾一下步骤2的init函数里用到一个函数
get_string('helloworld','block_helloworld');
该函数Returnsa localized string
第一个参数对应的是language file里的message key,例如上例的第一个参数就是对应languagefile里的”helloworld”的message。
第二个参数是指定来自哪一个module的language file,例如上例指定的是helloworldblock。该参数值实际就是存储该message的php file name (不要.php extension)。例如:我们的language phpfile是block_helloworld.php,所以参数值为” block_helloworld”。
另外还有一个函数与get_string类似,就是print_string,它是把返回的string 输出。
4. (Optional but very mportant) Working withcapabilities。capabilities见上面的章节。
5. (Optional but very mportant) 添加helloworldblock的configuration interface,使得在edit mode,在block区域里多一个button link toconfiguration interface。
例子:使helloworld block具有configuration功能,使得可以设置$this->content的值
1)需要在block main page”block_helloworld.php”的block_helloworld class里添加一个returntrue的instance_allow_config函数,代码如下:
function instance_allow_config() {
return true;
}
2)在block root目录下创建一个config_instance.html file。该html file的代码实际上是php code:
<?php print_textarea(true,10, 50, 0, 0, 'text', $this->config->text); ?>
<inputtype="submit" value="submit" />
<?php use_html_editor();?>
第一行是输出一个text area (name为text),其值为$this->config->text (注意:text area的name的值必须与$this->context里的对应的key name相同),在submit之后text area的值就会自动赋值给对应的$this->context里对应的变量。例如,该例的textarea的name为text,submit之后该值就会赋给$this->context->text。
第三行是嵌入Moodle's integrated WYSIWYG editor。
3)修改block_helloworldclass的get_content()函数,使得输出的content来自configuration interface设置的值。
$this->content->text= $this->config->text;
6. (optional) add schedule function to block.
Moodle的cron.php用来运行一个schedule来执行maintenance tasks,例如email delivery and backup。它可能每5~15分钟就运行一次。
例子:如果helloworld block需要执行schedule task,你需要
1) 在block_helloworld class的init函数里添加代码:
$this->cron = 5;
这表示每5秒就会执行下面定义的cron函数一次。
2)在block_helloworld class里添加函数cron()
function cron(){
print("Hello World is running its cronprocess./n");
}
参考书中的另外一个实例:Instructorcontact block
注意:如果我们想在moodle里添加一个不需要interface的module,那么Block就是最好的选择。对于没有interface的block,$this->content->text andfooter要设置empty。如:
function get_content() {
if($this->content!== NULL) {
return$this->content;
}
$this->content= new stdClass;
$this->content->text= '';
$this->content->footer= '';
return$this->content;
}
官方moodle block开发的翻译
Ref link http://docs.moodle.org/en/Development:Blocks
以开发一个简单的”SimpleHtml” block为例来讲解。
Minimumrequirement of block
在blocks目录下创建simplehtml目录,然后在该目录下创建block_simplehtml.php
<?php
class block_simplehtml extends block_base {
//init method必须设置var title and version
function init() {
$this->title = get_string('simplehtml', 'block_simplehtml');
$this->version = 2004111200;
}
//
function get_content() {
//check content是否为null是因为moodle的内部机制在一个php page里可能对同一个block的instance都会call几次,那么为了提高性能,我们只会在创建该block instance时(这时content=null)才为其赋值
if ($this->content !== NULL) {
return $this->content;
}
$this->content = new stdClass;
$this->content->text = 'The content of our SimpleHTML block!';
$this->content->footer = 'Footer here...';
return $this->content;
}
}
?>
EnableConfigure block
首先在block_simplehtml class里添加下面的function使得该block可以configure
function instance_allow_config() {
return true;
}
然后在simplehtml目录下创建一个config_instance.html文件,该文件包含当user点击block的configuration button时要显示的configuration page的content
<?php print_string('configcontent', 'block_simplehtml'); ?>:
<?php print_textarea(true, 10, 50, 0, 0, 'text', $this->config->text); ?>
<input type="submit" value="<?php print_string('savechanges') ?>" />
<?php use_html_editor(); ?>
上面的代码就是一个简单的configuration page。你会奇怪怎么没看到<form>?对的,不需要写<form>,只需要提供你需要config的东东的input,以及一个submit button即可。当你click submit button时,moodle会自动波帮你存储config setting到$this->config里。例如上例name为“text”的input field value就会存储在$this->config->text里。this->config变量可以供block_simplehtml class里除了init() method之外的任何地方调用!
下面我们修改block_simplehtml的getContent function来使用configuration varthis->config
function get_content() {
if ($this->content !== NULL) {
return $this->content;
}
$this->content = newstdClass;
$this->content->text = $this->config->text;
$this->content->footer = 'Footer here...';
return $this->content;
}
Specialists
我想在configuration page里设置block的title,则在config_instance.html里添加
<input type="text" name="title"
value="<?php echo $this->config->title; ?>" />
但由于$this->config变量不能在init() method里使用以及$this->title不能在getContent function改变,所以无法在init()里或在getContent method里使用下列代码
$this->title = $this->config->title;
怎么办?就要使用到specialization()method来给title赋值,该method是紧接着init()后被调用,即是在before block's content is computed for the first time之前被调用。
同时specialization() method is the natural choice forany configuration data that needs to be acted upon "as soon aspossible",即可以对this->config包含的值进行预处理。例如下列代码会在specialization method里check如果this->config->text为empty,则给一个default value给它。
function specialization() {
if (!empty($this->config->title)) {
$this->title = $this->config->title;
} else {
$this->config->title = 'Some title ...';
}
if (empty($this->config->text)) {
$this->config->text = 'Some text ...';
}
}
Now You See Me, Now You Don't
有时你可能想开发一个这样的block:当有数据时,就显示该block,但当没有数据时,就隐藏整个block。典型的例子是”recentactivity” block,如果没有recentactivity,该block就会自动隐藏。
怎么实现这个功能?
很简单,只需要在get_content()里设置$this->content->text and$this->content->footer为empty string即可。(moodle在处理block时,会先call is_empty() method来check it,如果text and footer is empty,就不会显示这个block。
注意:不管该block的title是不是empty,也不管hide_header() method是hide or show header,都不会影响上述show/hide block的behavior。即当content is empty时,即使title不为empty,也不hide header,moodle照样还是会隐藏该block。
Allow multipleblock instance in a course
如果你希望在同一个course里添加同一个block的多个instance,则要在block class里添加instance_allow_multiple method
function instance_allow_multiple(){
return true;
}
要注意的是
1.即使block本身supportmultiple instance,admin还是可以通过Administration/Configuration/Blocks page来disable multiple功能。
2.如果“allow multiple”和“allow config”同时存在,则会自动disable allow config function。
The Effects ofGlobalization
有时候admin可能希望他能够有一个地方对某个block的所有instance能一次性进行设置。
例如,admin希望simplehtml block的content长度不要超过200字,或者content只允许plaintext,如果是html text,则filter html tag
首先,在blockclass里添加下列代码
function has_config() {
return true;
}
然后,创建一个file config_global.html,该file is for the configuration screen output. 在该configuration page,我们添加一个checkboxsaying "Do not allow HTML in the content"以及一个"submit"button.
<input type="hidden" name="block_simplehtml_strict" value="0" />
<input type="checkbox" name="block_simplehtml_strict" value="1"
<?php if(!empty($CFG->block_simplehtml_strict))
echo 'checked="checked"'; ?> />
<p>
<input type="submit" value="<?php print_string('savechanges'); ?>" />
</p>
上面的代码会global configure 变量block_simplehtml_strict,该变量的值在submit时会储存在$CFG->block_simplehtml_strict里。注意设置的变量名一定要是唯一,如果别的module在$CFG使用同样的变量名,那就惨啦。所以把变量命名为block_simplehtml_strict应该是ok的。
上面代码你会奇怪为什么有2个input field(一个hidden[always 0], 一个checkbox)的name都为“block_simplehtml_strict”? This is a trick。因为如果没有hiddeninput field,当checkbox没有被勾上,该variable (block_simplehtml_strict=0)根本就不会pass给request。这样就无法设置$CFG->block_simplehtml_strict=0。因此加多一个hidden是为了保证request param里一定有block_simplehtml_strict variable。
原理就是:当PHP处理formrequest时,会按the variables在form里的出现顺序进行处理。当遇到一个之前已经存在并处理了的variable,新值就会覆盖旧值。利用这一点,我们就把hidden "block_simplehtml_strict"=0放在前面,checkbox放在后面。如果没勾上checkbox,就会有hidden的值0,如果勾上,就会使用checkbox的值1。
如果你觉得用2个input field来使用同一个name太令代码confuse,有一个替代方案:overwrite config_save() method (当在global configuration page click submitbutton时,就会调用它)。
下面代码是缺省的config_save()method,其中参数$data是form request variable key value pair array。
function config_save($data) {
// Default behaviour: save all variables as $CFG properties
// You don't need to override this if you 're satisfied with the above
foreach ($data as $name => $value) {
set_config($name, $value);
}
return TRUE;
}
我们重写它使得它会check是否存在block_simplehtml_strict variable. 如果不存在,就表示没有勾上checkbox。使用这个方法就不需要添加hidden input field了,I like it.
function config_save($data) {
if(isset($data['block_simplehtml_strict'])) {
set_config('block_simplehtml_strict', '1');
}else {
set_config('block_simplehtml_strict', '0');
}
return true;
}
OK。在global confirmation page里设置了$CFG->block_simplehtml_strict,那在我们的simplehtml block里如何使用它?其实$CFG是一个超全局变量,任何地方都可以使用它。
那么在本例中我们希望根据$CFG->block_simplehtml_strict这个block global configuration,来使得block instance的content只能是plaintext,如果有html text就filter。这时我们要overwrite instance_config_save()method!
instance_config_save()
该方法允许你override the storage mechanismfor your instance configuration data,即当在某一个blockinstance的configurationpage里clicksubmit button时,就会先调用该方法,你可以重写它来对submit formdata进行处理,处理完的最后再call parent::instance_config_save($data)来调用父类缺省的instance_config_save method。. 该方法的参数是一个associative array,它包含有submit form的key/value pair。缺省的instance_config_save如下:
function instance_config_save($data) {
$data =stripslashes_recursive($data);
$this->config = $data;
return set_field('block_instance', 'configdata', base64_encode(serialize($data)),
'id', $this->instance->id);
}
从上面缺省的方法可以看到,它会先调用stripslashes_recursive方法对submitted POST data进行stripslashes and recursive的处理,然后才调用set_field方法把处理后的data存到db里该blockinstance record的"configdata" field里。
好了,现在我们通过重写instance_config_save来filter html tag
function instance_config_save($data) {
global $CFG;
if(!empty($CFG->block_simplehtml_strict)) {
//filter html tag
$data->text = strip_tags($data->text);
}
//call parent instance_config_save method
return parent::instance_config_save($data);
}
hide_header()
如果你想hideblock title/header,那么添加下列方法到blockclass
function hide_header() {
return true;
}
注意:moodle不允许在block的init() method里把title设置为empty。
preferred_width()
设置block的prefer width。 Moodle对 block的width的处理过程包括2 parts:首先moodle会query在course page里的每一个block的prefer width,然后使用最大的prefer width作为desired value。因此当你设置prefer width时,moodle不一定保证一定以这个prefer width来显示,但显示该block时应该不会小于该prefered width。
所有的standard Moodle course formatswill deliver any requested width between 180 and 210 pixels, inclusive. 当你使用下列代码时:
function preferred_width() {
// The preferred value is in pixels
return 200;
}
就会使你的blockwidth大于standard的
html_attributes()
该方法是用来控制处理block的container的。每一个block都会包含在<div> or <table> container里(即block html code会包含在<div>or <table>里)。那么该方法可以通过添加一些attributes来设置包含block的container。具体方法有下列2种
a) directly affect the end result (if we say, assignbgcolor="black")
b) 给container一个class,从而利用CSS来控制
下面的例子就用到第二种方法。
function html_attributes() {
return array(
'class' => 'sideblock block_'. $this->name(),
'onmouseover' => "alert('Mouseover on our block!');"
);
}
以上代码把包住block的container设置为class=sideblock block_xxx,这样我们就可以use that class to make CSS selectors in our themeto alter this block's visual style (for example,".sideblock.block_simplehtml { border: 1px black solid}").
另外把onmouseover赋予该block的container,使得当鼠标进入该container时,就alert.
缺省的html_attributes()method。
function html_attributes() {
// Default case: an id with the instance and a class with our name
return array('id' => 'inst'.$this->instance->id,
'class' => 'block_'. $this->name());
}
Ifyou intend to override this method, you should return the default attributes aswell as those you add yourself. The recommended wayto do this is:
function html_attributes() {
$attrs = parent::html_attributes();
// Add your own attributes here, e.g.
// $attrs['width'] = '50%';
return $attrs;
}
applicable_formats()
该方法是用来控制block可以在哪里使用。有些block可能开发者不希望在所有地方都能够使用,例如"Social Activities"block只适用于social format的course,对于weekformat的course并不合适,因此block需要设置为只有socialformat的course才能够添加该block,就要用到applicable_formatsmethod。
注意:在applicable_formats method里定义哪些地方可以使用block,是以page为设置,而不是以course来设置。这是因为blocks can be displayed in anypage that supports them。例如,thequiz view page (the first one we see when we click on the name of the quiz)also supports blocks
例1:
function applicable_formats() {
return array(
'course-view' => true,
'course-view-social' => false);
}
上述代码先设置了允许所有的course的view.php page都可以添加该block,然后再disallow social format的course的view page不能够使用它。
例2:
function applicable_formats() {
return array(
'site-index' => true,
'course-view' => true,
'course-view-social' => false,
'mod' => true,
'mod-quiz' => false
);
}
上述代码设置了a blockcan be displayed in the site front page, in courses (but not social courses)and also when we are viewing any activity module, except quiz。
例3
function applicable_formats() {
return array('site' => true);
}
上述代码设置了a block appear onlyin the site front page (如果省略page name,则看作是index page,即site = site-index)
从上面的例子可以看出page format name的格式定义方法。 例如,
l 如果你需要设置/course/view.php是否能够使用block,则format name of that page is course-view.
l 类似的,请理解a quiz view page is mod-quiz-view
定义format name的规则
- The format name for the front page of Moodle is site-index.
- The format name for courses is actually not just course-view; it is course-view-weeks, course-view-topics, etc.
- Even though there is no such page, the format name all can be used as a catch-all option.
We can include as many format names as we want in our definition of theapplicable formats. Each format can be allowed or disallowed, and there arealso three more rules that help resolve the question "is this blockallowed into this page or not?":
- Prefixes of a format name will match that format name; for example, mod will match all the activity modules. course-view will match any course, regardless of the course format. And finally, site will also match the front page (remember that its full format name is site-index).
- The more specialized a format name that matches our page is, the higher precedence it has when deciding if the block will be allowed. For example, mod, mod-quiz and mod-quiz-view all match the quiz view page. But if all three are present, mod-quiz-view will take precedence over the other two because it is a better match.
- The character * can be used in place of any word. For example, mod and mod-* are equivalent. At the time of this document's writing, there is no actual reason to utilize this "wildcard matching" feature, but it exists for future usage.
- The order that the format names appear does not make any difference.
cron
要使block具有task schedule功能,只需要2步
Step 1: add function cron
function cron() {
mtrace( "Hey, my cron script is running" );
// do something
return true;
}
Step 2: in init() method, setthe (minimum) execution interval for your cron function
$this->cron = 300; //set 5 minutes interval
注意:如果你修改了cron interval,你必须修改block的version number,然后visit Notifications page才能生效。
NOTE: Theblock cron is designed to call the cron script for that block type only. 也就是说cron并不关心该block有多少个instance。 在cronfunction里,你如果需要获取blockinstance,你要自己写代码来iterate over them。
例:
function cron() {
// get the block type from the name
$blocktype = get_record( 'block', 'name', 'my_block_name' );
// get the instances of the block
$instances = get_records( 'block_instance','blockid',$blocktype->id );
// iterate over the instances
foreach ($instances as $instance) {
// recreate block object
$block = block_instance( 'my_block_name', $instance );
$someconfigitem = $block->config->item2;
}
}
Lists and Iconstype block
它是一个只提供itemlist的block type,该list的每一行只显示一个item and an optional image (icon) next to the item。典型的例子就是course page里的”administration” block。
开发这种类型的block,你应该extend block_list,而不是block_base。另外,在getContent里不是使用$this->content->text,而是使用$this->content->items and$this->content->icons array。
class block_my_menu extends block_list {
// The init() method does not need to change at all
function get_content() {
if ($this->content !== null) {
return $this->content;
}
$this->content = new stdClass;
$this->content->items = array();
$this->content->icons = array();
$this->content->footer = 'Footer here...';
$this->content->items[] ='<a href="a.php">Menu Option1</a>';
$this->content->icons[] = '<imgsrc="1.gif" />';
// Add morelist items here
return $this->content;
}
}
- Moodle开发笔记2-Block开发
- moodle的开发笔记2
- Moodle开发笔记1
- Moodle插件开发笔记
- moodle 板块(block)开发流程小记
- Moodle开发笔记1-基础知识
- Moodle开发笔记3-Filter开发
- Moodle开发笔记4-Theme开发
- Moodle开发笔记5-Course Format开发
- Moodle开发笔记7-Activity module开发
- Moodle开发笔记6-Database操作
- moodle开发——1开发总览
- Moodle笔记
- 开发笔记-NAND Flash Bad Block Management
- IOS开发笔记22-block与@protocol
- ios学习笔记之block在ios开发中的应用
- ios学习笔记之block在ios开发中的应用
- ios学习笔记之block在ios开发中的应用
- Hadoop环境搭建亲身体验详细解说
- web代码安全问题总结(转)
- 10.5 信号_中断的系统调用
- 数组作函数的参数和返回值
- Java代码块和构造方法执行顺序问题
- Moodle开发笔记2-Block开发
- T-SQL入门攻略之4
- google提供的几种读取feed的API
- T-SQL入门攻略之5
- Moodle开发笔记3-Filter开发
- sql 触发器
- T-SQL入门攻略之6
- 转换文本框字符串为数字
- Moodle开发笔记4-Theme开发