MDL-47494 ddmarker: Merge branch 'wip_imagetargetupgrader_2_1' into wip_imagetargetupgrader
This commit is contained in:
@@ -15,9 +15,10 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* @package moodlecore
|
||||
* @subpackage backup-moodle2
|
||||
* @copyright 2011 The Open University
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* @package moodlecore
|
||||
* @subpackage backup-moodle2
|
||||
* @copyright 2011 The Open University
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* ddmarker question type installation code.
|
||||
*
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
/**
|
||||
* Installation code for the ddmarker question type. It converts all existing imagetarget questions to ddmarker
|
||||
*/
|
||||
function xmldb_qtype_ddmarker_install() {
|
||||
global $DB, $OUTPUT;
|
||||
|
||||
$from = 'FROM {question_categories} cat, {question} q';
|
||||
$where = ' WHERE q.qtype = \'imagetarget\' AND q.category = cat.id ';
|
||||
|
||||
$sql = 'SELECT q.*, cat.contextid '.$from.$where.'ORDER BY cat.id, q.name';
|
||||
|
||||
$questions = $DB->get_records_sql($sql);
|
||||
|
||||
if (!empty($questions)) {
|
||||
require_once(dirname(__FILE__).'/../lib.php');
|
||||
$dragssql = 'SELECT drag.* '.$from.', {qtype_ddmarker_drags} drag'.$where.' AND drag.questionid = q.id';
|
||||
$drags = xmldb_qtype_ddmarker_index_array_of_records_by_key('questionid', $DB->get_records_sql($dragssql));
|
||||
|
||||
$dropssql = 'SELECT drop.* '.$from.', {qtype_ddmarker_drops} drop'.$where.' AND drop.questionid = q.id';
|
||||
$drops = xmldb_qtype_ddmarker_index_array_of_records_by_key('questionid', $DB->get_records_sql($dropssql));
|
||||
|
||||
$answerssql = 'SELECT answer.* '.$from.', {question_answers} answer'.$where.' AND answer.question = q.id';
|
||||
$answers = xmldb_qtype_ddmarker_index_array_of_records_by_key('question', $DB->get_records_sql($answerssql));
|
||||
|
||||
$imgfiles = $DB->get_records_sql_menu('SELECT question, qimage FROM {question_imagetarget}');
|
||||
$progressbar = new progress_bar('qtype_ddmarker_convert_from_imagetarget');
|
||||
$progressbar->create();
|
||||
$done = 0;
|
||||
foreach ($questions as $question) {
|
||||
qtype_ddmarker_convert_image_target_question($question, $imgfiles[$question->id], $answers[$question->id]);
|
||||
$done++;
|
||||
$progressbar->update($done, count($questions), get_string('convertingimagetargetquestion', 'qtype_ddmarker', $question));
|
||||
}
|
||||
list($qsql, $qparams) = $DB->get_in_or_equal(array_keys($questions));
|
||||
$DB->delete_records_select('question_answers', 'question '.$qsql, $qparams);
|
||||
$dbman = $DB->get_manager();
|
||||
$dbman->drop_table(new xmldb_table('question_imagetarget'));
|
||||
}
|
||||
}
|
||||
function xmldb_qtype_ddmarker_index_array_of_records_by_key($key, $recs) {
|
||||
$out = array();
|
||||
foreach ($recs as $id => $rec) {
|
||||
if (!isset($out[$rec->{$key}])) {
|
||||
$out[$rec->{$key}] = array();
|
||||
}
|
||||
$out[$rec->{$key}][$id] = $rec;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
@@ -20,14 +20,14 @@
|
||||
*
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2012 Jamie Pratt
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
/**
|
||||
* Class for converting attempt data from imagetarget questions when converting
|
||||
* attempts to the new question engine.
|
||||
|
||||
@@ -24,7 +24,8 @@ define('QTYPE_DDMARKER_ALLOWED_TAGS_IN_MARKER', '<br><i><em><b><strong><sup><sub
|
||||
*
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2009 The Open University
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
*
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2012 Jamie Pratt
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
@@ -51,75 +52,9 @@ class qtype_ddmarker_question_converter_list_item extends qtype_ddmarker_questio
|
||||
public $imagetargetrecord = null;
|
||||
public $answers = array();
|
||||
public function process($progresstrace = null, $depth = 0) {
|
||||
$this->convert_question();
|
||||
qtype_ddmarker_convert_image_target_question($this->record, $this->imagetargetrecord->qimage, $this->answers);
|
||||
parent::process($progresstrace, $depth);//outputs progress message
|
||||
}
|
||||
protected function convert_question() {
|
||||
global $DB;
|
||||
foreach ($this->answers as $answer) {
|
||||
$no = 1;
|
||||
if ('*' !== $answer->answer) {
|
||||
$drop = new stdClass();
|
||||
$drop->questionid = $this->record->id;
|
||||
$drop->shape = 'rectangle';
|
||||
$drop->no = $no;
|
||||
list($x1, $y1, $x2, $y2) = explode(',', $answer->answer);
|
||||
$width = $x2 - $x1;
|
||||
$height = $y2 - $y1;
|
||||
$drop->coords = "{$x1},{$y1};{$width},{$height}";
|
||||
$drop->choice = 1;
|
||||
$DB->insert_record('qtype_ddmarker_drops', $drop);
|
||||
$no++;
|
||||
$correctfeedback = $answer->feedback;
|
||||
$correctfeedbackformat = $answer->feedbackformat;
|
||||
} else {
|
||||
$incorrectfeedback = $answer->feedback;
|
||||
$incorrectfeedbackformat = $answer->feedbackformat;
|
||||
}
|
||||
}
|
||||
$drag = new stdClass();
|
||||
$drag->questionid = $this->record->id;
|
||||
$drag->no = 1;
|
||||
$drag->label = "X";
|
||||
$drag->infinite = 0;
|
||||
$DB->insert_record('qtype_ddmarker_drags', $drag);
|
||||
|
||||
$ddmarker = new stdClass();
|
||||
$ddmarker->questionid = $this->record->id;
|
||||
$ddmarker->shuffleanswers = 0;
|
||||
$ddmarker->correctfeedback = $correctfeedback;
|
||||
$ddmarker->correctfeedbackformat = $correctfeedbackformat;
|
||||
$ddmarker->partiallycorrectfeedback = '';
|
||||
$ddmarker->partiallycorrectfeedbackformat = 1;
|
||||
$ddmarker->incorrectfeedback = $incorrectfeedback;
|
||||
$ddmarker->incorrectfeedbackformat = $incorrectfeedbackformat;
|
||||
$ddmarker->shownumcorrect = 0;
|
||||
$ddmarker->showmisplaced = 0;
|
||||
$DB->insert_record('qtype_ddmarker', $ddmarker);
|
||||
|
||||
$newrec = clone($this->record);
|
||||
unset($newrec->contextid);
|
||||
$newrec->qtype = 'ddmarker';
|
||||
$newrec->timemodified = time();
|
||||
$DB->update_record('question', $newrec);
|
||||
|
||||
$fs = get_file_storage();
|
||||
$bgimagefile = $fs->get_file($this->course_context_id(),
|
||||
'course',
|
||||
'legacy',
|
||||
'0',
|
||||
'/'.dirname($this->imagetargetrecord->qimage).'/',
|
||||
basename($this->imagetargetrecord->qimage));
|
||||
$newbgimagefile = new stdClass();
|
||||
$newbgimagefile->component = 'qtype_ddmarker';
|
||||
$newbgimagefile->filearea = 'bgimage';
|
||||
$newbgimagefile->filepath = '/';
|
||||
$newbgimagefile->itemid = $this->record->id;
|
||||
$fs->create_file_from_storedfile($newbgimagefile, $bgimagefile);
|
||||
|
||||
$DB->delete_records('question_imagetarget', array('question' => $this->record->id));
|
||||
$DB->delete_records('question_answers', array('question' => $this->record->id));
|
||||
}
|
||||
}
|
||||
|
||||
$categoryid = optional_param('categoryid', 0, PARAM_INT);
|
||||
@@ -197,6 +132,7 @@ if (!count($questions)) {
|
||||
echo $contextlist->render('listitemlist', true, $top);
|
||||
}
|
||||
} else if (confirm_sesskey()) {
|
||||
require_once(dirname(__FILE__).'/lib.php');
|
||||
$questionlist->prepare_for_processing($top);
|
||||
echo '<ul>';
|
||||
$top->process();
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
*
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2011 The Open University
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
@@ -28,6 +29,7 @@ $string['answer'] = 'Answer';
|
||||
$string['bgimage'] = 'Background image';
|
||||
$string['confirmimagetargetconversion'] = 'You are about to convert the above image target questions to the drag and drop markers question type.';
|
||||
$string['coords'] = 'Coords';
|
||||
$string['convertingimagetargetquestion'] = 'Converted question "{$a->name}"';
|
||||
$string['correctansweris'] = 'The correct answer is: {$a}';
|
||||
$string['draggableimage'] = 'Draggable image';
|
||||
$string['draggableitem'] = 'Draggable item';
|
||||
|
||||
@@ -17,16 +17,21 @@
|
||||
/**
|
||||
* Serve question type files
|
||||
*
|
||||
* @since 2.0
|
||||
* @package qtype
|
||||
* @subpackage essay
|
||||
* @copyright Dongsheng Cai <[email protected]>
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
*
|
||||
* @var string label to use for drag items when converting image target questions to ddmarker question type
|
||||
*/
|
||||
define('QTYPE_DDMARKER_LABEL_FOR_MARKER_FOR_IMAGE_TARGET_QS', 'X');
|
||||
|
||||
/**
|
||||
* Checks file access for essay questions.
|
||||
@@ -36,3 +41,101 @@ function qtype_ddmarker_pluginfile($course, $cm, $context, $filearea, $args, $fo
|
||||
require_once($CFG->libdir . '/questionlib.php');
|
||||
question_pluginfile($course, $context, 'qtype_ddmarker', $filearea, $args, $forcedownload);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function qtype_ddmarker_course_context_id($catcontextid) {
|
||||
$context = get_context_instance_by_id($catcontextid);
|
||||
while ($context->contextlevel != CONTEXT_COURSE) {
|
||||
$context = get_context_instance_by_id(get_parent_contextid($context));
|
||||
}
|
||||
return $context->id;
|
||||
}
|
||||
|
||||
function qtype_ddmarker_convert_image_target_question($question, $imgfilename, $answers) {
|
||||
global $DB, $OUTPUT;
|
||||
$correctfeedback = '';
|
||||
$correctfeedbackformat = 1;
|
||||
$incorrectfeedback = '';
|
||||
$incorrectfeedbackformat = 1;
|
||||
$foundincorrectanswer = false;
|
||||
foreach ($answers as $answer) {
|
||||
$no = 1;
|
||||
if ('*' !== $answer->answer) {
|
||||
$drop = new stdClass();
|
||||
$drop->questionid = $question->id;
|
||||
$drop->shape = 'rectangle';
|
||||
$drop->no = $no;
|
||||
list($x1, $y1, $x2, $y2) = explode(',', $answer->answer);
|
||||
$width = $x2 - $x1;
|
||||
$height = $y2 - $y1;
|
||||
$drop->coords = "{$x1},{$y1};{$width},{$height}";
|
||||
$drop->choice = 1;
|
||||
$DB->insert_record('qtype_ddmarker_drops', $drop);
|
||||
$no++;
|
||||
$correctfeedback = $answer->feedback;
|
||||
$correctfeedbackformat = $answer->feedbackformat;
|
||||
} else {
|
||||
$foundincorrectanswer = true;
|
||||
$incorrectfeedback = $answer->feedback;
|
||||
$incorrectfeedbackformat = $answer->feedbackformat;
|
||||
}
|
||||
}
|
||||
if (count($answers) < 2) {
|
||||
echo $OUTPUT->notification('There are less than 2 answers. '.
|
||||
'(Normally we expect at least a correct and incorrect answer). '.
|
||||
'For question id '.$question->id.' "'.$question->name.'".',
|
||||
'notifyproblem');
|
||||
}
|
||||
if (!$foundincorrectanswer) {
|
||||
echo $OUTPUT->notification('No incorrect answer found for question id '.$question->id.' "'.$question->name.'".',
|
||||
'notifyproblem');
|
||||
}
|
||||
$drag = new stdClass();
|
||||
$drag->questionid = $question->id;
|
||||
$drag->no = 1;
|
||||
$drag->label = QTYPE_DDMARKER_LABEL_FOR_MARKER_FOR_IMAGE_TARGET_QS;
|
||||
$drag->infinite = 0;
|
||||
$DB->insert_record('qtype_ddmarker_drags', $drag);
|
||||
|
||||
$ddmarker = new stdClass();
|
||||
$ddmarker->questionid = $question->id;
|
||||
$ddmarker->shuffleanswers = 0;
|
||||
$ddmarker->correctfeedback = $correctfeedback;
|
||||
$ddmarker->correctfeedbackformat = $correctfeedbackformat;
|
||||
$ddmarker->partiallycorrectfeedback = '';
|
||||
$ddmarker->partiallycorrectfeedbackformat = 1;
|
||||
$ddmarker->incorrectfeedback = $incorrectfeedback;
|
||||
$ddmarker->incorrectfeedbackformat = $incorrectfeedbackformat;
|
||||
$ddmarker->shownumcorrect = 0;
|
||||
$ddmarker->showmisplaced = 0;
|
||||
$DB->insert_record('qtype_ddmarker', $ddmarker);
|
||||
|
||||
$newrec = clone($question);
|
||||
unset($newrec->contextid);
|
||||
$newrec->qtype = 'ddmarker';
|
||||
$newrec->timemodified = time();
|
||||
$DB->update_record('question', $newrec);
|
||||
|
||||
$fs = get_file_storage();
|
||||
//we need to look in the course legacy files area for file
|
||||
$bgimagefile = $fs->get_file(qtype_ddmarker_course_context_id($question->contextid),
|
||||
'course',
|
||||
'legacy',
|
||||
'0',
|
||||
'/'.dirname($imgfilename).'/',
|
||||
basename($imgfilename));
|
||||
if ($bgimagefile === false) {
|
||||
echo $OUTPUT->notification('File "'.$imgfilename.'" not found in legacy course files area. '.
|
||||
'For question id '.$question->id.' "'.$question->name.'".',
|
||||
'notifyproblem');
|
||||
} else {
|
||||
$newbgimagefile = new stdClass();
|
||||
$newbgimagefile->component = 'qtype_ddmarker';
|
||||
$newbgimagefile->filearea = 'bgimage';
|
||||
$newbgimagefile->filepath = '/';
|
||||
$newbgimagefile->itemid = $question->id;
|
||||
$newbgimagefile->contextid = $question->contextid;
|
||||
$fs->create_file_from_storedfile($newbgimagefile, $bgimagefile);
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,10 @@
|
||||
/**
|
||||
* Drag-and-drop markers question definition class.
|
||||
*
|
||||
* @package qtype_ddmarker
|
||||
* @copyright 2009 The Open University
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
*
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2009 The Open University
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
/**
|
||||
* Drag-and-drop markers question renderer class.
|
||||
*
|
||||
* @package qtype_ddmarker
|
||||
* @copyright 2010 The Open University
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
* Admin settings for the Opaque question type.
|
||||
*
|
||||
* @package qtype
|
||||
* @subpackage opaque
|
||||
* @copyright 2011 The Open University
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
/**
|
||||
* Drag-and-drop markers classes for dealing with shapes on the server side.
|
||||
*
|
||||
* @package qtype_ddmarker
|
||||
* @copyright 2009 The Open University
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class qtype_ddmarker_shape {
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
/**
|
||||
* Test helpers for the drag-and-drop markers question type.
|
||||
*
|
||||
* @package qtype_ddmarker
|
||||
* @copyright 2010 The Open University
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
/**
|
||||
* Unit tests for the drag-and-drop markers question definition class.
|
||||
*
|
||||
* @package qtype_ddmarker
|
||||
* @copyright 2010 The Open University
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
/**
|
||||
* Unit tests for the drag-and-drop markers question definition class.
|
||||
*
|
||||
* @package qtype_ddmarker
|
||||
* @copyright 2010 The Open University
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
*
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2010 The Open University
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
/**
|
||||
* Unit tests for the drag-and-drop markers question type.
|
||||
*
|
||||
* @package qtype_ddmarker
|
||||
* @copyright 2010 The Open University
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
/**
|
||||
* Version information for the drag-and-drop markers question type.
|
||||
*
|
||||
* @package qtype_ddmarker
|
||||
* @copyright 2011 The Open University
|
||||
* @package qtype
|
||||
* @subpackage ddmarker
|
||||
* @copyright 2012 The Open University
|
||||
* @author Jamie Pratt <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user