mirror of
https://github.com/moodle/moodle.git
synced 2025-08-09 02:46:40 +02:00
Merge branch 'master_MDL-71696-versioning-integration' of https://github.com/catalyst/moodle-MDL-70329
This commit is contained in:
commit
b841a811be
223 changed files with 7768 additions and 2899 deletions
|
@ -92,7 +92,7 @@ class category_condition extends condition {
|
|||
$categoryids = [$this->category->id];
|
||||
}
|
||||
list($catidtest, $this->params) = $DB->get_in_or_equal($categoryids, SQL_PARAMS_NAMED, 'cat');
|
||||
$this->where = 'q.category ' . $catidtest;
|
||||
$this->where = 'qbe.questioncategoryid ' . $catidtest;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
namespace core_question\bank\search;
|
||||
|
||||
use core_question\local\bank\question_version_status;
|
||||
|
||||
/**
|
||||
* This class controls whether hidden / deleted questions are hidden in the list.
|
||||
*
|
||||
|
@ -46,7 +48,8 @@ class hidden_condition extends condition {
|
|||
public function __construct($hide = true) {
|
||||
$this->hide = $hide;
|
||||
if ($hide) {
|
||||
$this->where = 'q.hidden = 0';
|
||||
$this->where = "qv.status = '" . question_version_status::QUESTION_STATUS_READY . "' " .
|
||||
" OR qv.status = '" . question_version_status::QUESTION_STATUS_DRAFT . "' ";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ class core_question_external extends external_api {
|
|||
|
||||
$cantag = question_has_capability_on($question, 'tag');
|
||||
$questioncontext = \context::instance_by_id($question->contextid);
|
||||
$contexts = new \question_edit_contexts($editingcontext);
|
||||
$contexts = new \core_question\local\bank\question_edit_contexts($editingcontext);
|
||||
|
||||
$formoptions = [
|
||||
'editingcontext' => $editingcontext,
|
||||
|
@ -300,7 +300,7 @@ class core_question_external extends external_api {
|
|||
|
||||
$categorycontextid = $DB->get_field('question_categories', 'contextid', ['id' => $categoryid], MUST_EXIST);
|
||||
$categorycontext = \context::instance_by_id($categorycontextid);
|
||||
$editcontexts = new \question_edit_contexts($categorycontext);
|
||||
$editcontexts = new \core_question\local\bank\question_edit_contexts($categorycontext);
|
||||
// The user must be able to view all questions in the category that they are requesting.
|
||||
$editcontexts->require_cap('moodle/question:viewall');
|
||||
|
||||
|
|
|
@ -47,7 +47,9 @@ abstract class action_column_base extends column_base {
|
|||
}
|
||||
|
||||
public function get_extra_joins(): array {
|
||||
return ['qc' => 'JOIN {question_categories} qc ON qc.id = q.category'];
|
||||
return ['qv' => 'JOIN {question_versions} qv ON qv.questionid = q.id',
|
||||
'qbe' => 'JOIN {question_bank_entries} qbe on qbe.id = qv.questionbankentryid',
|
||||
'qc' => 'JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid'];
|
||||
}
|
||||
|
||||
public function get_required_fields(): array {
|
||||
|
|
92
question/classes/local/bank/context_to_string_translator.php
Normal file
92
question/classes/local/bank/context_to_string_translator.php
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?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/>.
|
||||
|
||||
namespace core_question\local\bank;
|
||||
|
||||
/**
|
||||
* Converts contextlevels to strings and back to help with reading/writing contexts to/from import/export files.
|
||||
*
|
||||
* @package core_question
|
||||
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
|
||||
* @author 2021 Safat Shahin <safatshahin@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class context_to_string_translator {
|
||||
|
||||
/**
|
||||
* @var array used to translate between contextids and strings for this context.
|
||||
*/
|
||||
protected $contexttostringarray = [];
|
||||
|
||||
/**
|
||||
* context_to_string_translator constructor.
|
||||
*
|
||||
* @param \context[] $contexts
|
||||
*/
|
||||
public function __construct($contexts) {
|
||||
$this->generate_context_to_string_array($contexts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Context to string.
|
||||
*
|
||||
* @param int $contextid
|
||||
* @return mixed
|
||||
*/
|
||||
public function context_to_string($contextid) {
|
||||
return $this->contexttostringarray[$contextid];
|
||||
}
|
||||
|
||||
/**
|
||||
* String to context.
|
||||
*
|
||||
* @param string $contextname
|
||||
* @return false|int|string
|
||||
*/
|
||||
public function string_to_context($contextname) {
|
||||
return array_search($contextname, $this->contexttostringarray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate context to array.
|
||||
*
|
||||
* @param \context[] $contexts
|
||||
*/
|
||||
protected function generate_context_to_string_array($contexts) {
|
||||
if (!$this->contexttostringarray) {
|
||||
$catno = 1;
|
||||
foreach ($contexts as $context) {
|
||||
switch ($context->contextlevel) {
|
||||
case CONTEXT_MODULE :
|
||||
$contextstring = 'module';
|
||||
break;
|
||||
case CONTEXT_COURSE :
|
||||
$contextstring = 'course';
|
||||
break;
|
||||
case CONTEXT_COURSECAT :
|
||||
$contextstring = "cat$catno";
|
||||
$catno++;
|
||||
break;
|
||||
case CONTEXT_SYSTEM :
|
||||
$contextstring = 'system';
|
||||
break;
|
||||
}
|
||||
$this->contexttostringarray[$context->id] = $contextstring;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -97,4 +97,12 @@ class edit_menu_column extends column_base {
|
|||
return ['q.qtype'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get menuable actions.
|
||||
*
|
||||
* @return menuable_action Menuable actions.
|
||||
*/
|
||||
public function get_actions(): array {
|
||||
return $this->actions;
|
||||
}
|
||||
}
|
||||
|
|
222
question/classes/local/bank/question_edit_contexts.php
Normal file
222
question/classes/local/bank/question_edit_contexts.php
Normal file
|
@ -0,0 +1,222 @@
|
|||
<?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/>.
|
||||
|
||||
namespace core_question\local\bank;
|
||||
|
||||
/**
|
||||
* Tracks all the contexts related to the one we are currently editing questions and provides helper methods to check permissions.
|
||||
*
|
||||
* @package core_question
|
||||
* @copyright 2007 Jamie Pratt me@jamiep.org
|
||||
* @author 2021 Safat Shahin <safatshahin@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class question_edit_contexts {
|
||||
|
||||
/**
|
||||
* @var \string[][] array of the capabilities.
|
||||
*/
|
||||
public static $caps = [
|
||||
'editq' => [
|
||||
'moodle/question:add',
|
||||
'moodle/question:editmine',
|
||||
'moodle/question:editall',
|
||||
'moodle/question:viewmine',
|
||||
'moodle/question:viewall',
|
||||
'moodle/question:usemine',
|
||||
'moodle/question:useall',
|
||||
'moodle/question:movemine',
|
||||
'moodle/question:moveall'],
|
||||
'questions' => [
|
||||
'moodle/question:add',
|
||||
'moodle/question:editmine',
|
||||
'moodle/question:editall',
|
||||
'moodle/question:viewmine',
|
||||
'moodle/question:viewall',
|
||||
'moodle/question:movemine',
|
||||
'moodle/question:moveall'],
|
||||
'categories' => [
|
||||
'moodle/question:managecategory'],
|
||||
'import' => [
|
||||
'moodle/question:add'],
|
||||
'export' => [
|
||||
'moodle/question:viewall',
|
||||
'moodle/question:viewmine']];
|
||||
|
||||
/**
|
||||
* @var array of contexts.
|
||||
*/
|
||||
protected $allcontexts;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param \context $thiscontext the current context.
|
||||
*/
|
||||
public function __construct(\context $thiscontext) {
|
||||
$this->allcontexts = array_values($thiscontext->get_parent_contexts(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the contexts.
|
||||
*
|
||||
* @return \context[] all parent contexts
|
||||
*/
|
||||
public function all() {
|
||||
return $this->allcontexts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lowest context.
|
||||
*
|
||||
* @return \context lowest context which must be either the module or course context
|
||||
*/
|
||||
public function lowest() {
|
||||
return $this->allcontexts[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contexts having cap.
|
||||
*
|
||||
* @param string $cap capability
|
||||
* @return \context[] parent contexts having capability, zero based index
|
||||
*/
|
||||
public function having_cap($cap) {
|
||||
$contextswithcap = [];
|
||||
foreach ($this->allcontexts as $context) {
|
||||
if (has_capability($cap, $context)) {
|
||||
$contextswithcap[] = $context;
|
||||
}
|
||||
}
|
||||
return $contextswithcap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contexts having at least one cap.
|
||||
*
|
||||
* @param array $caps capabilities
|
||||
* @return \context[] parent contexts having at least one of $caps, zero based index
|
||||
*/
|
||||
public function having_one_cap($caps) {
|
||||
$contextswithacap = [];
|
||||
foreach ($this->allcontexts as $context) {
|
||||
foreach ($caps as $cap) {
|
||||
if (has_capability($cap, $context)) {
|
||||
$contextswithacap[] = $context;
|
||||
break; // Done with caps loop.
|
||||
}
|
||||
}
|
||||
}
|
||||
return $contextswithacap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Context having at least one cap.
|
||||
*
|
||||
* @param string $tabname edit tab name
|
||||
* @return \context[] parent contexts having at least one of $caps, zero based index
|
||||
*/
|
||||
public function having_one_edit_tab_cap($tabname) {
|
||||
return $this->having_one_cap(self::$caps[$tabname]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contexts for adding question and also using it.
|
||||
*
|
||||
* @return \context[] those contexts where a user can add a question and then use it.
|
||||
*/
|
||||
public function having_add_and_use() {
|
||||
$contextswithcap = [];
|
||||
foreach ($this->allcontexts as $context) {
|
||||
if (!has_capability('moodle/question:add', $context)) {
|
||||
continue;
|
||||
}
|
||||
if (!has_any_capability(['moodle/question:useall', 'moodle/question:usemine'], $context)) {
|
||||
continue;
|
||||
}
|
||||
$contextswithcap[] = $context;
|
||||
}
|
||||
return $contextswithcap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has at least one parent context got the cap $cap?
|
||||
*
|
||||
* @param string $cap capability
|
||||
* @return boolean
|
||||
*/
|
||||
public function have_cap($cap) {
|
||||
return (count($this->having_cap($cap)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Has at least one parent context got one of the caps $caps?
|
||||
*
|
||||
* @param array $caps capability
|
||||
* @return boolean
|
||||
*/
|
||||
public function have_one_cap($caps) {
|
||||
foreach ($caps as $cap) {
|
||||
if ($this->have_cap($cap)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has at least one parent context got one of the caps for actions on $tabname
|
||||
*
|
||||
* @param string $tabname edit tab name
|
||||
* @return boolean
|
||||
*/
|
||||
public function have_one_edit_tab_cap($tabname) {
|
||||
return $this->have_one_cap(self::$caps[$tabname]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw error if at least one parent context hasn't got the cap $cap
|
||||
*
|
||||
* @param string $cap capability
|
||||
*/
|
||||
public function require_cap($cap) {
|
||||
if (!$this->have_cap($cap)) {
|
||||
throw new \moodle_exception('nopermissions', '', '', $cap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw error if at least one parent context hasn't got one of the caps $caps
|
||||
*
|
||||
* @param array $caps capabilities
|
||||
*/
|
||||
public function require_one_cap($caps) {
|
||||
if (!$this->have_one_cap($caps)) {
|
||||
$capsstring = join(', ', $caps);
|
||||
throw new \moodle_exception('nopermissions', '', '', $capsstring);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw error if at least one parent context hasn't got one of the caps $caps
|
||||
*
|
||||
* @param string $tabname edit tab name
|
||||
*/
|
||||
public function require_one_edit_tab_cap($tabname) {
|
||||
if (!$this->have_one_edit_tab_cap($tabname)) {
|
||||
throw new \moodle_exception('nopermissions', '', '', 'access question edit tab '.$tabname);
|
||||
}
|
||||
}
|
||||
}
|
43
question/classes/local/bank/question_version_status.php
Normal file
43
question/classes/local/bank/question_version_status.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?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/>.
|
||||
|
||||
namespace core_question\local\bank;
|
||||
|
||||
/**
|
||||
* Class question_version_status contains the statuses for a question.
|
||||
*
|
||||
* @package core_question
|
||||
* @copyright 2021 Catalyst IT Australia Pty Ltd
|
||||
* @author Safat Shahin <safatshahin@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class question_version_status {
|
||||
|
||||
/**
|
||||
* Const if the question is ready to use.
|
||||
*/
|
||||
const QUESTION_STATUS_READY = 'ready';
|
||||
|
||||
/**
|
||||
* Const if the question is hidden.
|
||||
*/
|
||||
const QUESTION_STATUS_HIDDEN = 'hidden';
|
||||
|
||||
/**
|
||||
* const if the question is in draft.
|
||||
*/
|
||||
const QUESTION_STATUS_DRAFT = 'draft';
|
||||
}
|
|
@ -290,7 +290,25 @@ class random_question_loader {
|
|||
$fieldsstring = implode(',', $fields);
|
||||
}
|
||||
|
||||
return $DB->get_records_list('question', 'id', $questionids, 'id', $fieldsstring, $offset, $limit);
|
||||
// Create the query to get the questions (validate that at least we have a question id. If not, do not execute the sql).
|
||||
$hasquestions = false;
|
||||
if (!empty($questionids)) {
|
||||
$hasquestions = true;
|
||||
}
|
||||
if ($hasquestions) {
|
||||
list($condition, $param) = $DB->get_in_or_equal($questionids, SQL_PARAMS_NAMED, 'questionid');
|
||||
$condition = 'WHERE q.id ' . $condition;
|
||||
$sql = "SELECT {$fieldsstring}
|
||||
FROM (SELECT q.*, qbe.questioncategoryid as category
|
||||
FROM {question} q
|
||||
JOIN {question_versions} qv ON qv.questionid = q.id
|
||||
JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid
|
||||
{$condition}) q";
|
||||
|
||||
return $DB->get_records_sql($sql, $param, $offset, $limit);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -70,7 +70,7 @@ class view {
|
|||
protected $editquestionurl;
|
||||
|
||||
/**
|
||||
* @var \question_edit_contexts
|
||||
* @var \core_question\local\bank\question_edit_contexts
|
||||
*/
|
||||
protected $contexts;
|
||||
|
||||
|
@ -157,7 +157,7 @@ class view {
|
|||
/**
|
||||
* Constructor for view.
|
||||
*
|
||||
* @param \question_edit_contexts $contexts
|
||||
* @param \core_question\local\bank\question_edit_contexts $contexts
|
||||
* @param \moodle_url $pageurl
|
||||
* @param object $course course settings
|
||||
* @param object $cm (optional) activity settings.
|
||||
|
@ -244,8 +244,9 @@ class view {
|
|||
'preview_action_column',
|
||||
'delete_action_column',
|
||||
'export_xml_action_column',
|
||||
'question_status_column',
|
||||
'creator_name_column',
|
||||
'modifier_name_column'
|
||||
'comment_count_column'
|
||||
];
|
||||
if (question_get_display_preference('qbshowtext', 0, PARAM_BOOL, new \moodle_url(''))) {
|
||||
$corequestionbankcolumns[] = 'question_text_row';
|
||||
|
@ -560,7 +561,7 @@ class view {
|
|||
protected function build_query(): void {
|
||||
// Get the required tables and fields.
|
||||
$joins = [];
|
||||
$fields = ['q.hidden', 'q.category'];
|
||||
$fields = ['qv.status', 'qc.id', 'qv.version', 'qv.id as versionid', 'qbe.id as questionbankentryid'];
|
||||
if (!empty($this->requiredcolumns)) {
|
||||
foreach ($this->requiredcolumns as $column) {
|
||||
$extrajoins = $column->get_extra_joins();
|
||||
|
@ -583,7 +584,12 @@ class view {
|
|||
}
|
||||
|
||||
// Build the where clause.
|
||||
$tests = ['q.parent = 0'];
|
||||
$latestversion = 'qv.version = (SELECT MAX(v.version)
|
||||
FROM {question_versions} v
|
||||
JOIN {question_bank_entries} be
|
||||
ON be.id = v.questionbankentryid
|
||||
WHERE be.id = qbe.id)';
|
||||
$tests = ['q.parent = 0', $latestversion];
|
||||
$this->sqlparams = [];
|
||||
foreach ($this->searchconditions as $searchcondition) {
|
||||
if ($searchcondition->where()) {
|
||||
|
@ -1153,7 +1159,7 @@ class view {
|
|||
*/
|
||||
protected function get_row_classes($question, $rowcount): array {
|
||||
$classes = [];
|
||||
if ($question->hidden) {
|
||||
if ($question->status === question_version_status::QUESTION_STATUS_HIDDEN) {
|
||||
$classes[] = 'dimmed_text';
|
||||
}
|
||||
if ($question->id == $this->lastchangedid) {
|
||||
|
@ -1219,4 +1225,20 @@ class view {
|
|||
$this->searchconditions[] = $searchcondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets visible columns.
|
||||
* @return array $this->visiblecolumns Visible columns.
|
||||
*/
|
||||
public function get_visiblecolumns(): array {
|
||||
return $this->visiblecolumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get required columns.
|
||||
*
|
||||
* @return array Required columns.
|
||||
*/
|
||||
public function get_requiredcolumns(): array {
|
||||
return $this->requiredcolumns;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,6 +126,10 @@ class provider implements
|
|||
// The 'question_statistics' table contains aggregated statistics about responses.
|
||||
// It does not contain any identifiable user data.
|
||||
|
||||
$items->add_database_table('question_bank_entries', [
|
||||
'ownerid' => 'privacy:metadata:database:question_bank_entries:ownerid',
|
||||
], 'privacy:metadata:database:question_bank_entries');
|
||||
|
||||
// The question subsystem makes use of the qtype, qformat, and qbehaviour plugin types.
|
||||
$items->add_plugintype_link('qtype', [], 'privacy:metadata:link:qtype');
|
||||
$items->add_plugintype_link('qformat', [], 'privacy:metadata:link:qformat');
|
||||
|
@ -336,12 +340,13 @@ class provider implements
|
|||
|
||||
// A user may have created or updated a question.
|
||||
// Questions are linked against a question category, which has a contextid field.
|
||||
$sql = "SELECT cat.contextid
|
||||
$sql = "SELECT qc.contextid
|
||||
FROM {question} q
|
||||
INNER JOIN {question_categories} cat ON cat.id = q.category
|
||||
WHERE
|
||||
q.createdby = :useridcreated OR
|
||||
q.modifiedby = :useridmodified";
|
||||
JOIN {question_versions} qv ON qv.questionid = q.id
|
||||
JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid
|
||||
JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid
|
||||
WHERE q.createdby = :useridcreated
|
||||
OR q.modifiedby = :useridmodified";
|
||||
$params = [
|
||||
'useridcreated' => $userid,
|
||||
'useridmodified' => $userid,
|
||||
|
@ -363,9 +368,10 @@ class provider implements
|
|||
// Questions are linked against a question category, which has a contextid field.
|
||||
$sql = "SELECT q.createdby, q.modifiedby
|
||||
FROM {question} q
|
||||
JOIN {question_categories} cat
|
||||
ON cat.id = q.category
|
||||
WHERE cat.contextid = :contextid";
|
||||
JOIN {question_versions} qv ON qv.questionid = q.id
|
||||
JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid
|
||||
JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid
|
||||
WHERE qc.contextid = :contextid";
|
||||
|
||||
$params = [
|
||||
'contextid' => $context->id
|
||||
|
@ -487,7 +493,8 @@ class provider implements
|
|||
/**
|
||||
* Delete all data for all users in the specified context.
|
||||
*
|
||||
* @param context $context The specific context to delete data for.
|
||||
* @param \context $context The specific context to delete data for.
|
||||
* @throws \dml_exception
|
||||
*/
|
||||
public static function delete_data_for_all_users_in_context(\context $context) {
|
||||
global $DB;
|
||||
|
@ -496,17 +503,19 @@ class provider implements
|
|||
// user. They are still exported in the list of a users data, but they are not removed.
|
||||
// The userid is instead anonymised.
|
||||
|
||||
$DB->set_field_select('question', 'createdby', 0,
|
||||
'category IN (SELECT id FROM {question_categories} WHERE contextid = :contextid)',
|
||||
[
|
||||
'contextid' => $context->id,
|
||||
]);
|
||||
$sql = 'SELECT q.*
|
||||
FROM {question} q
|
||||
JOIN {question_versions} qv ON qv.questionid = q.id
|
||||
JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid
|
||||
JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid
|
||||
WHERE qc.contextid = ?';
|
||||
|
||||
$DB->set_field_select('question', 'modifiedby', 0,
|
||||
'category IN (SELECT id FROM {question_categories} WHERE contextid = :contextid)',
|
||||
[
|
||||
'contextid' => $context->id,
|
||||
]);
|
||||
$questions = $DB->get_records_sql($sql, [$context->id]);
|
||||
foreach ($questions as $question) {
|
||||
$question->createdby = 0;
|
||||
$question->modifiedby = 0;
|
||||
$DB->update_record('question', $question);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -523,15 +532,36 @@ class provider implements
|
|||
|
||||
list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
|
||||
$contextparams['createdby'] = $contextlist->get_user()->id;
|
||||
$DB->set_field_select('question', 'createdby', 0, "
|
||||
category IN (SELECT id FROM {question_categories} WHERE contextid {$contextsql})
|
||||
AND createdby = :createdby", $contextparams);
|
||||
$questiondata = $DB->get_records_sql(
|
||||
"SELECT q.*
|
||||
FROM {question} q
|
||||
JOIN {question_versions} qv ON qv.questionid = q.id
|
||||
JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid
|
||||
JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid
|
||||
WHERE qc.contextid {$contextsql}
|
||||
AND q.createdby = :createdby", $contextparams);
|
||||
|
||||
foreach ($questiondata as $question) {
|
||||
$question->createdby = 0;
|
||||
$DB->update_record('question', $question);
|
||||
}
|
||||
|
||||
list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
|
||||
$contextparams['modifiedby'] = $contextlist->get_user()->id;
|
||||
$DB->set_field_select('question', 'modifiedby', 0, "
|
||||
category IN (SELECT id FROM {question_categories} WHERE contextid {$contextsql})
|
||||
AND modifiedby = :modifiedby", $contextparams);
|
||||
$questiondata = $DB->get_records_sql(
|
||||
"SELECT q.*
|
||||
FROM {question} q
|
||||
JOIN {question_versions} qv ON qv.questionid = q.id
|
||||
JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid
|
||||
JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid
|
||||
WHERE qc.contextid {$contextsql}
|
||||
AND q.modifiedby = :modifiedby", $contextparams);
|
||||
|
||||
foreach ($questiondata as $question) {
|
||||
$question->modifiedby = 0;
|
||||
$DB->update_record('question', $question);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -554,12 +584,32 @@ class provider implements
|
|||
|
||||
$params = ['contextid' => $context->id];
|
||||
|
||||
$DB->set_field_select('question', 'createdby', 0, "
|
||||
category IN (SELECT id FROM {question_categories} WHERE contextid = :contextid)
|
||||
AND createdby {$createdbysql}", $params + $createdbyparams);
|
||||
$questiondata = $DB->get_records_sql(
|
||||
"SELECT q.*
|
||||
FROM {question} q
|
||||
JOIN {question_versions} qv ON qv.questionid = q.id
|
||||
JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid
|
||||
JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid
|
||||
WHERE qc.contextid = :contextid
|
||||
AND q.createdby {$createdbysql}", $params + $createdbyparams);
|
||||
|
||||
$DB->set_field_select('question', 'modifiedby', 0, "
|
||||
category IN (SELECT id FROM {question_categories} WHERE contextid = :contextid)
|
||||
AND modifiedby {$modifiedbysql}", $params + $modifiedbyparams);
|
||||
foreach ($questiondata as $question) {
|
||||
$question->createdby = 0;
|
||||
$DB->update_record('question', $question);
|
||||
}
|
||||
|
||||
$questiondata = $DB->get_records_sql(
|
||||
"SELECT q.*
|
||||
FROM {question} q
|
||||
JOIN {question_versions} qv ON qv.questionid = q.id
|
||||
JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid
|
||||
JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid
|
||||
WHERE qc.contextid = :contextid
|
||||
AND q.modifiedby {$modifiedbysql}", $params + $modifiedbyparams);
|
||||
|
||||
foreach ($questiondata as $question) {
|
||||
$question->modifiedby = 0;
|
||||
$DB->update_record('question', $question);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ class all_calculated_for_qubaid_condition {
|
|||
/**
|
||||
* @var object[]
|
||||
*/
|
||||
public $subquestions;
|
||||
public $subquestions = [];
|
||||
|
||||
/**
|
||||
* Holds slot (position) stats and stats for variants of questions in slots.
|
||||
|
|
|
@ -346,7 +346,15 @@ class calculator {
|
|||
* @param calculated $stats question stats to update.
|
||||
*/
|
||||
protected function initial_question_walker($stats) {
|
||||
$stats->markaverage = $stats->totalmarks / $stats->s;
|
||||
if ($stats->s != 0) {
|
||||
$stats->markaverage = $stats->totalmarks / $stats->s;
|
||||
$stats->othermarkaverage = $stats->totalothermarks / $stats->s;
|
||||
$stats->summarksaverage = $stats->totalsummarks / $stats->s;
|
||||
} else {
|
||||
$stats->markaverage = 0;
|
||||
$stats->othermarkaverage = 0;
|
||||
$stats->summarksaverage = 0;
|
||||
}
|
||||
|
||||
if ($stats->maxmark != 0) {
|
||||
$stats->facility = $stats->markaverage / $stats->maxmark;
|
||||
|
@ -354,10 +362,6 @@ class calculator {
|
|||
$stats->facility = null;
|
||||
}
|
||||
|
||||
$stats->othermarkaverage = $stats->totalothermarks / $stats->s;
|
||||
|
||||
$stats->summarksaverage = $stats->totalsummarks / $stats->s;
|
||||
|
||||
sort($stats->markarray, SORT_NUMERIC);
|
||||
sort($stats->othermarksarray, SORT_NUMERIC);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue