Commit 56246c0e authored by Plugins bot's avatar Plugins bot
Browse files

PLUGIN-26927 qtype_opaque: cibot precheck request

parent ceb41588
name: Moodle plugin CI
on: [push, pull_request]
jobs:
test:
runs-on: 'ubuntu-latest'
strategy:
fail-fast: false
matrix:
include:
- php: '7.4'
moodle-branch: 'master'
database: 'pgsql'
- php: '7.4'
moodle-branch: 'MOODLE_311_STABLE'
database: 'mariadb'
services:
postgres:
image: postgres
env:
POSTGRES_USER: 'postgres'
POSTGRES_HOST_AUTH_METHOD: 'trust'
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 3
ports:
- 5432:5432
mariadb:
image: mariadb
env:
MYSQL_USER: 'root'
MYSQL_ALLOW_EMPTY_PASSWORD: "true"
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 3
steps:
- name: Checkout
uses: actions/checkout@v2
with:
path: plugin
- name: Install node
uses: actions/setup-node@v1
with:
node-version: '14.15.0'
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: mbstring, pgsql, mysqli
- name: Deploy moodle-plugin-ci
run: |
composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3
# Add dirs to $PATH
echo $(cd ci/bin; pwd) >> $GITHUB_PATH
echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH
# PHPUnit depends on en_AU.UTF-8 locale
sudo locale-gen en_AU.UTF-8
- name: Install Moodle
run: |
moodle-plugin-ci add-plugin --branch main moodleou/moodle-qbehaviour_opaque
moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1
env:
DB: ${{ matrix.database }}
MOODLE_BRANCH: ${{ matrix.moodle-branch }}
- name: phplint
if: ${{ always() }}
run: moodle-plugin-ci phplint
- name: phpcpd
if: ${{ always() }}
run: moodle-plugin-ci phpcpd
- name: phpmd
if: ${{ always() }}
run: moodle-plugin-ci phpmd
- name: codechecker
if: ${{ always() }}
run: moodle-plugin-ci codechecker
- name: validate
if: ${{ always() }}
run: moodle-plugin-ci validate
- name: savepoints
if: ${{ always() }}
run: moodle-plugin-ci savepoints
- name: mustache
if: ${{ always() }}
run: moodle-plugin-ci mustache
- name: grunt
if: ${{ always() }}
run: moodle-plugin-ci grunt
- name: phpunit
if: ${{ always() }}
run: moodle-plugin-ci phpunit
- name: behat
if: ${{ always() }}
run: moodle-plugin-ci behat --profile chrome
The Opaque question type and behaviour
https://moodle.org/plugins/qtype_opaque
Opaque (http://docs.moodle.org/en/Development:Opaque) is the Open protocol for
accessing question engines.
The Opaque protocol was originally created by sam marshall of the Open
University (http://www.open.ac.uk/) as part of the OpenMark project
(http://java.net/projects/openmark/). The Moodle implementation of Opaque was
done by Tim Hunt.
As well as OpenMark, this question type can also be used to connect to
ounit (http://code.google.com/p/ounit/) and possibly other question systems
we don't know about.
Opaque has been available since Moodle 1.8, but this version is compatible with
Moodle 3.4.
This question behaviour also requires the Opaque question type to be installed.
https://moodle.org/plugins/qbehaviour_opaque
You can install from the Moodle plugins database using the links above.
Or to install using git, type this command in the root of your Moodle install
git clone https://github.com/moodleou/moodle-qtype_opaque.git question/type/opaque
echo '/question/type/opaque/' >> .git/info/exclude
git clone https://github.com/moodleou/moodle-qbehaviour_opaque.git question/behaviour/opaque
echo '/question/behaviour/opaque/' >> .git/info/exclude
Once installed you need to go to the question type settings page
(Site administration -> Plugins -> Question types -> Opaque) to
set up the URLs of the question engines you wish to use.
https://github.com/moodleou/moodle-local_testopaqueqe can be used to test that
Opaque is working.
To be able to run all the unit tests, you need a working OpenMark install, then you need to add
define('QTYPE_OPAQUE_TEST_ENGINE_QE', 'http://example.com/om-qe/services/Om');
define('QTYPE_OPAQUE_TEST_ENGINE_TN', 'http://example.com/openmark/!question');
define('QTYPE_OPAQUE_TEST_ENGINE_PASSKEY', 'abc123');
define('QTYPE_OPAQUE_TEST_ENGINE_TIMEOUT', '5');
to your config.php file. Of these, only the first is required. The remaining
ones are optional. Specify them if your set-up needs them.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Javascript change opaque question focus.
*
* @copyright 2017 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.2
*/
define(['jquery'], function($) {
/**
* @alias module:mod_quiz/attempt
*/
var t = {
init : function() {
$( document ).ready(function() {
var checkButton = $('input[id*="_omact_gen_"]');
var opaqueTryAgainButton = $('input[id*="omact_ok"]');
var lastindex = localStorage.getItem('last_question_index');
localStorage.removeItem('last_question_index');
/* Check if last question is set */
if (lastindex !== null) {
// Because we got timeout inside inline script so we need to wait for that timeout.
setTimeout(function () {
// Scroll to last checked question.
$('html, body').animate({
scrollTop: $('#q' + lastindex).offset().top
}, 100);
// Focus on "Try again" button if exist otherwise blur all other button.
var focusTryAgainButton = $('input[id*=' + '":' + lastindex + '_omact_ok"' + ']');
if ($(focusTryAgainButton).length > 0) {
$(focusTryAgainButton).focus();
} else {
$('input[id*="_omact_ok"]').blur();
}
}, 350);
}
opaqueTryAgainButton.on('keydown', function (e) {
var keyCode = e.keyCode || e.which;
e.preventDefault();
// Tab on Try again button.
if (keyCode == 9 && !e.shiftKey) {
var slot = t.getQuestionIndex(e);
$('#q' + slot + ' input.questionflagimage').focus();
$(this).attr('tabindex', -1);
}
});
// Check button clicked.
$(checkButton).click(function (e) {
localStorage.setItem('last_question_index', t.getQuestionIndex(e));
});
// Try again button clicked.
$(opaqueTryAgainButton).click(function (e) {
localStorage.setItem('last_question_index', t.getQuestionIndex(e));
});
});
},
getQuestionIndex: function (e) {
// Save last position to scroll back to that question when the page is re-rendered.
var str = e.target.id;
var questionindex = str.substr(str.indexOf(':') + 1);
questionindex = questionindex.substr(0, questionindex.indexOf('_'));
return questionindex;
}
};
return t;
});
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @package qtype_opaque
* @copyright 2011 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Provides the information to backup ddwtos questions.
*
* @copyright 2011 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class backup_qtype_opaque_plugin extends backup_qtype_plugin {
/**
* Returns the qtype information to attach to question element.
*/
protected function define_question_plugin_structure() {
// Define the virtual plugin element with the condition to fulfill.
$plugin = $this->get_plugin_element(null, '../../qtype', 'opaque');
// Create one standard named plugin element (the visible container).
$pluginwrapper = new backup_nested_element($this->get_recommended_name());
// Connect the visible container ASAP.
$plugin->add_child($pluginwrapper);
// Now create the qtype own structures.
$opaque = new backup_nested_element('opaque', array('id'), array(
'remoteid', 'remoteversion'));
$engine = new backup_nested_element('engine', array('id'), array('name', 'passkey', 'timeout'));
$server = new backup_nested_element('server', array('type'), array('url'));
// Now the own qtype tree.
$pluginwrapper->add_child($opaque);
$opaque->add_child($engine);
$engine->add_child($server);
// Set source to populate the data.
$opaque->set_source_table('qtype_opaque_options',
array('questionid' => backup::VAR_PARENTID));
$engine->set_source_sql('
SELECT e.*
FROM {qtype_opaque_engines} e
JOIN {qtype_opaque_options} qo ON qo.engineid = e.id
WHERE qo.id = ?',
array(backup::VAR_PARENTID));
$server->set_source_table('qtype_opaque_servers',
array('engineid' => backup::VAR_PARENTID));
return $plugin;
}
/**
* Returns one array with filearea => mappingname elements for the qtype.
*
* Used by {@link get_components_and_fileareas} to know about all the qtype.
* files to be processed both in backup and restore.
*/
public static function get_qtype_fileareas() {
return array(
'correctfeedback' => 'question_created',
'partiallycorrectfeedback' => 'question_created',
'incorrectfeedback' => 'question_created');
}
}
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @package qtype_opaque
* @copyright 2011 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/question/type/opaque/enginemanager.php');
/**
* Restore plugin class that provides the necessary information
* needed to restore one ddwtos qtype plugin.
*
* @copyright 2011 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class restore_qtype_opaque_plugin extends restore_qtype_plugin {
protected $enginemanager = null;
/* Overridden. See parent class for docs. */
protected function define_question_plugin_structure() {
return array(
new restore_path_element('opaque', $this->get_pathfor('/opaque'), true),
new restore_path_element('engine', $this->get_pathfor('/opaque/engine')),
new restore_path_element('server', $this->get_pathfor('/opaque/engine/server')),
);
}
/**
* Process the qtype/opaque element.
*/
public function process_opaque($data) {
global $DB;
$engine = (object) $data['engine'][0];
$engine->questionengines = array();
$engine->questionbanks = array();
foreach ($data['engine'][0]['server'] as $server) {
if ($server['type'] == 'qe') {
$engine->questionengines[] = $server['url'];
} else if ($server['type'] == 'qb') {
$engine->questionbanks[] = $server['url'];
}
}
if (empty($engine->questionengines)) {
throw new coding_exception(
'Missing question engine URLs in an Opaque question backup.');
}
// Detect if the question is created or mapped.
$oldquestionid = $this->get_old_parentid('question');
$newquestionid = $this->get_new_parentid('question');
$questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false;
// If the question has been created by restore, we need to create its
// question_ddwtos too.
if ($questioncreated) {
// New question, insert.
$question = (object) $data;
$question->engineid = qtype_opaque_engine_manager::get()->find_or_create($engine);
$question->questionid = $newquestionid;
$DB->insert_record('qtype_opaque_options', $question);
}
}
/**
* Process the qtype/opaque/server element
*/
public function process_engine($data) {
// Do nothing. All the data is processed in process_opaque.
}
/**
* Process the qtype/opaque/server element
*/
public function process_server($data) {
// Do nothing. All the data is processed in process_opaque.
}
}
# Change log for the The Opaque question type
## Changes in 2.9
* This version works with Moodle 4.0.
## Changes in 2.8
* Change to prevent Moodle styles interfering with OpenMark questions.
* Fix automated tests to work with Moodle 3.8.
## Changes in 2.7
* Fix automated tests to work with Moodle 3.6.
## Changes in 2.6
* Privacy API implementation.
* Update to use the newer editor_ousupsub, instead of editor_supsub.
* Fix a keyboard focus issue after and OpenMark question is submitted.
* Fix a styling clash with Moodle themes and OpenMark.
* Allow self-signed certificates when connecting to the rempte question engine over HTTPS.
* Setup Travis-CI automated testing integration.
* Fix some automated tests to pass with newer versions of Moodle.
* Fix some coding style.
* Due to privacy API support, this version now only works in Moodle 3.4+
For older Moodles, you will need to use a previous version of this plugin.
## 2.5 and before
Changes were not documented here.
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* The question engine created event.
*
* @package qtype_opaque
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace qtype_opaque\event;
/**
* The question engine created event class.
*
* @since Moodle 2.7
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
**/
class engine_created extends \core\event\base {
protected function init() {
$this->data['crud'] = 'c';
$this->data['edulevel'] = self::LEVEL_OTHER;
$this->data['objecttable'] = 'qtype_opaque_engines';
}
public static function get_name() {
return get_string('eventengine_created', 'qtype_opaque');
}
public function get_description() {
return "The user with id {$this->userid} created an Opaque question engine with id {$this->objectid}.";
}
public function get_url() {
return new \moodle_url('/question/type/opaque/testengine.php?', array('engineid' => '1'));
}
public function get_legacy_logdata() {
return array($this->courseid, 'qtype_opaque', 'question/type/opaque/engines.php',
$this->objectid, $this->contextinstanceid);
}
}
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* The question engine deleted event.
*
* @package qtype_opaque
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace qtype_opaque\event;
/**
* The question engine created event class.
*
* @since Moodle 2.7
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
**/
class engine_deleted extends \core\event\base {
protected function init() {
$this->data['crud'] = 'd';
$this->data['edulevel'] = self::LEVEL_OTHER;
$this->data['objecttable'] = 'qtype_opaque_engines';
}
public static function get_name() {
return get_string('eventengine_deleted', 'qtype_opaque');
}
public function get_description() {
return "The user with id {$this->userid} deleted the Opaque question engine with id {$this->objectid}.";
}
public function get_url() {
return new \moodle_url('/question/type/opaque/engines.php?');
}
public function get_legacy_logdata() {
return array($this->courseid, 'qtype_opaque', 'question/type/opaque/engines.php',
$this->objectid, $this->contextinstanceid);
}
}
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* The question engine edited event.
*
* @package qtype_opaque
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace qtype_opaque\event;
/**
* The question engine edited event class.
*