Moodle开发笔记7-Activity module开发

来源:互联网 发布:淘宝主账号修改密码 编辑:程序博客网 时间:2024/06/06 08:57

Activity modulemoodle里最复杂的module类型。Assignment, Quizmodule都属于activitymodule

 

Activitymodule can support for gradebook connectivity, course groups, course reset,and backup and restore.

 

一个典型的Activity都应该包含下列文件

  • mod_form.php - a form to set up or update an instance of this module
  • version.php - defines some meta-info
  • icon.gif - a 16x16 icon for the module
  • db/install.xml - defines the structure of db tables for all database types. Is used during module installation
  • db/upgrade.php - defines changes in the structure of db tables. Is used during module upgrade
  • db/access.php - defines module capabilities
  • index.php - a page to list all instances in a course
  • view.php - a page to view a particular instance
  • lib.php - any/all functions defined by the module should be in here. If the module name is called widget, then the required functions include:

·        widget_install() -will be called during the installation of the module

·        widget_add_instance()- code to add a new instance of widget

·        widget_update_instance()- code to update an existing instance

·        widget_delete_instance()- code to delete an instance

·        widget_user_outline()- given an instance, return a summary of a user's contribution

·        widget_user_complete()- given an instance, print details of a user's contribution

·        widget_get_view_actions()/ widget_get_post_actions() - Used by the participation report(course/report/participation/index.php) to classify actions in the logs table.

·        Other functionsavailable but not required are:

o   widget_delete_course()- code to clean up anything that would be leftover after all instances aredeleted

o   widget_process_options()- code to pre-process the form data from module settings

o   widget_reset_course_form()and widget_delete_userdata() - used to implement Reset coursefeature.

·        To avoid possibleconflict, any module functions should be named starting with widget_ and anyconstants you define should start with WIDGET_

  • backuplib.php and restorelib.php (optional)
  • settings.php or settingstree.php - (optional) a definition of an admin settings page for this module. mod/assignment/settings.php is a good simple example. mod/quiz/settingstree.php is a more complex example.
  • defaults.php - lets you easily define default values for your configuration variables. It is included by upgrade_activity_modules in lib/adminlib.php. It should define an array $defaults. These values are then loaded into the config table. Alternatively, if you set $defaults['_use_config_plugins'] to true, the values are instead loaded into the config_plugins table, which is better practice. See mod/quiz/defaults.php for an example. (This apparently only works with moodle 2.x branch.)
  • lang/en_utf8/widget.php - (optional) Lastly, each module will have some language files that contain strings for that module.

 

Moodle提供了一个activity template named NEWMODULE, you can download it at http://moodle.org/mod/data/view.php?d=13&rid=715&filter=1.当你开发activity时应该based onNEWMODULE。需要注意的是,NEWMODULE还是缺少了非常重要的功能没有涉及:backup and restore。少了这2个功能后果会很严重,很多moodle system不会安装缺少这2functionactivity module

 

下面以开发一个最为简单的“Foo” activity为例。It includes following features

l gradebook connectivity

l  course groups

l  course reset

l  backup and restore

 

Step 1 use NEWMODULE as template

1.      下载最新的NEWMODULE

2.      rename “newmodule” folder toour module name “foo”

3.      search目录下所有文件的内容,用”foo”替代”newmodule”

4.      rename lang/en_utf8/newmodule.php to foo.php

5.      copy the whole “foo” folder to<moodle home>/mod folder

 

Step 2 修改mod_form.php (important)

mod_form.php提供了当teacher create a newmodule instance时出现的forminterfaceteacher可以在该form输入对该moduleinstancesetting

 


 

mod_form.php要定义一个mod_<MODULE NAME>_mod_form class,该class需要extend moodleform_mod class.

require_once($CFG->dirroot.'/course/moodleform_mod.php');

classmod_foo_mod_form extends moodleform_mod {

 

mod_foo_mod_form class里,需要定义“definitionfunction,并在该function里创建forminstance, and then add elements (activity instance name, instruction, dateselector and grade option ) to the form instance需要注意的是:addedelement name必须和对应的field name in databasematch!!

function definition() {

global$COURSE, $CFG;

  //Create form instance

$mform =& $this->_form;

 

// creates the form header

$mform->addElement('header','general', get_string('general', 'form'));

//create text input

$mform->addElement('text', 'name',get_string('fooname', 'foo'), array('size'=>'64'));

        //input element type is controlled by the valueof the setType element

$mform->setType('name', PARAM_TEXT);

        //UI rules are defined by setting addRule

$mform->addRule('name',null, 'required', null, 'client');

// set instruction (html editor input)

$mform->addElement('htmleditor', 'instructions',get_string('instructions', 'foo'));

$mform->setType('instructions', PARAM_RAW);

$mform->addRule('instructions',get_string('required'), 'required', null, 'client');

//create html editor help button

$mform->setHelpButton('instructions',array('questions', 'richtext'), false, 'editorhelpbutton');

//create date available (date selector)

$mform->addElement('date_time_selector','timeavailable', get_string('timeavailable', 'foo'),array('optional'=>true));

$mform->setDefault('timeavailable', 0);

$mform->addElement('date_time_selector','timedue', get_string('timedue', 'foo'), array('optional'=>true));

$mform->setDefault('timedue',0);

// set grade (scale type input)

$mform->addElement('modgrade', 'scale',get_string('grade'), false);

$mform->disabledIf('scale','assessed', 'eq', 0);

 

//调用standard_coursemodule_elements方法common module进行设置。

//比如是否support group

//该方法同时也会controls the display of multiple form elements.

$features = array('groups'=>true, 'groupings'=>true,

'groupmembersonly'=>true,'outcomes'=>false, 'gradecat'=>false,'idnumber'=>false);

$this->standard_coursemodule_elements($features);

//add form buttons (cancel and submit)

$this->add_action_buttons();

}

 

Step 3 修改version.php

version.php用于manage database upgrades andenforce required versions of Moodle. upgrade.php会根据version.php的版本号来决定是否需要升级(例如upgrade related table in db)。该文件里定义了

l  modulecurrent verison

l  Moodlerequire version

l  以及cron

$module->version = 2009060103;

$module->requires= 2007101509;

$module->cron = 0;

 

 

Step 4 修改icon.gif

 

Step 5 修改install.xml

install.xml定义了the database structure for the module。你可以基于newmodule tempalteinstall.xml来通过moodle XMLDB editortool or 自己写代码来定义该moduledatabase structure

 

每个activity module必须至少有一个dbtable,而且该table name必须和module name相同。例如fooactivitytable name is footable最起码要包含下列fieldsid, name, intro, and modifiedtime

 

Foo activity我们在foo table里多定义了一些fieldscourse, timeavailable, timedue, and scale

另外,fooactivity还多定义了一个tablefoo_responses,该table包含了下列fieldsid, fooid, userid, response, and timemodifiedtable用于store one record for each user response in each foo activityinstance

 

另外,在install.xml里,还定义了database statements that are used to store user log data for a user's interaction with the modulenewmodule template by default对这部分是在log_display table定义了view, add, and update action for each module。你也可以添加更多的action type for loggingActivity module只是使用defaultcodes

 

<STATEMENTS>

<STATEMENT NAME="insert log_display" TYPE="insert" TABLE="log_display" COMMENT="Initial insert of records on tablelog_display">

<SENTENCES>

<SENTENCETEXT="(module, action, mtable, field) VALUES ('foo','view', 'foo', 'name')" />

<SENTENCETEXT="(module, action, mtable, field) VALUES ('foo', 'add', 'foo', 'name')" />

<SENTENCETEXT="(module, action, mtable, field) VALUES ('foo', 'update', 'foo', 'name')" />

 

??其实上面这段在table log_display里添加3records有什么用?

 

对于install.xml,如果该activity module已经开始使用,而你又有对install.xml进行修改,那么就要同时修改version.php。如果你是对install.xmldatabase structure进行修改,那么还要配合upgrade.php来进行

 

 

Step 6 修改db/access.php

access.php controls which capabilities can be assigned for user access. Fooactivity定义了2capabilities

l  mod/foo:submit   course student, teacher and admin areallowed

l  mod/foo:viewall   student roleis not allowed

 

<?php

//Define access capbilities

$mod_foo_capabilities = array(

    'mod/foo:submit' => array(

       'captype' => 'write',

       'contextlevel' => CONTEXT_MODULE,

       'legacy' => array(

           'student' => CAP_ALLOW,

           'teacher' => CAP_ALLOW,

           'editingteacher' => CAP_ALLOW,

           'admin' => CAP_ALLOW

        )

    ),

    'mod/foo:viewall' => array(

       'captype' => 'view',

       'contextlevel' => CONTEXT_MODULE,

       'legacy' => array(

           'student' => CAP_PREVENT,

           'teacher' => CAP_ALLOW,

           'editingteacher' => CAP_ALLOW,

           'admin' => CAP_ALLOW

        )

    )

 

);

?>

 

Step 7 修改index.php (important)

index.php file lists all of the instances ofactivity that are present in the course以及当前logined user对所有activityresponse

 

//include moodleconfig file and foo activity lib.php

require_once(dirname(dirname(dirname(__FILE__))).'/config.php');

require_once(dirname(__FILE__).'/lib.php');

//get course id from requestparam

$id= required_param('id', PARAM_INT);  // course

//如果global var$course与根据iddb获取的course不匹配,则error

if (! $course = get_record('course', 'id', $id)) {

    error('Course ID is incorrect');

}

require_course_login($course);

add_to_log($course->id,'foo','viewall',"index.php?id=$course->id", '');

 

$strfoos= get_string('modulenameplural', 'foo');

$strfoo  = get_string('modulename', 'foo');

 

///Print the header with navigation links

$navlinks= array();

$navlinks[]=array('name'=>$strfoos, 'link' => '', 'type' => 'activity');

$navigation= build_navigation($navlinks);

print_header_simple($strfoos,'', $navigation, '', '', true, '', navmenu($course));

 

//get all “foo” activity instance in the course

if (! $foos =get_all_instances_in_course('foo', $course)) {

    //如果no instance, then call function notice to print msg and exit

    notice(get_string('thereareno', 'moodle', $strfoos), "../../course/view.php?id=$course->id"); //changed

    die;

}

 

//获取当前user在该course的所有foo activity instancesresponse

//返回一个以foo instance idkeyresponse recordvaluearray “responses”

$sql= "SELECT foo_a.*

         FROM {$CFG->prefix}foo foo_b,

{$CFG->prefix}foo_responsesfoo_a

         WHERE foo_a.fooid = foo_b.id AND

              foo_b.course = $course->id AND foo_a.userid = $USER->id";

 

$responses= array () ;

if (isloggedin() and!isguestuser()

and $allresponses = get_records_sql($sql)) {

    foreach ($allresponses as $ra) {

        $responses[$ra->fooid] = $ra;

    }

    unset($allresponses);

}

 

$timenow  = time();

$strname  = get_string('name');

$strweek  = get_string('week');

$strtopic= get_string('topic');

$userquery= get_string('userquery','foo');

$yes= get_string('yes','foo');

$no= get_string('no','foo');

 

//set table format accordingto course format

if ($course->format == 'weeks') {

    $table->head  = array ($strweek, $strname, $userquery);

    $table->align = array ('center', 'left');

} else if ($course->format =='topics') {

    $table->head  = array ($strtopic, $strname,$userquery);

    $table->align = array ('center', 'left', 'left', 'left');

} else {

    $table->head  = array ($strname,$userquery);

    $table->align = array ('left', 'left', 'left');

}

 

//loop all foo instances in the course and print each fooinfo with response

foreach($foos as $foo) {

    if (!empty($responses[$foo->id])) {

        $response = $responses[$foo->id];

    } else {

        $response = "";

    }

    if (!empty($response->response)){

        if( $response->response == "1" ) {

            $fa = $yes;

        }

        else {

            $fa = $no;     

        } $response->response;

    } else {

        $fa = $no;

    }

    // Courses are divided into sections,typically weeks or topics, depending on the course

//format selected. Following code deals with section display.

// $foo居然有一个element “section”包含了session info

    $printsection= "";

    if ($foo->section !== $currentsection) {

        if ($foo->section) {

            $printsection = $foo->section;

        }

        if ($currentsection !== "") {

            $table->data[] = 'hr';

        }

        $currentsection = $foo->section;

    }

   

    //Calculate the href

    if (!$foo->visible) {  //check if the instance is hidden or visible

        //Show dimmed if the mod is hidden

        $tt_href = "<a class=/"dimmed/" href=/"view.php?id=$foo->coursemodule/">".format_string($foo->name,true)."</a>";

    } else {

        //Show normal if the mod is visible

        $tt_href = "<a href=/"view.php?id=$foo->coursemodule/">".format_string($foo->name,true)."</a>";

    }

    if ($course->format == "weeks" || $course->format == "topics") {

        $table->data[] = array ($printsection, $tt_href, $fa);

    } else {

        $table->data[] = array ($tt_href, $fa);

    }

}

 

print_heading($strfoos);

print_table($table);

 

///Finish the page

print_footer($course);

 

 

Step 8 修改view.php (important)

view.php是当user (teacher or student) click 创建好的activityinstance link后出现的interface

Foo activityview.php

l  显示一条问题

l  如果user答过这条问题,会显示他的response

l  处理当userview.phpclick cancel button

l  处理当userview.phpclick submit button

 

下面会讲解view.php里的一些重要代码

// submit_form.php定义了一个form class which extends moodleform,

//when user access fooactivity instance, provide a form to user to submit

// moodleform和之前所说的moodleform_mod用法相似。

require_once(dirname(__FILE__).'/submit_form.php');

 

//下面这部分代码是通过course module id or module instance id来获取对应的course module object ($cm) , course object($course) and foo instance object

 

//!!Course module object是来自table “mdl

//注意:course module idmodule instance id是不同的,但又是相关的

//例如,当teacher create a foo activity instance时,就会同时在”mdl_foo”table”mdl_course_modules”tableinserta record,其中”mdl_foo”table”id”field就是moduleinstance id,而”mdl_course_modules”table”id”field是该instancecourse module id,而而”mdl_course_modules”table”instance”field则是和”mdl_foo”table”id”field匹配。你可以说”mdl_foo” table”mdl_course_modules” table里的record是一对一关系。

 

// Course module object是来自table mdl_course_modules”record,它包含有下列fields: id (course module id), course (course id), module(对应tablemdl_modulesid),instance (对应tablemdl_fooid),section (所在course里的section id)

 

//如果你想通过instance id来获取course module record,可以调用get_coursemodule_from_instance function。如果你想通过coursemodule id来获取coursemodule record,可以调用get_coursemodule_from_id function

 

$id= optional_param('id', 0, PARAM_INT); // course_module ID, or

$a  = optional_param('a', 0, PARAM_INT);  // foo instance ID

 

if ($id) {

    if (! $cm = get_coursemodule_from_id('foo', $id))

        error('Course Module ID was incorrect');

    if (! $course = get_record('course', 'id', $cm->course))

        error('Course is misconfigured');

    if (! $foo = get_record('foo', 'id', $cm->instance))

        error('Course module is incorrect');

} else if ($a) {

    if (! $foo = get_record('foo', 'id', $a))

        error('Course module is incorrect');

    if (! $course = get_record('course', 'id', $foo->course))

        error('Course is misconfigured');

    if (! $cm = get_coursemodule_from_instance('foo', $foo->id, $course->id))

        error('Course Module ID was incorrect');

}

 

//print navigationlinks

$navlinks = array();

$navlinks[] = array('name' => $strfoos, 'link' => "index.php?id=$course->id", 'type' => 'activity');

$navlinks[] = array('name' => format_string($foo->name), 'link' => '', 'type' => 'activityinstance');

$navigation= build_navigation($navlinks);

print_header_simple(format_string($foo->name),'', $navigation, '', '', true,update_module_button($cm->id, $course->id, $strfoo),navmenu($course, $cm));

 

//获取该module instancecontext!!

$context = get_context_instance(CONTEXT_MODULE,$cm->id);          

//check当前user在该context里是否具有submit permission,如果没有permission,则不做任何事

if (has_capability('mod/foo:submit', $context)) {

 

//然后下面是具有submit permission要进行的操作,分为3 parts,一是当user刚进入该module instance时的代码,二是当user click cancel button,三是当userclick submit button

//注意,无论是刚进入该instance,还是clickcancel or submit button,都由view.php处理。

 

$mform= new foo_submit_form("view.php?id=$cm->id");

if ($mform->is_cancelled()){//whenuser click cancel button

} else if ($fromform=$mform->get_data()){ //when user click submit button

    add_to_log($course->id, "foo", "add response", "view.php?id=$cm->id", $foo->name, $cm->id);

    $response = new object();

    $response->response= $fromform->response;

    $response->fooid= $foo->id;

    $response->userid= $USER->id;

    $response->timemodified= time();

    //如果user之前曾经submit,update record

    if ($old_response = get_record('foo_responses', 'fooid', $response->fooid,'userid', $USER->id)) {

        $response->id = $old_response->id;

        if(! update_record('foo_responses', $response)) {

            echo get_string('errorupdateresponse','foo');

        }

    }

    //如果user未曾submit,insert record

    else {

          if(!insert_record('foo_responses', $response)) echo get_string('errorinsertresponse','foo');

    }

    // Set grades,详见该例子的lib.php/foo_grade function

    foo_grade($foo,$USER->id, $response->response);

} else {

}

 

//***显示user进入该instance时要显示的form***

$data =new stdClass();

$data->cmid= $cm->id;

 

//get response if already exists to preload in form

if ($old_response = get_record('foo_responses', 'fooid', $foo->id, 'userid', $USER->id)) { 

     $data->response = $old_response->response;

}

 

$mform->set_data($data);

$mform->display();

//**************************

   

echo('<strong>'.get_string('submissions','foo').'</strong><br>');

//!!显示userresponse!!

//如果有viewall permission,则show allparticipant responses

if (has_capability('mod/foo:viewall', $context) && $participants = foo_get_participants($foo->id))    {

    foreach ($participants as $id => $participant) {

        //print_object($id->id);

        $user = get_record( 'user', 'id', $id );

        echo( '<br>'.$user->firstname." ".$user->lastname.': ' );

        //call foo_user_complete function to look up their responses

        foo_user_complete( $user, $foo );

        echo( '</br>' );

    }

}

//若没有viewall permission,则显示current user own response

else {

    echo('<br>');

    foo_user_complete( $USER, $foo);

 

    //****下面部分是support moodle groupfeature*****

    //如果enable group,那么就显示所在的group的其他partipantresponses

 

// see if groups are enabled for an activity

$groupmode = groups_get_activity_groupmode($cm);

    if ($groupmode) {

        groups_get_activity_group($cm, true);

        groups_print_activity_menu($cm, 'view.php?id='.$id);

    }

    /// Get the current group

    if ($groupmode > 0) {

        $currentgroup = groups_get_activity_group($cm);

    } else {

        $currentgroup = 0;

    }

 

    /// Initialise the returned array, which is a matrix:  $allresponses[responseid][userid] =responseobject

    $allresponses = array();

 

    /// First get all the users who have access here

    /// To start with we assume they are all "unanswered" thenmove them later

    // get a list of all of the group participantsand their user information

    $allresponses[0] = get_users_by_capability($context, 'mod/foo:submit', 'u.id,u.picture, u.firstname, u.lastname, u.idnumber', 'u.firstname ASC', '', '', $currentgroup, '', false, true);

 

    //get a complete list of all responses for this activity instance

//save this list in $rawresponses

    $rawresponses = get_records('foo_responses', 'fooid', $foo->id);   

    if ($rawresponses) {

        echo(get_string('your_groups_performance','foo'));

        foreach ($rawresponses as $response) {

// This person is enrolled and in correct group

           if (isset($allresponses[0][$response->userid])) {  

                $userid = $response->userid;

                $user = get_record( 'user', 'id', $userid );

                echo( '<br>'.$user->firstname." ".$user->lastname.': ' );

                foo_user_complete( $user , $foo);

           }

        }

}

    echo('</br>');

//**************************

}

 

 

Step 9 完成lib.php

lib.php file stores all of the basic functions used by theother files in the module

大部分moodle requiredfunctions in lib.php都包含在newmodule template lib.php里。许多在newmodulelib.php定义的function都可以不加改变的用在我们foo activity module里。你也可以添加functionlib.php来实现代码共享,例如本例添加了一个foo_grade function

 

注意:你可以通过把你添加的functions放入locallib.php而不是lib.php里,从而达到提供代码的执行性能。这是因为core Moodle functions包含module's lib.php file, 但不需要包含locally added functions. The Moodle core programmingguidelines state that it is only necessary to create a separate file if youmake significant additions.

 

下面讲解一些lib.php里的functions

l  Function foo_add_instance

当一个foo activity instance被添加到course时,就会call foo_add_instancefunction The sample function provided by NEWMODULE is pretty complete, butit doesn't set the modification time. We add this line to set the modificationtime

$foo->timemodified= time();

 

l  Function foo_delete_instance

当一个foo activity instancecourse里被delete时,就会call foo_delete_instancefunctionWe just need tomake one minor addition to the template. We need to deleteany 'child' records stored in our foo_responses table that are related to this instance

 

if(delete_records("foo_responses", "fooid","$foo->id")) {

$result =false;

}

 

l  Function foo_user_outline

function返回a smallobject with summary information about what a user has done with a givenparticular instance of this module。该function用于查看user activity reports.

 

返回的变量$result包含下列2data

$return->time = the time they did it

$return->info = a short text description

 

 

l  Function foo_user_complete

function用于prints the user'ssubmission, if any, to the activity. This function isused by the core Moodle libraries, and also in activity Foo!'s view.php file. 例的该function用于输出参数userresponse,获取的responsefunction foo_user_outline的方法一样。

 

l  Function foo_get_participants

This function returns a listof all of the users that have participated in the activity

 

l  Function reset_course_form_definition

Newmoduletempalte并没有该functionfunction用于当courseresetThis is called by Moodle core to build the course reset formdisplayed to the user. 该例中,会往mform里添加2elements

function foo_reset_course_form_definition(&$mform) {

$mform->addElement('header','fooheader', get_string('modulenameplural', 'foo'));

$mform->addElement('advcheckbox','reset_foo', get_string('removeresponses','foo'));

}

 

l  Function foo_reset_course_form_defaults

This function is required toimplement the course reset. It enables the display of our module in the coursereset form

function foo_reset_course_form_defaults($course) {

returnarray('reset_foo'=>1);

}

 

l  Function foo_reset_userdata

This function是真正的对该moduleuser data进行resetfunction. It is called byMoodle core if a user selects the form value in the course reset。该例中,它会delete all the fooresponses for course $data->courseid.

该函数的参数为$data,它包含the data submitted from the reset course. 该函数返回的是status array

functionfoo_reset_userdata($data) {

    global $CFG;

    $componentstr = get_string('modulenameplural', 'foo');

    $status = array();

    // First, check to see if reset_foo was selected

    if (!empty($data->reset_foo)) {

        //获取要resetcourse所包含的foo instance records and delete them

        $foossql = "SELECT f.id

                         FROM {$CFG->prefix}foof

                        WHERE f.course={$data->courseid}";

        delete_records_select('foo_responses', "fooid IN ($foossql)");

        $status[] = array('component'=>$componentstr, 'item'=>get_string('removeresponses', 'foo'), 'error'=>false);

    }

 

    /// updating dates - shift may be negative too

    // resetthe date values by using the shift_course_mod_dates function from the Moodle core

    if ($data->timeshift) {

        shift_course_mod_dates('foo', array('timeopen', 'timeclose'), $data->timeshift, $data->courseid);

        $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged'), 'error'=>false);

    }

    return $status;

}

 

l  Function foo_grade

function用于insert grade record togradebook. It is called when user click submit button

function演示了如何和moodlegradebook进行interaction

 

foo activity给分非常简化,如果答Yes,则给满分,如果答No,则给0分。

 

functionfoo_grade($foo, $userid, $response) {

    global $CFG;

    if (!function_exists('grade_update'))

        //include grade lib file

        require_once($CFG->libdir.'/gradelib.php');

 

    if($response == 0)

        $grade = 0;

    else

      $grade = $foo->scale; //$foo->scale即为满分

 

 //assign aarray with both elements userid and rawgrade

     $grades = array('userid'=>$userid,'rawgrade'=>$grade);

    //assign some grading parameters

$params = array('itemname'=>$foo->name, 'idnumber'=>$foo->id);

 

//assign the grade type

    if ( $foo->scale == 0) {

        $params['gradetype'] = GRADE_TYPE_NONE;

    } else if ($foo->scale > 0) {

        $params['gradetype'] = GRADE_TYPE_VALUE;

        $params['grademax']  = $foo->scale;

        $params['grademin']  = 0;

    } else if ($foo->scale < 0) {

        $params['gradetype'] = GRADE_TYPE_SCALE;

        $params['scaleid']   = -$foo->scale;

    }

 

    if ($grades  === 'reset') {

        $params['reset'] = true;

        $grades = NULL;

    }

    //!最关键方法:insert/update grade record

    return grade_update('mod/foo', $foo->course, 'mod', 'foo', $foo->id, 0, $grades,$params);

}

 

 

Step 10 upgrade.php

file用于module upgradeIt is only necessary if we have deployed our module to users andsubsequently make updates that require the database to be changed.

 

最推荐的完成upgrade.php的方法是用moodle XMLDB editor toolIt provides a GUIthat you can use to update the database, including adding new tables. Theeditor will output both a complete new install.xml file and the PHP code needed for our upgrade.php file

 

下列代码是a sample section ofcode generated from the XMLDB editor,它讲解了当往foo table里添加一个scale field的代码

if ($result && $oldversion < 2009060103) {

///Define field scale to be added to foo

$table =new XMLDBTable('foo');

$field =new XMLDBField('scale');

$field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED,XMLDB_NOTNULL, null, null, null, '0', 'timemodified');

/// Launch add fieldscale

$result= $result && add_field($table, $field);

 

关于upgrade,详见

http://docs.moodle.org/en/Development:Installing_and_upgrading_plugin_database_tables

 

 

Step 10 Creatingbackup and restore support

Moodlecourse backup system使用XML format来保存activity databackup a course时,moodlecall所有modulebackuplib.php file里的函数

 

如果某个module并没有提供backuplib.php,那么backup course就不会backupcourse里该module的任何相关data。而且在backup时,不会提示该moduledata没有backup,只会在user restore course时才发现!

 

restorelib.php则包含了在restore moodle course时要调用的函数

 

注意:moodle 2.0重写了backup and restore的方法,但会向后兼容。

 

下面是foo activity backup xml example

<MOD>

<ID>80</ID>

<TYPE>foo</TYPE>

<INSTANCE>1</INSTANCE>

<ADDED>1250743636</ADDED>

<SCORE>0</SCORE>

<INDENT>0</INDENT>

<VISIBLE>1</VISIBLE>

<GROUPMODE>1</GROUPMODE>

<GROUPINGID>0</GROUPINGID>

<GROUPMEMBERSONLY>0</GROUPMEMBERSONLY>

<IDNUMBER>$@NULL@$</IDNUMBER>

<ROLES_OVERRIDES>

</ROLES_OVERRIDES>

<ROLES_ASSIGNMENTS>

</ROLES_ASSIGNMENTS>

</MOD>

 

下面是response保存到backup xml fileexample

<RESPONSE>

<ID>1</ID>

<USERID>2</USERID>

<RESPONSE>1</RESPONSE>

<TIMEMODIFIED>1250743885</TIMEMODIFIED>

</RESPONSE>

 

Foo activitybackuplib.php file基于moodle core 'choice'module,代码95%是一样的。只是通过search and replace “the module name”and database element

 

The foo_responses structure is verysimilar to the choice_answers table. 'choice' actually has three tables, so a few items were removed.

 

 

下面是backuplib.phpfunctions(包括通用functions and only for foo module functions

 

Common backup functions

Common backup functions should be implemented for every activitymodule.

l  foo_backup_mods(): The main entry point for thebackup process. 会为每一个activity instance in course都调用一次方法foo_backup_one_mod()

l  foo_backup_one_mod(): Creates a backup for a single instance of theactivity. 该例子里,它除了会backupinstancebasic info外,还会调用自定义函数backup_foo_responses()备份response.

l  foo_check_backup_mods(): 函数被/backupfolder下的backup libraries调用。用于生成由所有instancesetting info构成的string

l  foo_check_backup_mods_instances(): foo_check_backup_mods()对每一个instance都调用该函数来生成该instancesettinginfo string。该函数还会调用自定义函数foo_response_ids_by_instance()获取response count,并写入setting info string.

l  foo_encode_content_links(): Necessary to support interactivity linking.Ensures that interactivity links stay intact between the backup and restoreprocesses.

l  foo_ids(): Returns an array of all of the Foo! IDs for a course. Used by foo_check_backup_mods().

 

 

Backup functions only for foo module

l  backup_foo_responses(): Creates the XML output tobackup the foo_responses table. Executed from the foo_backup_mods()function.

l  foo_response_ids_by_course(): Uses an SQL query to return an array of IDs fromthe table foo_responses. Called by foo_check_backup_mods().

l  foo_response_ids_by_instance(): Returns an array of IDs for a particular instanceof foo from the foo_responses table. Called by foo_check_backup_mods_instances().

 

 

下面是restorelib.phpfunctions(包括通用functions and only for foo module functions

 

Common restore functions

Common restore functions should be implemented for every activitymodule.

 

l  foo_restore_mods(): This is the main entry pointto the restore code for the module. It is called by core Moodle to performrestores. Calls the foo_responses_restore_mods() function to perform internalrestore functions.

l  foo_decode_content_links_caller(): Reverses the link encoding from the backup process in order torestore the interactivity links. Iterates through all module content and calls foo_decode_content_links()function where needed to performthe decode. It's called from the restore_decode_content_links()function.

l  foo_decode_content_links(): Performs the actual decoding of content in therestore file. Required to support interactivity linking.

l  foo_restore_logs(): Returns a log record. Called by restore_log_module().

l  foo_restore_wiki2markdown(): Converts instructions in FORMAT_WIKI to FORMAT_MARKDOWN.

 

Restore functions only for foo module

l  foo_responses_restore_mods(): This function restores the foo_responses table entries and is called by the foo_restore_mods() function.

 

原创粉丝点击