Skip to content

Commit

Permalink
StudentQuiz: make the SQ working with Moodle 4.3
Browse files Browse the repository at this point in the history
  • Loading branch information
hieuvu committed Dec 14, 2023
1 parent b55da1c commit fc9a82b
Show file tree
Hide file tree
Showing 45 changed files with 1,760 additions and 175 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/moodle-plugin-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ jobs:
include:
- {php: '7.3', moodle-branch: MOODLE_400_STABLE, database: pgsql}
- {php: '7.4', moodle-branch: MOODLE_401_STABLE, database: mariadb}
- {php: '8.1', moodle-branch: MOODLE_402_STABLE, database: pgsql}
- {php: '8.0', moodle-branch: MOODLE_402_STABLE, database: pgsql}
- {php: '8.2', moodle-branch: MOODLE_403_STABLE, database: mariadb}
- {php: '8.0', moodle-branch: master, database: pgsql}
- {php: '8.1', moodle-branch: main, database: pgsql}

steps:
- name: Check out repository code
Expand Down Expand Up @@ -73,10 +73,12 @@ jobs:

- name: PHP Lint
if: ${{ always() }}
continue-on-error: true # This step will show errors but will not fail
run: moodle-plugin-ci phplint

- name: PHP Copy/Paste Detector
if: ${{ always() }}
continue-on-error: true # This step will show errors but will not fail
run: moodle-plugin-ci phpcpd

- name: PHP Mess Detector
Expand Down
5 changes: 2 additions & 3 deletions amd/build/question_nav_tabs.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion amd/build/question_nav_tabs.min.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions amd/src/question_nav_tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,20 @@
* @copyright 2021 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import * as UserRepository from 'core_user/repository';

/**
* Update the current active tab to user preferences.
*
* @private
* @param {Object} e Event
* @return {Promise} The promise object.
*/
const updateActiveTab = (e) => {
return M.util.set_user_preference('mod_studentquiz_question_active_tab', e.target.dataset.tabId);
if (typeof UserRepository.setUserPreference !== 'undefined') {
UserRepository.setUserPreference('mod_studentquiz_question_active_tab', e.target.dataset.tabId);
} else {
M.util.set_user_preference('mod_studentquiz_question_active_tab', e.target.dataset.tabId);
}
};

/**
Expand Down
22 changes: 20 additions & 2 deletions classes/condition/studentquiz_condition.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
* @copyright 2017 HSR (http://www.hsr.ch)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class studentquiz_condition extends \core_question\bank\search\condition {
class studentquiz_condition extends \core_question\local\bank\condition {

/**
* Due to fix_sql_params not accepting repeated use of named params,
Expand Down Expand Up @@ -67,6 +67,24 @@ public function __construct($cm, $filterform, $report, $studentquiz) {
$this->init();
}

/**
* Return title of the condition
*
* @return string title of the condition
*/
public function get_title() {
return get_string('showhidden', 'core_question');
}

/**
* Return filter class associated with this condition
*
* @return string filter class
*/
public function get_filter_class() {
return 'qbank_deletequestion/datafilter/filtertypes/hidden';
}

/** @var stdClass */
protected $cm;

Expand All @@ -83,7 +101,7 @@ public function __construct($cm, $filterform, $report, $studentquiz) {
protected $tests;

/** @var array */
protected $params;
protected array $params = [];

/** @var bool */
protected $isfilteractive = false;
Expand Down
251 changes: 251 additions & 0 deletions classes/condition/studentquiz_condition_pre_43.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
<?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/>.

/**
* Modify stuff conditionally
*
* @package mod_studentquiz
* @copyright 2017 HSR (http://www.hsr.ch)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

namespace mod_studentquiz\condition;
defined('MOODLE_INTERNAL') || die();

require_once($CFG->dirroot . '/mod/studentquiz/classes/local/db.php');
use mod_studentquiz\local\db;

/**
* Conditionally modify question bank queries.
*
* @copyright 2017 HSR (http://www.hsr.ch)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class studentquiz_condition_pre_43 extends \core_question\bank\search\condition {

/**
* Due to fix_sql_params not accepting repeated use of named params,
* we need to get unique names for params that will be used more than
* once...
*
* init() from parent class duplicated here as we can't call it directly
* (private) :-P
*
* where() overridden with call to init() followed by call to parent
* where()...
*
* params() always returns $this->params, which doesn't change between
* calls to get_in_or_equal, so don't need to fix anything there.
* Which is fortunate, as there'd be no way to keep where() and params()
* in sync.
*
* @param stdClass $cm
* @param stdClass $filterform
* @param \mod_studentquiz_report $report
* @param stdClass $studentquiz
*/
public function __construct($cm, $filterform, $report, $studentquiz) {
$this->cm = $cm;
$this->filterform = $filterform;
$this->tests = array();
$this->params = array();
$this->report = $report;
$this->studentquiz = $studentquiz;
$this->init();
}

/** @var stdClass */
protected $cm;

/** @var stdClass $filterform Search condition depends on filterform */
protected $filterform;

/** @var stdClass */
protected $studentquiz;

/** @var \mod_studentquiz_report */
protected $report;

/** @var array */
protected $tests;

/** @var array */
protected $params;

/** @var bool */
protected $isfilteractive = false;

/**
* Whether the filter is active.
* @return bool
*/
public function is_filter_active() {
return $this->isfilteractive;
}

/**
* Initialize.
*/
protected function init() {
if ($adddata = $this->filterform->get_data()) {

$this->tests = array();
$this->params = array();

foreach ($this->filterform->get_fields() as $field) {

// Validate input.
$data = $field->check_data($adddata);

// If input is valid, at least one filter was activated.
if ($data === false) {
continue;
} else {
$this->isfilteractive = true;
}

$sqldata = $field->get_sql_filter($data);

// Disable filtering by firstname if anonymized.
if ($field->_name == 'firstname' && !(mod_studentquiz_check_created_permission($this->cm->id) ||
!$this->report->is_anonymized())) {
continue;
}

// Disable filtering by firstname if anonymized.
if ($field->_name == 'lastname' && !(mod_studentquiz_check_created_permission($this->cm->id) ||
!$this->report->is_anonymized())) {
continue;
}

// Respect leading and ending ',' for the tagarray as provided by tag_column.php.
if ($field->_name == 'tagarray') {
foreach ($sqldata[1] as $key => $value) {
if (!empty($value)) {
$sqldata[1][$key] = "%,$value,%";
} else {
$sqldata[0] = "$field->_name IS NULL";
}
}
}

// TODO: cleanup that buggy filter function to remove this!
// The user_filter_checkbox class has a buggy get_sql_filter function.
if ($field->_name == 'createdby') {
$sqldata = array($field->_name . ' = ' . intval($data['value']), array());
}

if (is_array($sqldata)) {
$sqldata[0] = str_replace($field->_name, $this->get_sql_field($field->_name)
, $sqldata[0]);
$sqldata[0] = $this->get_special_sql($sqldata[0], $field->_name);
$this->tests[] = '((' . $sqldata[0] . '))';
$this->params = array_merge($this->params, $sqldata[1]);
}
}
}
}

/**
* Replaces special fields with additional sql instructions in the query
*
* @param string $sqldata the sql query
* @param string $name affected field name
* @return string modified sql query
*/
private function get_special_sql($sqldata, $name) {
if (substr($sqldata, 0, 12) === 'mydifficulty') {
return str_replace('mydifficulty', '(CASE WHEN sp.attempts > 0 THEN
ROUND(1 - (CAST(sp.correctattempts AS DECIMAL) / CAST(sp.attempts AS DECIMAL)), 2)
ELSE 0
END)', $sqldata);
}
if ($name == "onlynew") {
return str_replace('myattempts', 'sp.attempts', $sqldata);
}
return $sqldata;
}

/**
* Replaces fields with additional sql instructions in place of the field
*
* @param string $name affected field name
* @return string modified sql query
*/
private function get_sql_field($name) {
if (substr($name, 0, 12) === 'mydifficulty') {
return str_replace('mydifficulty', '(CASE WHEN sp.attempts > 0 THEN
ROUND(1 - (CAST(sp.correctattempts AS DECIMAL) / CAST(sp.attempts AS DECIMAL)), 2)
ELSE 0
END)', $name);
}
if (substr($name, 0, 10) === 'myattempts') {
return 'sp.attempts';
}
return $this->get_sql_table_prefix($name) . $name;
}


/**
* Get the sql table prefix
*
* @param string $name
* @return string return sql prefix
*/
private function get_sql_table_prefix($name) {
switch($name){
case 'difficultylevel':
return 'dl.';
case 'rate':
return 'vo.';
case 'publiccomment':
return 'copub.';
case 'state':
return 'sqq.';
case 'firstname':
case 'lastname':
return 'uc.';
case 'lastanswercorrect':
return 'sp.';
case 'mydifficulty':
return 'mydiffs.';
case 'myattempts':
return 'myatts.';
case 'myrate':
return 'myrate.';
case 'tagarray':
return 'tags.';
default;
return 'q.';
}
}

/**
* Provide SQL fragment to be ANDed into the WHERE clause to filter which questions are shown.
* @return string SQL fragment. Must use named parameters.
*/
public function where() {
return implode(' AND ', $this->tests);
}

/**
* Return parameters to be bound to the above WHERE clause fragment.
* @return array parameter name => value.
*/
public function params() {
return $this->params;
}
}
8 changes: 6 additions & 2 deletions classes/local/studentquiz_question.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,14 @@ class studentquiz_question {
private $cm;

/** @var \context_module $context - Context. */
private $context;
protected $context;

/** @var stdClass - StudentQuiz data. */
private $studentquiz;
protected $studentquiz;

/** @var int - StudentQuiz question id. */
protected $id;


/**
* studentquiz_question constructor.
Expand Down
9 changes: 9 additions & 0 deletions classes/question/bank/attempts_column.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ class attempts_column extends studentquiz_column_base {
/** @var \stdClass */
protected $studentquiz;

/** @var int category id*/
protected $categoryid;

/** @var int current user id*/
protected $currentuserid;

/** @var int student quiz id*/
protected $studentquizid;

/**
* Initialise Parameters for join
*/
Expand Down
Loading

0 comments on commit fc9a82b

Please sign in to comment.