Как отлаживать собственный плагин в Moodle - PullRequest
1 голос
/ 19 июня 2020

Меня попросили создать настраиваемый плагин, отображающий обзор курса (идентификатор курса, название курса, зачислен и завершен) через API. Есть плагин report_completionoverview, на который я могу ссылаться и в основном хочу получить точно такой же список через Moodle API в формате JSON.

enter image description here

I ' m пытается создать локальный плагин на основе документации Moodle (https://docs.moodle.org/dev/Adding_a_web_service_to_a_plugin) и других плагинов по умолчанию, но испытывает трудности с отладкой.

* измененное имя папки в соответствии с именем плагина *

Я создал

local / get_completion_overview / db / service. php

local / get_completion_overview / lang / en / local_get_completion_overview. php

local / get_completion_overview / externallib. php

local / get_completion_overview / version. php

Плагин успешно установлен без ошибок в Moodle, но плагин не указан в функции.

The plugin is installed

enter image description here

Я честно думаю, что мой код неправильный (и он беспорядочный поскольку я скопировал из разных источников), но не знаю, как его отлаживать.

Кто-нибудь, пожалуйста, дайте мне знать, если вы знаете, как?

Я также прикрепляю local / completedview / 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')
            )
            );
    }
}

** сервис. 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
        )
);

Ответы [ 3 ]

0 голосов
/ 07 июля 2020

Увеличить номер версии внутри версии. php файл. Это вызовет настройку для обновления. Затем вам следует сделать несколько обновлений в moodle. После этого вы увидите список

0 голосов
/ 18 июля 2020

Это работает как ожидалось. Я изменил разрешение на 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()
            )
        );
    }
}
0 голосов
/ 21 июня 2020

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, category FROM {course} WHERE id IS NULL [array ()] Код ошибки: 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()
...