已要求我创建一个自定义插件,以通过API显示课程概述(课程ID,课程名称,已注册和已完成)。我可以引用一个report_completionoverview插件,基本上想通过Moodle API以JSON格式检索完全相同的列表。
我正在尝试基于穆德尔文档(https://docs.moodle.org/dev/Adding_a_web_service_to_a_plugin)和其他默认插件创建本地插件,但是调试困难。
*修改了文件夹名称以匹配插件名称*
我已经创建
local / get_completion_overview / db / service.php
local / get_completion_overview / lang / zh-CN / local_get_completion_overview.php
local / get_completion_overview / externallib.php
local / get_completion_overview / version.php
已成功在Moodle中成功安装了插件,但该函数未列出该插件。
老实说,我的代码不正确(由于我是从其他来源复制而来的,所以很乱),但不知道如何调试它。
有人可以告诉我吗?
我还附加了local / completionview / externallib.php(我确定这是导致我相信的问题)。 任何帮助或想法或意见,将不胜感激。 非常感谢!
<?php
require_once($CFG->libdir . "/externallib.php");
require_once("lib.php");
class local_get_completion_overview_external extends external_api {
public static function get_completion_overview_parameters() {
return new external_function_parameters(
array(
'field' => new external_value(PARAM_ALPHA, 'The field to search can be left empty for all courses or:
id: course id
ids: comma separated course ids
shortname: course short name
idnumber: course id number
category: category id the course belongs to
', VALUE_DEFAULT, ''),
'value' => new external_value(PARAM_RAW, 'The value to match', VALUE_DEFAULT, '')
)
);
}
public static function get_completion_overview($field = '', $value = ''){
global $CFG, $DB;
require_once($CFG->dirroot . '/course/lib.php');
require_once($CFG->libdir . '/filterlib.php');
$params = self::validate_parameters(self::get_completion_overview_parameters(),
array(
'field' => $field,
'value' => $value,
)
);
$sql = "SELECT DISTINCT cr.id AS courseid, cr.fullname AS coursename,
COUNT(DISTINCT ra.id ) AS enrols,
COUNT(DISTINCT cc.timecompleted) AS completed
FROM {course} cr
JOIN {context} ct ON ( ct.instanceid = cr.id )
LEFT JOIN {role_assignments} ra ON ( ra.contextid = ct.id ) and ra.roleid = 5
LEFT JOIN {course_completions} cc ON cc.course = cr.id
GROUP BY cr.fullname, cr.id
ORDER BY coursename";
$warnings = array();
if (empty($params['field'])) {
$courses = $DB->get_records_sql($sql, array());
} else {
switch ($params['field']) {
case 'id':
case 'category':
$value = clean_param($params['value'], PARAM_INT);
break;
case 'ids':
$value = clean_param($params['value'], PARAM_SEQUENCE);
break;
case 'shortname':
$value = clean_param($params['value'], PARAM_TEXT);
break;
case 'idnumber':
$value = clean_param($params['value'], PARAM_RAW);
break;
default:
throw new invalid_parameter_exception('Invalid field name');
}
if ($params['field'] === 'ids') {
$courses = $DB->get_records_list('course', 'id', explode(',', $value), 'id ASC');
} else {
$courses = $DB->get_records('course', array($params['field'] => $value), 'id ASC');
}
}
if(!empty($courses)){
$coursesdata = array();
$currentcourseid = null;
$course = null;
foreach($courses as $completion) {
$context = context_course::instance($course->id);
$crs = array();
$crs['courseid'] = $completion->courseid;
$crs['coursename'] = (string)$completion->coursename;
$crs['enrols'] = $completion->enrols;
$crs['completed'] = $completion->completed;
try {
self::validate_context($context);
} catch (Exception $e) {
continue;
}
if(is_null($currentcourseid) || ($completion->courseid != $currentcourseid)) {
if(!is_null($course)) {
$coursesdata[] = $course;
}
$course = array();
$course['courseid'] = $completion->courseid;
}
$course['courseid'][] = $crs;
$currentcourseid = $completion->courseid;
}
if(!is_null($course)){
$coursesdata[] = $course;
}
$courses->close();
}
$result = array();
$result['course'] = $coursesdata;
return $result;
}
public static function get_completion_overview_returns() {
return new external_single_structure(
array(
'course' => new external_multiple_structure(self::get_completion_overview(), 'list of courses completion')
)
);
}
}
** service.php
<?php
$functions = array(
'local_get_completion_overview' =>
array('classname' => 'local_get_completion_overview_external',
'methodname' => 'get_completion_overview',
'classpath' => 'local/get_completion_overview/externallib.php',
'description' => 'Get course completion overview',
'type' => 'read',
'capabilities'=> array(), //optional, useful to let the administrator know what potential capabilities the user 'could' need
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
),
);
$services = array(
'get completion overview' => array( //the name of the web service
'functions' => array ('local_get_completion_overview'), //web service functions of this service
'requiredcapability' => '', //if set, the web service user need this capability to access
//any function of this service. For example: 'some/capability:specified'
'restrictedusers' =>0, //if enabled, the Moodle administrator must link some user to this service
//into the administration
'enabled'=>1, //if enabled, the service can be reachable on a default installation
)
);
答案 0 :(得分:0)
service.php应该是services.php。 修复文件名后,它在Moodle中显示为函数,但是在加载函数时遇到问题。
未定义的属性:stdClass :: $ id /Users/lucy/Sites/moodle/local/get_completion_overview/externallib.php 在第84行
是
$context = context_course::instance($completion->id);
在foreach块中。
还
调试信息:SELECT ID,类别来自{course},其中ID为NULL [数组( )] 错误代码:invalidrecord
Stack trace: line 1562 of /lib/dml/moodle_database.php: dml_missing_record_exception thrown line 1538 of /lib/dml/moodle_database.php: call to moodle_database->get_record_select() line 6822 of /lib/accesslib.php: call to moodle_database->get_record() line 84 of /local/get_completion_overview/externallib.php: call to context_course::instance() line 138 of /local/get_completion_overview/externallib.php: call to local_get_completion_overview_external::get_completion_overview() line 124 of /lib/externallib.php: call to local_get_completion_overview_external::get_completion_overview_returns() line 219 of /webservice/renderer.php: call to external_api::external_function_info() line 121 of /admin/webservice/service_functions.php: call to core_webservice_renderer->admin_service_function_list()
答案 1 :(得分:0)
在version.php文件中增加版本号。它将触发心情进行更新。然后,您应该在Moodle中进行少量更新。之后,您应该查看列表
答案 2 :(得分:0)
这按预期工作。我已将权限更改为has_capability('moodle/site:config', $context);
如果有人遇到相同问题,我会发布解决方案。
<?php
require_once('../../config.php');
require_once($CFG->libdir . "/externallib.php");
// require_once('../lib/externallib.php');
// require_once("lib.php");
class local_get_completion_overview_external extends external_api {
public static function get_completion_overview_parameters() {
return new external_function_parameters(
array(
'field' => new external_value(PARAM_ALPHA, 'The field to search can be left empty for all courses or:
id: course id', VALUE_DEFAULT, ''),
'value' => new external_value(PARAM_RAW, 'The value to match', VALUE_DEFAULT, '')
)
);
}
public static function get_completion_overview($field='', $value=''){
global $CFG, $DB;
require_once($CFG->dirroot . '/course/lib.php');
$params = self::validate_parameters(self::get_completion_overview_parameters(),
array(
'field' => $field,
'value' => $value,
)
);
$sql = "SELECT DISTINCT cr.id AS courseid,
cr.fullname AS coursename,
COUNT(DISTINCT ra.id ) AS enrols,
COUNT(DISTINCT cc.timecompleted) AS completed
FROM {course} cr
JOIN {context} ct ON ( ct.instanceid = cr.id )
LEFT JOIN {role_assignments} ra ON ( ra.contextid = ct.id ) and ra.roleid = 5
LEFT JOIN {course_completions} cc ON cc.course = cr.id
GROUP BY cr.fullname, cr.id
ORDER BY coursename";
$warnings = array();
$coursesdata = array();
$requestedcourseids = $params['value'];
if (empty($params['field'])) {
$courses = $DB->get_records_sql($sql, array());
} else {
$value = clean_param($params['id'], PARAM_INT);
if (count($value) > 0) {
$placeholders = array();
$sql_2 = "SELECT DISTINCT cr.id AS courseid,
cr.fullname AS coursename,
COUNT(DISTINCT ra.id) AS enrols,
COUNT(DISTINCT cc.timecompleted) AS completed
FROM {course} cr JOIN {context} ct ON ( ct.instanceid = cr.id )
LEFT JOIN {role_assignments} ra ON ( ra.contextid = ct.id ) and ra.roleid = 5
LEFT JOIN {course_completions} cc ON (cc.course = cr.id)
WHERE cr.id = ".$requestedcourseids." GROUP BY cr.fullname, cr.id";
$courses = $DB->get_records_sql($sql_2, $placeholders);
}
}
if(!empty($courses)) {
$currentcourseid = null;
$course = null;
foreach($courses as $completion) {
$context = context_system::instance();
has_capability('moodle/site:config', $context);
if(is_null($currentcourseid) || ($completion->courseid != $currentcourseid)) {
if(!is_null($course)) {
$coursesdata[] = $course;
}
$course = array();
$course['courseid'] = $completion->courseid;
$course['coursename'] = $completion->coursename;
$course['enrols'] = $completion->enrols;
$course['completed'] = $completion->completed;
$course['totalcourses'] = count($course);
}
$currentcourseid = $completion->courseid;
}
if(!is_null($course)){
$coursesdata[] = $course;
}
} else {
$warning = array();
$warning['item'] = 'course';
$warning['itemid'] = $requestedcourseids;
$warning['warningcode'] = '1';
$warning['message'] = 'No course found';
$warnings[] = $warning;
}
$result['course'] = $coursesdata;
$result['warnings'] = $warnings;
return $result;
}
public static function get_completion_overview_returns() {
return new external_single_structure(
array(
'course' => new external_multiple_structure(
new external_single_structure(
array(
'courseid' => new external_value(PARAM_INT, 'description'),
'coursename' => new external_value(PARAM_TEXT, ''),
'enrols' => new external_value(PARAM_INT, '', VALUE_OPTIONAL),
'completed' => new external_value(PARAM_INT, '', VALUE_OPTIONAL),
'totalcourses' => new external_value(PARAM_INT, '', VALUE_OPTIONAL),
)
)
),
'warnings' => new external_warnings()
)
);
}
}