diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 191de69..1360477 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -1,138 +1,113 @@ -name: Moodle plugin CI +name: Moodle Plugin CI + on: [push, pull_request] jobs: test: - runs-on: 'ubuntu-latest' - strategy: - fail-fast: false - matrix: - include: - - php: '8.1' - moodle-branch: 'MOODLE_402_STABLE' - database: 'mariadb' - - php: '8.1' - moodle-branch: 'MOODLE_402_STABLE' - database: 'mariadb' - - php: '8.0' - moodle-branch: 'MOODLE_402_STABLE' - database: 'mariadb' - - php: '8.0' - moodle-branch: 'MOODLE_402_STABLE' - database: 'mariadb' - - php: '8.1' - moodle-branch: 'MOODLE_401_STABLE' - database: 'mariadb' - - php: '8.1' - moodle-branch: 'MOODLE_401_STABLE' - database: 'mariadb' - - php: '8.0' - moodle-branch: 'MOODLE_401_STABLE' - database: 'mariadb' - - php: '8.0' - moodle-branch: 'MOODLE_401_STABLE' - database: 'mariadb' - - php: '7.4' - moodle-branch: 'MOODLE_401_STABLE' - database: 'mariadb' - - php: '7.4' - moodle-branch: 'MOODLE_401_STABLE' - database: 'mariadb' - - php: '7.4' - moodle-branch: 'MOODLE_400_STABLE' - database: 'mariadb' - - php: '7.4' - moodle-branch: 'MOODLE_400_STABLE' - database: 'mariadb' + runs-on: ubuntu-22.04 services: postgres: - image: postgres + image: postgres:13 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 + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 mariadb: - image: mariadb:10.5 + image: mariadb:10 env: MYSQL_USER: 'root' MYSQL_ALLOW_EMPTY_PASSWORD: "true" + MYSQL_CHARACTER_SET_SERVER: "utf8mb4" + MYSQL_COLLATION_SERVER: "utf8mb4_unicode_ci" ports: - 3306:3306 options: --health-cmd="mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 3 + strategy: + fail-fast: false + matrix: + php: ['8.0'] + moodle-branch: ['MOODLE_403_STABLE', 'MOODLE_404_STABLE'] + database: [pgsql, mariadb] + steps: - - name: Checkout - uses: actions/checkout@v3 + - name: Check out repository code + uses: actions/checkout@v4 with: path: plugin - - name: Setup PHP + - name: Setup PHP ${{ matrix.php }} uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: zip, gd, mbstring, pgsql, mysqli + extensions: ${{ matrix.extensions }} + ini-values: max_input_vars=5000 + coverage: none - - name: Deploy moodle-plugin-ci + - name: Initialise moodle-plugin-ci run: | - composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3 - # Add dirs to $PATH + composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^4 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 - # Need explicit IP to stop mysql client fail on attempt to use unix socket. + echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV + + - name: Install moodle-plugin-ci run: moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 env: DB: ${{ matrix.database }} MOODLE_BRANCH: ${{ matrix.moodle-branch }} - IGNORE_NAMES: 'mobile_*.mustache' - IGNORE_PATHS: 'templates/local/mobile' - - name: phplint - if: ${{ always() }} + - name: PHP Lint + if: ${{ !cancelled() }} run: moodle-plugin-ci phplint - - name: phpcpd - if: ${{ always() }} - run: moodle-plugin-ci phpcpd || true + - name: PHP Copy/Paste Detector + continue-on-error: true # This step will show errors but will not fail + if: ${{ !cancelled() }} + run: moodle-plugin-ci phpcpd - - name: phpmd - if: ${{ always() }} + - name: PHP Mess Detector + continue-on-error: true # This step will show errors but will not fail + if: ${{ !cancelled() }} run: moodle-plugin-ci phpmd - - name: codechecker - if: ${{ always() }} - run: moodle-plugin-ci codechecker + - name: Moodle Code Checker + if: ${{ !cancelled() }} + run: moodle-plugin-ci phpcs --max-warnings 0 - - name: validate - if: ${{ always() }} + - name: Moodle PHPDoc Checker + if: ${{ !cancelled() }} + run: moodle-plugin-ci phpdoc --max-warnings 0 + + - name: Validating + if: ${{ !cancelled() }} run: moodle-plugin-ci validate - - name: savepoints - if: ${{ always() }} + - name: Check upgrade savepoints + if: ${{ !cancelled() }} run: moodle-plugin-ci savepoints - - name: mustache - if: ${{ always() }} + - name: Mustache Lint + if: ${{ !cancelled() }} run: moodle-plugin-ci mustache - - name: grunt - if: ${{ always() }} - run: moodle-plugin-ci grunt + - name: Grunt + if: ${{ !cancelled() }} + run: moodle-plugin-ci grunt --max-lint-warnings 0 - - name: phpunit - if: ${{ always() }} - run: moodle-plugin-ci phpunit + - name: PHPUnit tests + if: ${{ !cancelled() }} + run: moodle-plugin-ci phpunit --fail-on-warning - - name: behat - if: ${{ always() }} + - name: Behat features + if: ${{ !cancelled() }} run: moodle-plugin-ci behat --profile chrome + + - name: Mark cancelled jobs as failed. + if: ${{ cancelled() }} + run: exit 1 diff --git a/.travis.yml b/.travis.yml deleted file mode 100755 index 9879a04..0000000 --- a/.travis.yml +++ /dev/null @@ -1,51 +0,0 @@ -language: php - -addons: - postgresql: "9.5" - -services: - - mysql - - postgresql - - docker - -cache: - directories: - - $HOME/.composer/cache - - $HOME/.npm - -php: - - 7.2 - - 7.3 - - 7.4 - -env: - global: - - MOODLE_BRANCH=MOODLE_39_STABLE - matrix: - - DB=pgsql - - DB=mysqli - -before_install: - - phpenv config-rm xdebug.ini - - cd ../.. - - composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3 - - export PATH="$(cd ci/bin; pwd):$(cd ci/vendor/bin; pwd):$PATH" - -install: - - moodle-plugin-ci install - -script: - - moodle-plugin-ci phplint - - moodle-plugin-ci phpcpd - - moodle-plugin-ci phpmd - - moodle-plugin-ci codechecker - - moodle-plugin-ci validate - - moodle-plugin-ci savepoints - - moodle-plugin-ci mustache - - moodle-plugin-ci grunt - - moodle-plugin-ci phpdoc - - moodle-plugin-ci phpunit --coverage-clover - - moodle-plugin-ci behat - -after_success: - - moodle-plugin-ci coveralls-upload diff --git a/action.php b/action.php index f93300d..191e8eb 100755 --- a/action.php +++ b/action.php @@ -33,16 +33,14 @@ $cmid = capquiz_urls::require_course_module_id_param(); $cm = get_coursemodule_from_id('capquiz', $cmid, 0, false, MUST_EXIST); require_login($cm->course, false, $cm); + $context = \context_module::instance($cmid); require_capability('mod/capquiz:instructor', $context); $action = required_param('action', PARAM_TEXT); -$cmid = capquiz_urls::require_course_module_id_param(); $capquiz = new capquiz($cmid); -if ($capquiz) { - capquiz_urls::set_page_url($capquiz, capquiz_urls::$urlasync); - capquiz_action_performer::perform($action, $capquiz); -} +capquiz_urls::set_page_url($capquiz, capquiz_urls::$urlasync); +capquiz_action_performer::perform($action, $capquiz); capquiz_urls::redirect_to_dashboard(); diff --git a/adminlib.php b/adminlib.php index 2e09f85..5ce721b 100644 --- a/adminlib.php +++ b/adminlib.php @@ -38,37 +38,33 @@ class capquiz_admin_page_manage_capquiz_plugins extends admin_externalpage { /** @var string the name of plugin subtype */ - private $subtype = ''; + private string $subtype; /** - * The constructor - calls parent constructor + * Constructor. * * @param string $subtype */ - public function __construct($subtype) { + public function __construct(string $subtype) { $this->subtype = $subtype; - $url = new moodle_url('/mod/capquiz/adminmanageplugins.php', array('subtype' => $subtype)); - parent::__construct('manage' . $subtype . 'plugins', - get_string('manage' . $subtype . 'plugins', 'capquiz'), - $url); + $url = new moodle_url('/mod/capquiz/adminmanageplugins.php', ['subtype' => $subtype]); + parent::__construct('manage' . $subtype . 'plugins', get_string('manage' . $subtype . 'plugins', 'capquiz'), $url); } /** * Search plugins for the specified string * * @param string $query The string to search for - * @return array */ - public function search($query) { - if ($result = parent::search($query)) { + public function search($query): array { + $result = parent::search($query); + if ($result) { return $result; } - $found = false; - foreach (core_component::get_plugin_list($this->subtype) as $name => $notused) { - if (strpos(core_text::strtolower(get_string('pluginname', $this->subtype . '_' . $name)), - $query) !== false) { + $pluginname = get_string('pluginname', $this->subtype . '_' . $name); + if (str_contains(core_text::strtolower($pluginname), $query)) { $found = true; break; } @@ -76,10 +72,10 @@ public function search($query) { if ($found) { $result = new stdClass(); $result->page = $this; - $result->settings = array(); - return array($this->name => $result); + $result->settings = []; + return [$this->name => $result]; } else { - return array(); + return []; } } } @@ -95,60 +91,53 @@ public function search($query) { */ class capquiz_plugin_manager { - /** @var object the url of the manage capquiz plugin page */ - private $pageurl; - /** @var string any error from the current action */ - private $error = ''; + /** @var moodle_url the url of the manage capquiz plugin page */ + private moodle_url $pageurl; + /** @var string report */ - private $subtype = ''; + private string $subtype; + + /** @var string any error from the current action */ + private string $error = ''; /** - * Constructor for this capquiz plugin manager + * Constructor. + * * @param string $subtype */ - public function __construct($subtype) { - $this->pageurl = new moodle_url('/mod/capquiz/adminmanageplugins.php', array('subtype' => $subtype)); + public function __construct(string $subtype) { + $this->pageurl = new moodle_url('/mod/capquiz/adminmanageplugins.php', ['subtype' => $subtype]); $this->subtype = $subtype; } /** * This is the entry point for this controller class. * - * @param string $action - The action to perform - * @param string $plugin - Optional name of a plugin type to perform the action on - * @return None + * @param string $action Action to perform + * @param ?string $plugin Optional name of a plugin type to perform the action on */ - public function execute($action, $plugin) { - if ($action == null) { - $action = 'view'; - } - + public function execute(string $action = 'view', ?string $plugin = null): void { $this->check_permissions(); - - // Process. - if ($action == 'hide' && $plugin != null) { - $action = $this->hide_plugin($plugin); - } else if ($action == 'show' && $plugin != null) { - $action = $this->show_plugin($plugin); - } else if ($action == 'moveup' && $plugin != null) { - $action = $this->move_plugin($plugin, 'up'); - } else if ($action == 'movedown' && $plugin != null) { - $action = $this->move_plugin($plugin, 'down'); + if ($plugin !== null) { + if ($action === 'hide') { + $action = $this->hide_plugin($plugin); + } else if ($action === 'show') { + $action = $this->show_plugin($plugin); + } else if ($action === 'moveup') { + $action = $this->move_plugin($plugin, 'up'); + } else if ($action === 'movedown') { + $action = $this->move_plugin($plugin, 'down'); + } } - - // View. - if ($action == 'view') { + if ($action === 'view') { $this->view_plugins_table(); } } /** * Check this user has permission to edit the list of installed plugins - * - * @return None */ - private function check_permissions() { - // Check permissions. + private function check_permissions(): void { require_login(); $systemcontext = context_system::instance(); require_capability('moodle/site:config', $systemcontext); @@ -160,7 +149,7 @@ private function check_permissions() { * @param string $plugin - The plugin to hide * @return string The next page to display */ - public function hide_plugin($plugin) { + public function hide_plugin(string $plugin): string { set_config('disabled', 1, $this->subtype . '_' . $plugin); core_plugin_manager::reset_caches(); return 'view'; @@ -172,7 +161,7 @@ public function hide_plugin($plugin) { * @param string $plugin - The plugin to show * @return string The next page to display */ - public function show_plugin($plugin) { + public function show_plugin(string $plugin): string { set_config('disabled', 0, $this->subtype . '_' . $plugin); core_plugin_manager::reset_caches(); return 'view'; @@ -185,7 +174,7 @@ public function show_plugin($plugin) { * @param string $dir - up or down * @return string The next page to display */ - public function move_plugin($plugintomove, $dir) { + public function move_plugin(string $plugintomove, string $dir): string { // Get a list of the current plugins. $plugins = $this->get_sorted_plugins_list(); @@ -229,11 +218,9 @@ public function move_plugin($plugintomove, $dir) { * * @return array The list of plugins */ - public function get_sorted_plugins_list() { + public function get_sorted_plugins_list(): array { $names = core_component::get_plugin_list($this->subtype); - - $result = array(); - + $result = []; foreach ($names as $name => $path) { $idx = get_config($this->subtype . '_' . $name, 'sortorder'); if (!$idx) { @@ -245,16 +232,13 @@ public function get_sorted_plugins_list() { $result[$idx] = $name; } ksort($result); - return $result; } /** * Write the HTML for the capquiz plugins table. - * - * @return None */ - private function view_plugins_table() { + private function view_plugins_table(): void { global $OUTPUT, $CFG; require_once($CFG->libdir . '/tablelib.php'); @@ -262,11 +246,10 @@ private function view_plugins_table() { $this->view_header(); $table = new flexible_table($this->subtype . 'pluginsadminttable'); $table->define_baseurl($this->pageurl); - $table->define_columns(array('pluginname', 'version', 'hideshow', 'order', - 'settings', 'uninstall')); - $table->define_headers(array(get_string($this->subtype . 'type', 'capquiz'), + $table->define_columns(['pluginname', 'version', 'hideshow', 'order', 'settings', 'uninstall']); + $table->define_headers([get_string($this->subtype . 'type', 'capquiz'), get_string('version'), get_string('hideshow', 'capquiz'), - get_string('order'), get_string('settings'), get_string('uninstallplugin', 'core_admin'))); + get_string('order'), get_string('settings'), get_string('uninstallplugin', 'core_admin')]); $table->set_attribute('id', $this->subtype . 'plugins'); $table->set_attribute('class', 'admintable generaltable'); $table->setup(); @@ -275,7 +258,7 @@ private function view_plugins_table() { $shortsubtype = substr($this->subtype, strlen('capquiz')); foreach ($plugins as $idx => $plugin) { - $row = array(); + $row = []; $class = ''; $row[] = get_string('pluginname', $this->subtype . '_' . $plugin); @@ -294,7 +277,7 @@ private function view_plugins_table() { if (!$idx == 0) { $movelinks .= $this->format_icon_link('moveup', $plugin, 't/up', get_string('up')); } else { - $movelinks .= $OUTPUT->spacer(array('width' => 16)); + $movelinks .= $OUTPUT->spacer(['width' => 16]); } if ($idx != count($plugins) - 1) { $movelinks .= $this->format_icon_link('movedown', $plugin, 't/down', get_string('down')); @@ -302,9 +285,9 @@ private function view_plugins_table() { $row[] = $movelinks; $exists = file_exists($CFG->dirroot . '/mod/capquiz/' . $shortsubtype . '/' . $plugin . '/settings.php'); - if ($row[1] != '' && $exists) { - $row[] = html_writer::link(new moodle_url('/admin/settings.php', - array('section' => $this->subtype . '_' . $plugin)), get_string('settings')); + if ($row[1] !== '' && $exists) { + $url = new moodle_url('/admin/settings.php', ['section' => $this->subtype . '_' . $plugin]); + $row[] = html_writer::link($url, get_string('settings')); } else { $row[] = ' '; } @@ -320,10 +303,8 @@ private function view_plugins_table() { /** * Write the page header - * - * @return None */ - private function view_header() { + private function view_header(): void { global $OUTPUT; admin_externalpage_setup('manage' . $this->subtype . 'plugins'); // Print the page heading. @@ -340,11 +321,8 @@ private function view_header() { * @param string $alt The string description of the link used as the title and alt text * @return string The icon/link */ - private function format_icon_link($action, $plugin, $icon, $alt) { + private function format_icon_link(string $action, string $plugin, string $icon, string $alt): string { global $OUTPUT; - - $url = $this->pageurl; - if ($action === 'delete') { $url = core_plugin_manager::instance()->get_uninstall_url($this->subtype . '_' . $plugin, 'manage'); if (!$url) { @@ -352,19 +330,15 @@ private function format_icon_link($action, $plugin, $icon, $alt) { } return html_writer::link($url, get_string('uninstallplugin', 'core_admin')); } - - return $OUTPUT->action_icon(new moodle_url($url, - array('action' => $action, 'plugin' => $plugin, 'sesskey' => sesskey())), - new pix_icon($icon, $alt, 'moodle', array('title' => $alt)), - null, array('title' => $alt)) . ' '; + $url = new moodle_url($this->pageurl, ['action' => $action, 'plugin' => $plugin, 'sesskey' => sesskey()]); + $icon = new pix_icon($icon, $alt, 'moodle', ['title' => $alt]); + return $OUTPUT->action_icon($url, $icon, null, ['title' => $alt]) . ' '; } /** * Write the page footer - * - * @return None */ - private function view_footer() { + private function view_footer(): void { global $OUTPUT; echo $OUTPUT->footer(); } diff --git a/adminmanageplugins.php b/adminmanageplugins.php index 3d9d758..ca758fd 100644 --- a/adminmanageplugins.php +++ b/adminmanageplugins.php @@ -30,17 +30,14 @@ require_once($CFG->dirroot . '/mod/capquiz/adminlib.php'); $subtype = required_param('subtype', PARAM_PLUGIN); -$action = optional_param('action', null, PARAM_PLUGIN); +$action = optional_param('action', 'view', PARAM_PLUGIN); $plugin = optional_param('plugin', null, PARAM_PLUGIN); if (!empty($plugin)) { require_sesskey(); } -// Create the class for this controller. -$pluginmanager = new capquiz_plugin_manager($subtype); - $PAGE->set_context(context_system::instance()); -// Execute the controller. +$pluginmanager = new capquiz_plugin_manager($subtype); $pluginmanager->execute($action, $plugin); diff --git a/amd/build/edit_questions.min.js b/amd/build/edit_questions.min.js index ccf188c..e709700 100755 --- a/amd/build/edit_questions.min.js +++ b/amd/build/edit_questions.min.js @@ -4,6 +4,6 @@ * @copyright 2019 NTNU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -define("mod_capquiz/edit_questions",["jquery"],(function($){var parameters={courseModuleId:0};function sendAction(data,onSuccess,onError){$.ajax({type:"post",url:"action.php",data:data,success:onSuccess,error:onError})}function sendDefaultQuestionRating(data,rating,onSuccess,onError){sendAction({action:"set-default-question-rating",id:parameters.courseModuleId,rating:rating},onSuccess,onError)}function sendQuestionRating(data,rating,onSuccess,onError){sendAction({action:"set-question-rating",id:parameters.courseModuleId,"question-id":data.questionId,rating:rating},onSuccess,onError)}function submitInput($input,sendInput,data){$input.data("saving",!0),$input.data("dirty",!1);var $indicator=$input.next();$indicator.css("color","blue"),sendInput(data,$input.val(),(function(){!0===$input.data("dirty")?submitInput($input,sendInput,data):($indicator.css("color","green"),$input.data("dirty",!1),$input.data("saving",!1))}),(function(){$indicator.css("color","red")}))}function submitQuestionRating($input){submitInput($input,sendQuestionRating,{questionId:$input.data("question-id")})}function submitDefaultQuestionRating($input){submitInput($input,sendDefaultQuestionRating,null)}function registerListener(query,submit){$(document).on("input",query,(function(event){var $input=$(event.target);!0!==$input.data("saving")?submit($input):$input.data("dirty",!0)}))}function sortTable($header){var column=$header.index(),$table=$header.parent().parent(),$rows=$table.find("tr:gt(0)").toArray().sort((function(rowA,rowB){var $colA=$(rowA).children("td").eq(0),$colB=$(rowB).children("td").eq(0);return parseInt($colA.text())-parseInt($colB.text())}));$table.append($rows),$rows=$table.find("tr:gt(0)").toArray().sort((function(rowA,rowB){var $colA=$(rowA).children("td").eq(column),$colB=$(rowB).children("td").eq(column),$itemA=$colA.find(".capquiz-sortable-item"),$itemB=$colB.find(".capquiz-sortable-item"),valA=0===$itemA.length?$colA.html():0===$itemA.val().length?$itemA.html():$itemA.val(),valB=0===$itemB.length?$colB.html():0===$itemB.val().length?$itemB.html():$itemB.val();return $.isNumeric(valA)&&$.isNumeric(valB)?valA-valB:valA.toString().localeCompare(valB)}));var ascending="true"===$table.data("asc");$table.data("asc",ascending?"false":"true");var iconName=ascending?"fa-arrow-up":"fa-arrow-down";$.each($table.find(".capquiz-sortable"),(function(){$(this).find(".fa").remove()})),$header.prepend(''),ascending||($rows=$rows.reverse()),$table.append($rows);var i=1;$table.find("tr:gt(0)").each((function(){$(this).find("td:first-child").html(i),i++}))}return{initialize:function(courseModuleId){parameters.courseModuleId=courseModuleId,registerListener(".capquiz-question-rating input",submitQuestionRating),registerListener(".capquiz-default-question-rating input",submitDefaultQuestionRating),$(".capquiz-question-rating-submit-wrapper button").each((function(index,object){$(object).attr("tabindex",-1)})),$(document).on("click",".capquiz-sortable",(function(){sortTable($(this))})),$(".capquiz-sortable-default-asc").each((function(){sortTable($(this)),sortTable($(this))})),$(".capquiz-sortable-default-desc").each((function(){sortTable($(this))})),$(".capquiz-add-selected-questions").on("click",(function(){var questionIds="";$("#categoryquestions td input[type=checkbox]:checked").each((function(){questionIds+=$(this).attr("name").slice(1)+","})),$.post("action.php",{action:"add-question",id:parameters.courseModuleId,"question-id":questionIds},(function(){location.reload()}))}))}}})); +define("mod_capquiz/edit_questions",["jquery"],(function($){var parameters={courseModuleId:0};function sendAction(data,onSuccess,onError){$.ajax({type:"post",url:"action.php",data:data,success:onSuccess,error:onError})}function sendDefaultQuestionRating(data,rating,onSuccess,onError){sendAction({action:"set-default-question-rating",id:parameters.courseModuleId,rating:rating},onSuccess,onError)}function sendQuestionRating(data,rating,onSuccess,onError){sendAction({action:"set-question-rating",id:parameters.courseModuleId,"question-id":data.questionId,rating:rating},onSuccess,onError)}function submitInput($input,sendInput,data){$input.data("saving",!0),$input.data("dirty",!1);var $indicator=$input.next();$indicator.css("color","blue"),sendInput(data,$input.val(),(function(){!0===$input.data("dirty")?submitInput($input,sendInput,data):($indicator.css("color","green"),$input.data("dirty",!1),$input.data("saving",!1))}),(function(){$indicator.css("color","red")}))}function submitQuestionRating($input){submitInput($input,sendQuestionRating,{questionId:$input.data("question-id")})}function submitDefaultQuestionRating($input){submitInput($input,sendDefaultQuestionRating,null)}function registerListener(query,submit){$(document).on("input",query,(function(event){var $input=$(event.target);!0!==$input.data("saving")?submit($input):$input.data("dirty",!0)}))}function sortTable($header){const column=$header.index(),$table=$header.parent().parent();let $rows=$table.find("tr:gt(0)").toArray().sort((function(rowA,rowB){const $colA=$(rowA).children("td").eq(0),$colB=$(rowB).children("td").eq(0);return parseInt($colA.text())-parseInt($colB.text())}));$table.append($rows),$rows=$table.find("tr:gt(0)").toArray().sort((function(rowA,rowB){const $colA=$(rowA).children("td").eq(column),$colB=$(rowB).children("td").eq(column),$itemA=$colA.find(".capquiz-sortable-item"),$itemB=$colB.find(".capquiz-sortable-item");let valA,valB;return valA=0===$itemA.length?$colA.html():0===$itemA.val().length?$itemA.html():$itemA.val(),valB=0===$itemB.length?$colB.html():0===$itemB.val().length?$itemB.html():$itemB.val(),$.isNumeric(valA)&&$.isNumeric(valB)?valA-valB:valA.toString().localeCompare(valB)}));const ascending="true"===$table.data("asc");$table.data("asc",ascending?"false":"true");const iconName=ascending?"fa-arrow-up":"fa-arrow-down";$.each($table.find(".capquiz-sortable"),(function(){$(this).find(".fa").remove()})),$header.prepend(''),ascending||($rows=$rows.reverse()),$table.append($rows);let i=1;$table.find("tr:gt(0)").each((function(){$(this).find("td:first-child").html(i),i++}))}return{initialize:function(courseModuleId){parameters.courseModuleId=courseModuleId,registerListener(".capquiz-question-rating input",submitQuestionRating),registerListener(".capquiz-default-question-rating input",submitDefaultQuestionRating),$(".capquiz-question-rating-submit-wrapper button").each((function(index,object){$(object).attr("tabindex",-1)})),$(document).on("click",".capquiz-sortable",(function(){sortTable($(this))})),$(".capquiz-sortable-default-asc").each((function(){sortTable($(this)),sortTable($(this))})),$(".capquiz-sortable-default-desc").each((function(){sortTable($(this))})),$(".capquiz-add-selected-questions").on("click",(function(){var questionIds="";$("#categoryquestions td input[type=checkbox]:checked").each((function(){questionIds+=$(this).attr("name").slice(1)+","})),$.post("action.php",{action:"add-question",id:parameters.courseModuleId,"question-id":questionIds},(function(){location.reload()}))}))}}})); //# sourceMappingURL=edit_questions.min.js.map \ No newline at end of file diff --git a/amd/build/edit_questions.min.js.map b/amd/build/edit_questions.min.js.map index 1e3d7d1..a7b839c 100644 --- a/amd/build/edit_questions.min.js.map +++ b/amd/build/edit_questions.min.js.map @@ -1 +1 @@ -{"version":3,"file":"edit_questions.min.js","sources":["../src/edit_questions.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * @module mod_capquiz\n * @author Sebastian S. Gundersen \n * @copyright 2019 NTNU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery'], function($) {\n\n var parameters = {\n courseModuleId: 0,\n };\n\n /**\n * Send an action to the server.\n * @param {Object} data\n * @param {Object} onSuccess\n * @param {Object} onError\n */\n function sendAction(data, onSuccess, onError) {\n $.ajax({\n type: 'post',\n url: 'action.php',\n data: data,\n success: onSuccess,\n error: onError\n });\n }\n\n /**\n * Send the new default rating for the question list to the server.\n * @param {Object} data\n * @param {number} rating\n * @param {Object} onSuccess\n * @param {Object} onError\n */\n function sendDefaultQuestionRating(data, rating, onSuccess, onError) {\n sendAction({\n 'action': 'set-default-question-rating',\n 'id': parameters.courseModuleId,\n 'rating': rating,\n }, onSuccess, onError);\n }\n\n /**\n * Send the new rating for the question to the server.\n * @param {Object} data\n * @param {number} rating\n * @param {Object} onSuccess\n * @param {Object} onError\n */\n function sendQuestionRating(data, rating, onSuccess, onError) {\n sendAction({\n 'action': 'set-question-rating',\n 'id': parameters.courseModuleId,\n 'question-id': data.questionId,\n 'rating': rating,\n }, onSuccess, onError);\n }\n\n /**\n * Send the new value, and avoid race condition.\n * @param {Object} $input\n * @param {Object} sendInput\n * @param {Object} data\n */\n function submitInput($input, sendInput, data) {\n $input.data('saving', true);\n $input.data('dirty', false);\n var $indicator = $input.next();\n $indicator.css('color', 'blue');\n sendInput(data, $input.val(), function() {\n if ($input.data('dirty') === true) {\n submitInput($input, sendInput, data);\n } else {\n $indicator.css('color', 'green');\n $input.data('dirty', false);\n $input.data('saving', false);\n }\n }, function() {\n $indicator.css('color', 'red');\n });\n }\n\n /**\n * Send the new rating for the question, and avoid race condition.\n * @param {Object} $input\n */\n function submitQuestionRating($input) {\n submitInput($input, sendQuestionRating, {questionId: $input.data('question-id')});\n }\n\n /**\n * Send the new default rating for the question list, and avoid race condition.\n * @param {Object} $input\n */\n function submitDefaultQuestionRating($input) {\n submitInput($input, sendDefaultQuestionRating, null);\n }\n\n /**\n * Register an input event listener for submission.\n * @param {string} query\n * @param {Object} submit\n */\n function registerListener(query, submit) {\n $(document).on('input', query, function(event) {\n var $input = $(event.target);\n var isBeingSaved = $input.data('saving');\n if (isBeingSaved === true) {\n $input.data('dirty', true);\n return;\n }\n submit($input);\n });\n }\n\n /**\n * Sorts a table by the respective column based on $header.\n * It searches for an element of class \"capquiz-sortable-item\" inside the , and if found,\n * the value attribute is used if it exists. Otherwise, the inner html is used to sort by.\n *\n * The tag may not have the item class, as it has no effect on the sorting.\n * Their children elements are not required to have the class either. The inner html of will be used then.\n *\n * The first column in the table must be an index of the row.\n *\n * @param {Object} $header The header column for which to sort the table by.\n */\n function sortTable($header) {\n var column = $header.index();\n var $table = $header.parent().parent();\n var $rows = $table.find('tr:gt(0)').toArray().sort(function(rowA, rowB) {\n var $colA = $(rowA).children('td').eq(0);\n var $colB = $(rowB).children('td').eq(0);\n return parseInt($colA.text()) - parseInt($colB.text());\n });\n $table.append($rows);\n $rows = $table.find('tr:gt(0)').toArray().sort(function(rowA, rowB) {\n var $colA = $(rowA).children('td').eq(column);\n var $colB = $(rowB).children('td').eq(column);\n var $itemA = $colA.find('.capquiz-sortable-item');\n var $itemB = $colB.find('.capquiz-sortable-item');\n var valA = ($itemA.length === 0 ? $colA.html() : ($itemA.val().length === 0 ? $itemA.html() : $itemA.val()));\n var valB = ($itemB.length === 0 ? $colB.html() : ($itemB.val().length === 0 ? $itemB.html() : $itemB.val()));\n if ($.isNumeric(valA) && $.isNumeric(valB)) {\n return valA - valB;\n } else {\n return valA.toString().localeCompare(valB);\n }\n });\n var ascending = ($table.data('asc') === 'true');\n $table.data('asc', ascending ? 'false' : 'true');\n var iconName = (ascending ? 'fa-arrow-up' : 'fa-arrow-down');\n $.each($table.find('.capquiz-sortable'), function() {\n $(this).find('.fa').remove();\n });\n $header.prepend('');\n if (!ascending) {\n $rows = $rows.reverse();\n }\n $table.append($rows);\n var i = 1;\n $table.find('tr:gt(0)').each(function() {\n $(this).find('td:first-child').html(i);\n i++;\n });\n }\n\n /**\n * Register click event listeners for the sortable table columns.\n */\n function registerSortListener() {\n $(document).on('click', '.capquiz-sortable', function() {\n sortTable($(this));\n });\n $('.capquiz-sortable-default-asc').each(function() {\n sortTable($(this));\n sortTable($(this));\n });\n $('.capquiz-sortable-default-desc').each(function() {\n sortTable($(this));\n });\n }\n\n /**\n * Set the tab indices for the question rating elements to be more user friendly.\n */\n function fixTabIndicesForQuestionRatingInputs() {\n $('.capquiz-question-rating-submit-wrapper button').each(function(index, object) {\n $(object).attr('tabindex', -1);\n });\n }\n\n /**\n * Register click event listener for \"Add to quiz\" button.\n */\n function listenAddToQuiz() {\n $('.capquiz-add-selected-questions').on('click', function() {\n var questionIds = '';\n $('#categoryquestions td input[type=checkbox]:checked').each(function() {\n questionIds += $(this).attr('name').slice(1) + ',';\n });\n $.post('action.php', {\n 'action': 'add-question',\n 'id': parameters.courseModuleId,\n 'question-id': questionIds,\n }, function() {\n location.reload();\n });\n });\n }\n\n return {\n initialize: function(courseModuleId) {\n parameters.courseModuleId = courseModuleId;\n registerListener('.capquiz-question-rating input', submitQuestionRating);\n registerListener('.capquiz-default-question-rating input', submitDefaultQuestionRating);\n fixTabIndicesForQuestionRatingInputs();\n registerSortListener();\n listenAddToQuiz();\n }\n };\n\n});\n"],"names":["define","$","parameters","courseModuleId","sendAction","data","onSuccess","onError","ajax","type","url","success","error","sendDefaultQuestionRating","rating","sendQuestionRating","questionId","submitInput","$input","sendInput","$indicator","next","css","val","submitQuestionRating","submitDefaultQuestionRating","registerListener","query","submit","document","on","event","target","sortTable","$header","column","index","$table","parent","$rows","find","toArray","sort","rowA","rowB","$colA","children","eq","$colB","parseInt","text","append","$itemA","$itemB","valA","length","html","valB","isNumeric","toString","localeCompare","ascending","iconName","each","this","remove","prepend","reverse","i","initialize","object","attr","questionIds","slice","post","location","reload"],"mappings":";;;;;;AAsBAA,oCAAO,CAAC,WAAW,SAASC,OAEpBC,WAAa,CACbC,eAAgB,YASXC,WAAWC,KAAMC,UAAWC,SACjCN,EAAEO,KAAK,CACHC,KAAM,OACNC,IAAK,aACLL,KAAMA,KACNM,QAASL,UACTM,MAAOL,mBAWNM,0BAA0BR,KAAMS,OAAQR,UAAWC,SACxDH,WAAW,QACG,iCACJF,WAAWC,sBACPW,QACXR,UAAWC,kBAUTQ,mBAAmBV,KAAMS,OAAQR,UAAWC,SACjDH,WAAW,QACG,yBACJF,WAAWC,6BACFE,KAAKW,kBACVF,QACXR,UAAWC,kBASTU,YAAYC,OAAQC,UAAWd,MACpCa,OAAOb,KAAK,UAAU,GACtBa,OAAOb,KAAK,SAAS,OACjBe,WAAaF,OAAOG,OACxBD,WAAWE,IAAI,QAAS,QACxBH,UAAUd,KAAMa,OAAOK,OAAO,YACG,IAAzBL,OAAOb,KAAK,SACZY,YAAYC,OAAQC,UAAWd,OAE/Be,WAAWE,IAAI,QAAS,SACxBJ,OAAOb,KAAK,SAAS,GACrBa,OAAOb,KAAK,UAAU,OAE3B,WACCe,WAAWE,IAAI,QAAS,mBAQvBE,qBAAqBN,QAC1BD,YAAYC,OAAQH,mBAAoB,CAACC,WAAYE,OAAOb,KAAK,0BAO5DoB,4BAA4BP,QACjCD,YAAYC,OAAQL,0BAA2B,eAQ1Ca,iBAAiBC,MAAOC,QAC7B3B,EAAE4B,UAAUC,GAAG,QAASH,OAAO,SAASI,WAChCb,OAASjB,EAAE8B,MAAMC,SAEA,IADFd,OAAOb,KAAK,UAK/BuB,OAAOV,QAHHA,OAAOb,KAAK,SAAS,eAmBxB4B,UAAUC,aACXC,OAASD,QAAQE,QACjBC,OAASH,QAAQI,SAASA,SAC1BC,MAAQF,OAAOG,KAAK,YAAYC,UAAUC,MAAK,SAASC,KAAMC,UAC1DC,MAAQ5C,EAAE0C,MAAMG,SAAS,MAAMC,GAAG,GAClCC,MAAQ/C,EAAE2C,MAAME,SAAS,MAAMC,GAAG,UAC/BE,SAASJ,MAAMK,QAAUD,SAASD,MAAME,WAEnDb,OAAOc,OAAOZ,OACdA,MAAQF,OAAOG,KAAK,YAAYC,UAAUC,MAAK,SAASC,KAAMC,UACtDC,MAAQ5C,EAAE0C,MAAMG,SAAS,MAAMC,GAAGZ,QAClCa,MAAQ/C,EAAE2C,MAAME,SAAS,MAAMC,GAAGZ,QAClCiB,OAASP,MAAML,KAAK,0BACpBa,OAASL,MAAMR,KAAK,0BACpBc,KAA0B,IAAlBF,OAAOG,OAAeV,MAAMW,OAAkC,IAAxBJ,OAAO7B,MAAMgC,OAAeH,OAAOI,OAASJ,OAAO7B,MACjGkC,KAA0B,IAAlBJ,OAAOE,OAAeP,MAAMQ,OAAkC,IAAxBH,OAAO9B,MAAMgC,OAAeF,OAAOG,OAASH,OAAO9B,aACjGtB,EAAEyD,UAAUJ,OAASrD,EAAEyD,UAAUD,MAC1BH,KAAOG,KAEPH,KAAKK,WAAWC,cAAcH,aAGzCI,UAAoC,SAAvBxB,OAAOhC,KAAK,OAC7BgC,OAAOhC,KAAK,MAAOwD,UAAY,QAAU,YACrCC,SAAYD,UAAY,cAAgB,gBAC5C5D,EAAE8D,KAAK1B,OAAOG,KAAK,sBAAsB,WACrCvC,EAAE+D,MAAMxB,KAAK,OAAOyB,YAExB/B,QAAQgC,QAAQ,gBAAkBJ,SAAW,UACxCD,YACDtB,MAAQA,MAAM4B,WAElB9B,OAAOc,OAAOZ,WACV6B,EAAI,EACR/B,OAAOG,KAAK,YAAYuB,MAAK,WACzB9D,EAAE+D,MAAMxB,KAAK,kBAAkBgB,KAAKY,GACpCA,aAgDD,CACHC,WAAY,SAASlE,gBACjBD,WAAWC,eAAiBA,eAC5BuB,iBAAiB,iCAAkCF,sBACnDE,iBAAiB,yCAA0CD,6BA5B/DxB,EAAE,kDAAkD8D,MAAK,SAAS3B,MAAOkC,QACrErE,EAAEqE,QAAQC,KAAK,YAAa,MAjBhCtE,EAAE4B,UAAUC,GAAG,QAAS,qBAAqB,WACzCG,UAAUhC,EAAE+D,UAEhB/D,EAAE,iCAAiC8D,MAAK,WACpC9B,UAAUhC,EAAE+D,OACZ/B,UAAUhC,EAAE+D,UAEhB/D,EAAE,kCAAkC8D,MAAK,WACrC9B,UAAUhC,EAAE+D,UAiBhB/D,EAAE,mCAAmC6B,GAAG,SAAS,eACzC0C,YAAc,GAClBvE,EAAE,sDAAsD8D,MAAK,WACzDS,aAAevE,EAAE+D,MAAMO,KAAK,QAAQE,MAAM,GAAK,OAEnDxE,EAAEyE,KAAK,aAAc,QACP,kBACJxE,WAAWC,6BACFqE,cAChB,WACCG,SAASC"} \ No newline at end of file +{"version":3,"file":"edit_questions.min.js","sources":["../src/edit_questions.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * @module mod_capquiz\n * @author Sebastian S. Gundersen \n * @copyright 2019 NTNU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery'], function($) {\n\n var parameters = {\n courseModuleId: 0,\n };\n\n /**\n * Send an action to the server.\n * @param {Object} data\n * @param {Object} onSuccess\n * @param {Object} onError\n */\n function sendAction(data, onSuccess, onError) {\n $.ajax({\n type: 'post',\n url: 'action.php',\n data: data,\n success: onSuccess,\n error: onError\n });\n }\n\n /**\n * Send the new default rating for the question list to the server.\n * @param {Object} data\n * @param {number} rating\n * @param {Object} onSuccess\n * @param {Object} onError\n */\n function sendDefaultQuestionRating(data, rating, onSuccess, onError) {\n sendAction({\n 'action': 'set-default-question-rating',\n 'id': parameters.courseModuleId,\n 'rating': rating,\n }, onSuccess, onError);\n }\n\n /**\n * Send the new rating for the question to the server.\n * @param {Object} data\n * @param {number} rating\n * @param {Object} onSuccess\n * @param {Object} onError\n */\n function sendQuestionRating(data, rating, onSuccess, onError) {\n sendAction({\n 'action': 'set-question-rating',\n 'id': parameters.courseModuleId,\n 'question-id': data.questionId,\n 'rating': rating,\n }, onSuccess, onError);\n }\n\n /**\n * Send the new value, and avoid race condition.\n * @param {Object} $input\n * @param {Object} sendInput\n * @param {Object} data\n */\n function submitInput($input, sendInput, data) {\n $input.data('saving', true);\n $input.data('dirty', false);\n var $indicator = $input.next();\n $indicator.css('color', 'blue');\n sendInput(data, $input.val(), function() {\n if ($input.data('dirty') === true) {\n submitInput($input, sendInput, data);\n } else {\n $indicator.css('color', 'green');\n $input.data('dirty', false);\n $input.data('saving', false);\n }\n }, function() {\n $indicator.css('color', 'red');\n });\n }\n\n /**\n * Send the new rating for the question, and avoid race condition.\n * @param {Object} $input\n */\n function submitQuestionRating($input) {\n submitInput($input, sendQuestionRating, {questionId: $input.data('question-id')});\n }\n\n /**\n * Send the new default rating for the question list, and avoid race condition.\n * @param {Object} $input\n */\n function submitDefaultQuestionRating($input) {\n submitInput($input, sendDefaultQuestionRating, null);\n }\n\n /**\n * Register an input event listener for submission.\n * @param {string} query\n * @param {Object} submit\n */\n function registerListener(query, submit) {\n $(document).on('input', query, function(event) {\n var $input = $(event.target);\n var isBeingSaved = $input.data('saving');\n if (isBeingSaved === true) {\n $input.data('dirty', true);\n return;\n }\n submit($input);\n });\n }\n\n /**\n * Sorts a table by the respective column based on $header.\n * It searches for an element of class \"capquiz-sortable-item\" inside the , and if found,\n * the value attribute is used if it exists. Otherwise, the inner html is used to sort by.\n *\n * The tag may not have the item class, as it has no effect on the sorting.\n * Their children elements are not required to have the class either. The inner html of will be used then.\n *\n * The first column in the table must be an index of the row.\n *\n * @param {Object} $header The header column for which to sort the table by.\n */\n function sortTable($header) {\n const column = $header.index();\n const $table = $header.parent().parent();\n let $rows = $table.find('tr:gt(0)').toArray().sort(function(rowA, rowB) {\n const $colA = $(rowA).children('td').eq(0);\n const $colB = $(rowB).children('td').eq(0);\n return parseInt($colA.text()) - parseInt($colB.text());\n });\n $table.append($rows);\n $rows = $table.find('tr:gt(0)').toArray().sort(function(rowA, rowB) {\n const $colA = $(rowA).children('td').eq(column);\n const $colB = $(rowB).children('td').eq(column);\n const $itemA = $colA.find('.capquiz-sortable-item');\n const $itemB = $colB.find('.capquiz-sortable-item');\n let valA;\n if ($itemA.length === 0) {\n valA = $colA.html();\n } else {\n valA = $itemA.val().length === 0 ? $itemA.html() : $itemA.val();\n }\n let valB;\n if ($itemB.length === 0) {\n valB = $colB.html();\n } else {\n valB = $itemB.val().length === 0 ? $itemB.html() : $itemB.val();\n }\n if ($.isNumeric(valA) && $.isNumeric(valB)) {\n return valA - valB;\n } else {\n return valA.toString().localeCompare(valB);\n }\n });\n const ascending = ($table.data('asc') === 'true');\n $table.data('asc', ascending ? 'false' : 'true');\n const iconName = (ascending ? 'fa-arrow-up' : 'fa-arrow-down');\n $.each($table.find('.capquiz-sortable'), function() {\n $(this).find('.fa').remove();\n });\n $header.prepend('');\n if (!ascending) {\n $rows = $rows.reverse();\n }\n $table.append($rows);\n let i = 1;\n $table.find('tr:gt(0)').each(function() {\n $(this).find('td:first-child').html(i);\n i++;\n });\n }\n\n /**\n * Register click event listeners for the sortable table columns.\n */\n function registerSortListener() {\n $(document).on('click', '.capquiz-sortable', function() {\n sortTable($(this));\n });\n $('.capquiz-sortable-default-asc').each(function() {\n sortTable($(this));\n sortTable($(this));\n });\n $('.capquiz-sortable-default-desc').each(function() {\n sortTable($(this));\n });\n }\n\n /**\n * Set the tab indices for the question rating elements to be more user friendly.\n */\n function fixTabIndicesForQuestionRatingInputs() {\n $('.capquiz-question-rating-submit-wrapper button').each(function(index, object) {\n $(object).attr('tabindex', -1);\n });\n }\n\n /**\n * Register click event listener for \"Add to quiz\" button.\n */\n function listenAddToQuiz() {\n $('.capquiz-add-selected-questions').on('click', function() {\n var questionIds = '';\n $('#categoryquestions td input[type=checkbox]:checked').each(function() {\n questionIds += $(this).attr('name').slice(1) + ',';\n });\n $.post('action.php', {\n 'action': 'add-question',\n 'id': parameters.courseModuleId,\n 'question-id': questionIds,\n }, function() {\n location.reload();\n });\n });\n }\n\n return {\n initialize: function(courseModuleId) {\n parameters.courseModuleId = courseModuleId;\n registerListener('.capquiz-question-rating input', submitQuestionRating);\n registerListener('.capquiz-default-question-rating input', submitDefaultQuestionRating);\n fixTabIndicesForQuestionRatingInputs();\n registerSortListener();\n listenAddToQuiz();\n }\n };\n\n});\n"],"names":["define","$","parameters","courseModuleId","sendAction","data","onSuccess","onError","ajax","type","url","success","error","sendDefaultQuestionRating","rating","sendQuestionRating","questionId","submitInput","$input","sendInput","$indicator","next","css","val","submitQuestionRating","submitDefaultQuestionRating","registerListener","query","submit","document","on","event","target","sortTable","$header","column","index","$table","parent","$rows","find","toArray","sort","rowA","rowB","$colA","children","eq","$colB","parseInt","text","append","$itemA","$itemB","valA","valB","length","html","isNumeric","toString","localeCompare","ascending","iconName","each","this","remove","prepend","reverse","i","initialize","object","attr","questionIds","slice","post","location","reload"],"mappings":";;;;;;AAsBAA,oCAAO,CAAC,WAAW,SAASC,OAEpBC,WAAa,CACbC,eAAgB,YASXC,WAAWC,KAAMC,UAAWC,SACjCN,EAAEO,KAAK,CACHC,KAAM,OACNC,IAAK,aACLL,KAAMA,KACNM,QAASL,UACTM,MAAOL,mBAWNM,0BAA0BR,KAAMS,OAAQR,UAAWC,SACxDH,WAAW,QACG,iCACJF,WAAWC,sBACPW,QACXR,UAAWC,kBAUTQ,mBAAmBV,KAAMS,OAAQR,UAAWC,SACjDH,WAAW,QACG,yBACJF,WAAWC,6BACFE,KAAKW,kBACVF,QACXR,UAAWC,kBASTU,YAAYC,OAAQC,UAAWd,MACpCa,OAAOb,KAAK,UAAU,GACtBa,OAAOb,KAAK,SAAS,OACjBe,WAAaF,OAAOG,OACxBD,WAAWE,IAAI,QAAS,QACxBH,UAAUd,KAAMa,OAAOK,OAAO,YACG,IAAzBL,OAAOb,KAAK,SACZY,YAAYC,OAAQC,UAAWd,OAE/Be,WAAWE,IAAI,QAAS,SACxBJ,OAAOb,KAAK,SAAS,GACrBa,OAAOb,KAAK,UAAU,OAE3B,WACCe,WAAWE,IAAI,QAAS,mBAQvBE,qBAAqBN,QAC1BD,YAAYC,OAAQH,mBAAoB,CAACC,WAAYE,OAAOb,KAAK,0BAO5DoB,4BAA4BP,QACjCD,YAAYC,OAAQL,0BAA2B,eAQ1Ca,iBAAiBC,MAAOC,QAC7B3B,EAAE4B,UAAUC,GAAG,QAASH,OAAO,SAASI,WAChCb,OAASjB,EAAE8B,MAAMC,SAEA,IADFd,OAAOb,KAAK,UAK/BuB,OAAOV,QAHHA,OAAOb,KAAK,SAAS,eAmBxB4B,UAAUC,eACTC,OAASD,QAAQE,QACjBC,OAASH,QAAQI,SAASA,aAC5BC,MAAQF,OAAOG,KAAK,YAAYC,UAAUC,MAAK,SAASC,KAAMC,YACxDC,MAAQ5C,EAAE0C,MAAMG,SAAS,MAAMC,GAAG,GAClCC,MAAQ/C,EAAE2C,MAAME,SAAS,MAAMC,GAAG,UACjCE,SAASJ,MAAMK,QAAUD,SAASD,MAAME,WAEnDb,OAAOc,OAAOZ,OACdA,MAAQF,OAAOG,KAAK,YAAYC,UAAUC,MAAK,SAASC,KAAMC,YACpDC,MAAQ5C,EAAE0C,MAAMG,SAAS,MAAMC,GAAGZ,QAClCa,MAAQ/C,EAAE2C,MAAME,SAAS,MAAMC,GAAGZ,QAClCiB,OAASP,MAAML,KAAK,0BACpBa,OAASL,MAAMR,KAAK,8BACtBc,KAMAC,YAJAD,KADkB,IAAlBF,OAAOI,OACAX,MAAMY,OAEkB,IAAxBL,OAAO7B,MAAMiC,OAAeJ,OAAOK,OAASL,OAAO7B,MAI1DgC,KADkB,IAAlBF,OAAOG,OACAR,MAAMS,OAEkB,IAAxBJ,OAAO9B,MAAMiC,OAAeH,OAAOI,OAASJ,OAAO9B,MAE1DtB,EAAEyD,UAAUJ,OAASrD,EAAEyD,UAAUH,MAC1BD,KAAOC,KAEPD,KAAKK,WAAWC,cAAcL,eAGvCM,UAAoC,SAAvBxB,OAAOhC,KAAK,OAC/BgC,OAAOhC,KAAK,MAAOwD,UAAY,QAAU,cACnCC,SAAYD,UAAY,cAAgB,gBAC9C5D,EAAE8D,KAAK1B,OAAOG,KAAK,sBAAsB,WACrCvC,EAAE+D,MAAMxB,KAAK,OAAOyB,YAExB/B,QAAQgC,QAAQ,gBAAkBJ,SAAW,UACxCD,YACDtB,MAAQA,MAAM4B,WAElB9B,OAAOc,OAAOZ,WACV6B,EAAI,EACR/B,OAAOG,KAAK,YAAYuB,MAAK,WACzB9D,EAAE+D,MAAMxB,KAAK,kBAAkBiB,KAAKW,GACpCA,aAgDD,CACHC,WAAY,SAASlE,gBACjBD,WAAWC,eAAiBA,eAC5BuB,iBAAiB,iCAAkCF,sBACnDE,iBAAiB,yCAA0CD,6BA5B/DxB,EAAE,kDAAkD8D,MAAK,SAAS3B,MAAOkC,QACrErE,EAAEqE,QAAQC,KAAK,YAAa,MAjBhCtE,EAAE4B,UAAUC,GAAG,QAAS,qBAAqB,WACzCG,UAAUhC,EAAE+D,UAEhB/D,EAAE,iCAAiC8D,MAAK,WACpC9B,UAAUhC,EAAE+D,OACZ/B,UAAUhC,EAAE+D,UAEhB/D,EAAE,kCAAkC8D,MAAK,WACrC9B,UAAUhC,EAAE+D,UAiBhB/D,EAAE,mCAAmC6B,GAAG,SAAS,eACzC0C,YAAc,GAClBvE,EAAE,sDAAsD8D,MAAK,WACzDS,aAAevE,EAAE+D,MAAMO,KAAK,QAAQE,MAAM,GAAK,OAEnDxE,EAAEyE,KAAK,aAAc,QACP,kBACJxE,WAAWC,6BACFqE,cAChB,WACCG,SAASC"} \ No newline at end of file diff --git a/amd/src/edit_questions.js b/amd/src/edit_questions.js index d8971ca..a2984f4 100755 --- a/amd/src/edit_questions.js +++ b/amd/src/edit_questions.js @@ -143,30 +143,40 @@ define(['jquery'], function($) { * @param {Object} $header The header column for which to sort the table by. */ function sortTable($header) { - var column = $header.index(); - var $table = $header.parent().parent(); - var $rows = $table.find('tr:gt(0)').toArray().sort(function(rowA, rowB) { - var $colA = $(rowA).children('td').eq(0); - var $colB = $(rowB).children('td').eq(0); + const column = $header.index(); + const $table = $header.parent().parent(); + let $rows = $table.find('tr:gt(0)').toArray().sort(function(rowA, rowB) { + const $colA = $(rowA).children('td').eq(0); + const $colB = $(rowB).children('td').eq(0); return parseInt($colA.text()) - parseInt($colB.text()); }); $table.append($rows); $rows = $table.find('tr:gt(0)').toArray().sort(function(rowA, rowB) { - var $colA = $(rowA).children('td').eq(column); - var $colB = $(rowB).children('td').eq(column); - var $itemA = $colA.find('.capquiz-sortable-item'); - var $itemB = $colB.find('.capquiz-sortable-item'); - var valA = ($itemA.length === 0 ? $colA.html() : ($itemA.val().length === 0 ? $itemA.html() : $itemA.val())); - var valB = ($itemB.length === 0 ? $colB.html() : ($itemB.val().length === 0 ? $itemB.html() : $itemB.val())); + const $colA = $(rowA).children('td').eq(column); + const $colB = $(rowB).children('td').eq(column); + const $itemA = $colA.find('.capquiz-sortable-item'); + const $itemB = $colB.find('.capquiz-sortable-item'); + let valA; + if ($itemA.length === 0) { + valA = $colA.html(); + } else { + valA = $itemA.val().length === 0 ? $itemA.html() : $itemA.val(); + } + let valB; + if ($itemB.length === 0) { + valB = $colB.html(); + } else { + valB = $itemB.val().length === 0 ? $itemB.html() : $itemB.val(); + } if ($.isNumeric(valA) && $.isNumeric(valB)) { return valA - valB; } else { return valA.toString().localeCompare(valB); } }); - var ascending = ($table.data('asc') === 'true'); + const ascending = ($table.data('asc') === 'true'); $table.data('asc', ascending ? 'false' : 'true'); - var iconName = (ascending ? 'fa-arrow-up' : 'fa-arrow-down'); + const iconName = (ascending ? 'fa-arrow-up' : 'fa-arrow-down'); $.each($table.find('.capquiz-sortable'), function() { $(this).find('.fa').remove(); }); @@ -175,7 +185,7 @@ define(['jquery'], function($) { $rows = $rows.reverse(); } $table.append($rows); - var i = 1; + let i = 1; $table.find('tr:gt(0)').each(function() { $(this).find('td:first-child').html(i); i++; diff --git a/backup/moodle2/backup_capquiz_activity_task.class.php b/backup/moodle2/backup_capquiz_activity_task.class.php index 2d1bbba..7319225 100644 --- a/backup/moodle2/backup_capquiz_activity_task.class.php +++ b/backup/moodle2/backup_capquiz_activity_task.class.php @@ -53,10 +53,11 @@ protected function define_my_steps() { /** * Code the transformations to perform in the activity in order to get transportable (encoded) links. + * * @param string $content * @return string of content with the URLs encoded */ - public static function encode_content_links($content) { + public static function encode_content_links($content): string { global $CFG; $base = preg_quote($CFG->wwwroot, '/'); // Link to the list of CAPQuizzes. diff --git a/backup/moodle2/backup_capquiz_stepslib.php b/backup/moodle2/backup_capquiz_stepslib.php index d45cf1f..0bd25a8 100644 --- a/backup/moodle2/backup_capquiz_stepslib.php +++ b/backup/moodle2/backup_capquiz_stepslib.php @@ -35,43 +35,83 @@ class backup_capquiz_activity_structure_step extends backup_questions_activity_s */ protected function define_structure() { $capquiz = new backup_nested_element('capquiz', ['id'], [ - 'name', 'intro', 'introformat', 'timecreated', 'timemodified', 'published', 'default_user_rating' + 'name', + 'intro', + 'introformat', + 'timecreated', + 'timemodified', + 'published', + 'default_user_rating', ]); $questionlist = new backup_nested_element('questionlist', null, [ - 'id', 'capquiz_id', 'title', 'author', 'description', - 'star_ratings', 'is_template', 'time_created', 'time_modified', 'default_question_rating' + 'id', + 'capquiz_id', + 'title', + 'author', + 'description', + 'star_ratings', + 'is_template', + 'time_created', + 'time_modified', + 'default_question_rating', ]); $questions = new backup_nested_element('questions'); $question = new backup_nested_element('question', ['id'], [ - 'question_id', 'question_list_id', 'rating' + 'question_id', + 'question_list_id', + 'rating', ]); $questionratings = new backup_nested_element('questionratings'); $questionrating = new backup_nested_element('question_rating', ['id'], [ - 'capquiz_question_id', 'rating', 'manual', 'timecreated' + 'capquiz_question_id', + 'rating', + 'manual', + 'timecreated', ]); $questionselections = new backup_nested_element('questionselections'); $questionselection = new backup_nested_element('questionselection', ['id'], [ - 'capquiz_id', 'strategy', 'configuration' + 'capquiz_id', + 'strategy', + 'configuration', ]); $ratingsystems = new backup_nested_element('ratingsystems'); $ratingsystem = new backup_nested_element('ratingsystem', ['id'], [ - 'capquiz_id', 'rating_system', 'configuration' + 'capquiz_id', + 'rating_system', + 'configuration', ]); $users = new backup_nested_element('users'); $user = new backup_nested_element('user', ['id'], [ - 'user_id', 'capquiz_id', 'question_usage_id', 'rating', 'highest_level' + 'user_id', + 'capquiz_id', + 'question_usage_id', + 'rating', + 'highest_level', ]); $this->add_question_usages($user, 'question_usage_id'); $userratings = new backup_nested_element('userratings'); $userrating = new backup_nested_element('user_rating', ['id'], [ - 'capquiz_user_id', 'rating', 'manual', 'timecreated' + 'capquiz_user_id', + 'rating', + 'manual', + 'timecreated', ]); $attempts = new backup_nested_element('attempts'); $attempt = new backup_nested_element('attempt', ['id'], [ - 'slot', 'user_id', 'question_id', 'reviewed', 'answered', 'time_answered', 'time_reviewed', - 'question_rating_id', 'question_prev_rating_id', 'prev_question_rating_id', - 'prev_question_prev_rating_id', 'user_rating_id', 'user_prev_rating_id' + 'slot', + 'user_id', + 'question_id', + 'reviewed', + 'answered', + 'time_answered', + 'time_reviewed', + 'question_rating_id', + 'question_prev_rating_id', + 'prev_question_rating_id', + 'prev_question_prev_rating_id', + 'user_rating_id', + 'user_prev_rating_id', ]); // Build the tree. diff --git a/backup/moodle2/restore_capquiz_activity_task.class.php b/backup/moodle2/restore_capquiz_activity_task.class.php index 6b65421..686145b 100644 --- a/backup/moodle2/restore_capquiz_activity_task.class.php +++ b/backup/moodle2/restore_capquiz_activity_task.class.php @@ -49,35 +49,31 @@ protected function define_my_steps() { } /** - * Define the contents in the activity that must be - * processed by the link decoder + * Define the contents in the activity that must be processed by the link decoder * * @return restore_decode_content[] */ public static function define_decode_contents() { return [ - new restore_decode_content('capquiz', ['intro']) + new restore_decode_content('capquiz', ['intro']), ]; } /** - * Define the decoding rules for links belonging - * to the activity to be executed by the link decoder + * Define the decoding rules for links belonging to the activity to be executed by the link decoder * * @return restore_decode_rule[] */ public static function define_decode_rules() { return [ new restore_decode_rule('CAPQUIZVIEWBYID', '/mod/capquiz/view.php?id=$1', 'course_module'), - new restore_decode_rule('CAPQUIZINDEX', '/mod/capquiz/index.php?id=$1', 'course') + new restore_decode_rule('CAPQUIZINDEX', '/mod/capquiz/index.php?id=$1', 'course'), ]; } /** - * Define the restore log rules that will be applied - * by the {@see restore_logs_processor} when restoring - * course logs. It must return one array - * of {@see restore_log_rule} objects + * Define the restore log rules that will be applied by the {@see restore_logs_processor} when restoring + * course logs. It must return one array of {@see restore_log_rule} objects * * @return restore_log_rule[] */ @@ -86,14 +82,10 @@ public static function define_restore_log_rules() { } /** - * Define the restore log rules that will be applied - * by the {@see restore_logs_processor} - * when restoring - * course logs. It must return one array - * of {@see restore_log_rule} objects + * Define the restore log rules that will be applied by the {@see restore_logs_processor} when restoring + * course logs. It must return one array of {@see restore_log_rule} objects * - * Note this rules are applied when restoring course logs - * by the restore final task, but are defined here at + * Note this rules are applied when restoring course logs by the restore final task, but are defined here at * activity level. All them are rules not linked to any module instance (cmid = 0) * * @return restore_log_rule[] diff --git a/backup/moodle2/restore_capquiz_stepslib.php b/backup/moodle2/restore_capquiz_stepslib.php index 2ba2d4a..ff80470 100644 --- a/backup/moodle2/restore_capquiz_stepslib.php +++ b/backup/moodle2/restore_capquiz_stepslib.php @@ -62,9 +62,6 @@ protected function define_structure() { * Processes and backs up capquiz * * @param object $data - * @throws base_step_exception - * @throws dml_exception - * @throws restore_step_exception */ protected function process_capquiz($data) { global $DB; @@ -82,9 +79,6 @@ protected function process_capquiz($data) { * Processes and backs up capquiz question list * * @param object $data - * @throws base_step_exception - * @throws dml_exception - * @throws restore_step_exception */ protected function process_capquiz_question_list($data) { global $DB; @@ -102,8 +96,6 @@ protected function process_capquiz_question_list($data) { * Processes and backs up capquiz questions * * @param object $data - * @throws dml_exception - * @throws restore_step_exception */ protected function process_capquiz_question($data) { global $DB; @@ -122,8 +114,6 @@ protected function process_capquiz_question($data) { * Processes and backs up capquiz question rating * * @param object $data - * @throws dml_exception - * @throws restore_step_exception */ protected function process_capquiz_question_rating($data) { global $DB; @@ -138,8 +128,6 @@ protected function process_capquiz_question_rating($data) { * Processes and backs up capquiz question selection * * @param object $data - * @throws dml_exception - * @throws restore_step_exception */ protected function process_capquiz_question_selection($data) { global $DB; @@ -154,8 +142,6 @@ protected function process_capquiz_question_selection($data) { * Processes and backs up capquiz question rating system * * @param object $data - * @throws dml_exception - * @throws restore_step_exception */ protected function process_capquiz_rating_system($data) { global $DB; @@ -182,8 +168,6 @@ protected function process_capquiz_user($data) { * Processes and backs up capquiz user rating * * @param object $data - * @throws dml_exception - * @throws restore_step_exception */ protected function process_capquiz_user_rating($data) { global $DB; @@ -198,8 +182,6 @@ protected function process_capquiz_user_rating($data) { * Processes and backs up capquiz question attempt * * @param object $data - * @throws dml_exception - * @throws restore_step_exception */ protected function process_capquiz_attempt($data) { global $DB; @@ -221,8 +203,6 @@ protected function process_capquiz_attempt($data) { * Updates a users usageid and maps the users old and new ids * * @param int $newusageid - * @throws dml_exception - * @throws restore_step_exception */ protected function inform_new_usage_id($newusageid) { global $DB; diff --git a/classes/bank/add_action_column.php b/classes/bank/add_action_column.php deleted file mode 100644 index 028bfe5..0000000 --- a/classes/bank/add_action_column.php +++ /dev/null @@ -1,66 +0,0 @@ -. - -namespace mod_capquiz\bank; - -/** - * A column type for the add this question to the quiz action. - * - * This class is copied to CAPQuiz from the Core Quiz, without - * modification (as of Fri 9 Sep 08:29:48 UTC 2022 ). - * - * @package mod_capquiz - * @category question - * @copyright 2009 Tim Hunt - * @author 2021 Safat Shahin - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class add_action_column extends \core_question\local\bank\action_column_base { - - /** @var string caches a lang string used repeatedly. */ - protected $stradd; - - /** - * A chance for subclasses to initialise themselves, for example to load lang strings, - * without having to override the constructor. - */ - public function init(): void { - parent::init(); - $this->stradd = get_string('addtoquiz', 'quiz'); - } - - /** - * Get the internal name for this column. Used as a CSS class name, - * and to store information about the current sort. Must match PARAM_ALPHA. - * - * @return string column name. - */ - public function get_name() { - return 'addtoquizaction'; - } - - /** - * Output the contents of this column. - * @param object $question the row from the $question table, augmented with extra information. - * @param string $rowclasses CSS class names that should be applied to this row of output. - */ - protected function display_content($question, $rowclasses) { - if (!question_has_capability_on($question, 'use')) { - return; - } - $this->print_icon('t/add', $this->stradd, $this->qbank->add_to_quiz_url($question->id)); - } -} diff --git a/classes/bank/add_to_quiz_action.php b/classes/bank/add_to_quiz_action.php new file mode 100644 index 0000000..6cb9496 --- /dev/null +++ b/classes/bank/add_to_quiz_action.php @@ -0,0 +1,46 @@ +. + +namespace mod_capquiz\bank; + +use mod_capquiz\capquiz_urls; +use stdClass; + +/** + * Question bank action to add question to quiz. + * + * @package mod_capquiz + * @copyright 2024 NTNU + * @author 2024 Sebastian Gundersen + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class add_to_quiz_action extends \core_question\local\bank\question_action_base { + /** + * Get the information required to display this action either as a menu item or a separate action column. + * + * @param stdClass $question the row from the $question table, augmented with extra information. + * @return array with three elements. + * $url - the URL to perform the action. + * $icon - the icon for this action. E.g. 't/delete'. + * $label - text label to display in the UI (either in the menu, or as a tool-tip on the icon) + */ + protected function get_url_icon_and_label(stdClass $question): array { + if (!question_has_capability_on($question, 'use')) { + return [null, null, null]; + } + return [capquiz_urls::add_question_to_list_url($question->id), 't/add', get_string('addtoquiz', 'quiz')]; + } +} diff --git a/classes/bank/question_bank_view.php b/classes/bank/question_bank_view.php index 19a4601..8fc8212 100755 --- a/classes/bank/question_bank_view.php +++ b/classes/bank/question_bank_view.php @@ -30,18 +30,7 @@ namespace mod_capquiz\bank; -use \core_question\local\bank\checkbox_column; -use \qbank_viewcreator\creator_name_column; -use \qbank_editquestion\edit_action_column; -use \qbank_deletequestion\delete_action_column; -use \qbank_previewquestion\preview_action_column; -use \qbank_viewquestionname\viewquestionname_column_helper; -use \qbank_viewquestiontype\question_type_column; -use \core_question\bank\search\tag_condition as tag_condition; -use \core_question\bank\search\hidden_condition as hidden_condition; -use \core_question\bank\search\category_condition; -use mod_capquiz\local\capquiz_urls; -use mod_capquiz\bank\add_action_column; +use context; /** * Class question_bank_view @@ -53,122 +42,26 @@ */ class question_bank_view extends \core_question\local\bank\view { - /** - * URL of add to quiz. - * - * @param int $questionid the question id - * @return \moodle_url - * @throws \coding_exception - * @throws \moodle_exception - */ - public function add_to_quiz_url($questionid) { - return \mod_capquiz\capquiz_urls::add_question_to_list_url($questionid); - } - - /** - * Get the list of qbank plugins with available objects for features. - * - * @return array - */ - protected function get_question_bank_plugins(): array { - $questionbankclasscolumns = []; - $corequestionbankcolumns = [ - 'add_action_column', - 'checkbox_column', - 'question_type_column', - 'question_name_text_column', - 'preview_action_column', - 'edit_action_column' - ]; - - if (question_get_display_preference('qbshowtext', 0, PARAM_BOOL, new \moodle_url(''))) { - $corequestionbankcolumns[] = 'question_text_row'; - } - - foreach ($corequestionbankcolumns as $fullname) { - $shortname = $fullname; - if (class_exists('mod_capquiz\\bank\\' . $fullname)) { - $fullname = 'mod_capquiz\\bank\\' . $fullname; - $questionbankclasscolumns[$shortname] = new $fullname($this); - } else if (class_exists('core_question\\local\\bank\\' . $fullname)) { - $fullname = 'core_question\\local\\bank\\' . $fullname; - $questionbankclasscolumns[$shortname] = new $fullname($this); - } else { - $questionbankclasscolumns[$shortname] = ''; - } - } - $plugins = \core_component::get_plugin_list_with_class('qbank', 'plugin_feature', 'plugin_feature.php'); - foreach ($plugins as $componentname => $plugin) { - $pluginentrypointobject = new $plugin(); - $plugincolumnobjects = $pluginentrypointobject->get_question_columns($this); - // Don't need the plugins without column objects. - if (empty($plugincolumnobjects)) { - unset($plugins[$componentname]); - continue; - } - foreach ($plugincolumnobjects as $columnobject) { - $columnname = $columnobject->get_column_name(); - foreach ($corequestionbankcolumns as $key => $corequestionbankcolumn) { - if (!\core\plugininfo\qbank::is_plugin_enabled($componentname)) { - unset($questionbankclasscolumns[$columnname]); - continue; - } - // Check if it has custom preference selector to view/hide. - if ($columnobject->has_preference() && !$columnobject->get_preference()) { - continue; - } - if ($corequestionbankcolumn === $columnname) { - $questionbankclasscolumns[$columnname] = $columnobject; - } - } - } - } - - // Mitigate the error in case of any regression. - foreach ($questionbankclasscolumns as $shortname => $questionbankclasscolumn) { - if (empty($questionbankclasscolumn)) { - unset($questionbankclasscolumns[$shortname]); - } - } - - return $questionbankclasscolumns; - } - /** * Specify the column heading - * - * @return string Column name for the heading */ protected function heading_column(): string { - return 'mod_capquiz\\bank\\question_name_text_column'; + return question_name_text_column::class; } /** - * Renders the html question bank (same as display, but returns the result). - * - * Note that you can only output this rendered result once per page, as - * it contains IDs which must be unique. + * Display button to add selected questions to the quiz. * - * @param array $pagevars - * @param string $tabname - * @return string HTML code for the form + * @param context $catcontext */ - public function render($pagevars, $tabname): string { - ob_start(); - $this->display($pagevars, $tabname); - $out = ob_get_contents(); - ob_end_clean(); - return $out; - } - - /** - * Displays the add selected questions button - * - * @throws \coding_exception - */ - private function display_add_selected_questions_button() { - $straddtoquiz = get_string('add_to_quiz', 'capquiz'); - echo ''; + protected function display_bottom_controls(context $catcontext): void { + echo '
'; + if (has_capability('moodle/question:useall', $catcontext)) { + echo ''; + } + echo '
'; } } diff --git a/classes/bank/question_name_column.php b/classes/bank/question_name_column.php index d4fd812..ec92b48 100644 --- a/classes/bank/question_name_column.php +++ b/classes/bank/question_name_column.php @@ -16,7 +16,7 @@ namespace mod_capquiz\bank; -use \html_writer; +use stdClass; /** * A column type for the name of the question name. @@ -59,10 +59,10 @@ public function get_title(): string { /** * Lable for this column. * - * @param object $question the row from the $question table, augmented with extra information. + * @param stdClass $question the row from the $question table, augmented with extra information. * @return string column label. */ - protected function label_for($question): string { + protected function label_for(stdClass $question): string { if (is_null($this->checkboxespresent)) { $this->checkboxespresent = $this->qbank->has_column('core_question\local\bank\checkbox_column'); } @@ -75,6 +75,7 @@ protected function label_for($question): string { /** * Output the contents of this column. + * * @param object $question the row from the $question table, augmented with extra information. * @param string $rowclasses CSS class names that should be applied to this row of output. */ diff --git a/classes/bank/question_name_text_column.php b/classes/bank/question_name_text_column.php index f2b0f73..e2b1f01 100644 --- a/classes/bank/question_name_text_column.php +++ b/classes/bank/question_name_text_column.php @@ -16,8 +16,10 @@ namespace mod_capquiz\bank; -use \html_writer; - +use core_tag_tag; +use html_writer; +use question_utils; +use stdClass; /** * A column type for the name followed by the start of the question text. @@ -26,7 +28,6 @@ * the `quiz_question_tostring` method copied from Core Quiz' locallib. * * @package mod_capquiz - * @package mod_capquiz * @category question * @copyright 2009 Tim Hunt * @author 2022 Hans Georg Schaathun @@ -37,28 +38,24 @@ class question_name_text_column extends question_name_column { /** * Get the internal name for this column. Used as a CSS class name, * and to store information about the current sort. Must match PARAM_ALPHA. - * - * @return string column name. */ public function get_name(): string { return 'questionnametext'; } - /** * Creates a textual representation of a question for display. * - * @param object $question A question object from the database questions table + * @param stdClass $question A question object from the database questions table * @param bool $showicon If true, show the question's icon with the question. False by default. * @param bool $showquestiontext If true (default), show question text after question name. * If false, show only question name. * @param bool $showidnumber If true, show the question's idnumber, if any. False by default. - * @param core_tag_tag[]|bool $showtags if array passed, show those tags. Else, if true, get and show tags, + * @param bool|core_tag_tag[] $showtags if array passed, show those tags. Else, if true, get and show tags, * else, don't show tags (which is the default). - * @return string HTML fragment. */ - protected function quiz_question_tostring($question, $showicon = false, $showquestiontext = true, - $showidnumber = false, $showtags = false) { + protected function quiz_question_tostring(stdClass $question, bool $showicon = false, bool $showquestiontext = true, + bool $showidnumber = false, array|bool $showtags = false): string { global $OUTPUT; $result = ''; @@ -71,9 +68,11 @@ protected function quiz_question_tostring($question, $showicon = false, $showque // Question idnumber. if ($showidnumber && $question->idnumber !== null && $question->idnumber !== '') { - $result .= ' ' . html_writer::span( - html_writer::span(get_string('idnumber', 'question'), 'accesshide') . - ' ' . s($question->idnumber), 'badge badge-primary'); + $result .= ' '; + $result .= html_writer::span( + html_writer::span(get_string('idnumber', 'question'), 'accesshide') + . ' ' . s($question->idnumber), 'badge badge-primary' + ); } // Question tags. @@ -90,8 +89,8 @@ protected function quiz_question_tostring($question, $showicon = false, $showque // Question text. if ($showquestiontext) { - $questiontext = \question_utils::to_plain_text($question->questiontext, - $question->questiontextformat, array('noclean' => true, 'para' => false)); + $questiontext = question_utils::to_plain_text($question->questiontext, + $question->questiontextformat, ['noclean' => true, 'para' => false]); $questiontext = shorten_text($questiontext, 50); if ($questiontext) { $result .= ' ' . html_writer::span(s($questiontext), 'questiontext'); @@ -107,23 +106,21 @@ protected function quiz_question_tostring($question, $showicon = false, $showque * @param string $rowclasses CSS class names that should be applied to this row of output. */ protected function display_content($question, $rowclasses): void { - echo \html_writer::start_tag('div'); + echo html_writer::start_tag('div'); $labelfor = $this->label_for($question); if ($labelfor) { - echo \html_writer::start_tag('label', ['for' => $labelfor]); + echo html_writer::start_tag('label', ['for' => $labelfor]); } echo $this->quiz_question_tostring($question, false, true, true, $question->tags); if ($labelfor) { - echo \html_writer::end_tag('label'); + echo html_writer::end_tag('label'); } - echo \html_writer::end_tag('div'); + echo html_writer::end_tag('div'); } /** * Use table alias 'q' for the question table, or one of the * ones from get_extra_joins. Every field requested must specify a table prefix. - * - * @return array fields required. */ public function get_required_fields(): array { $fields = parent::get_required_fields(); @@ -140,9 +137,9 @@ public function get_required_fields(): array { * Probably a good idea to check that another column has not already * loaded the data you want. * - * @param \stdClass[] $questions the questions that will be displayed. + * @param stdClass[] $questions the questions that will be displayed. */ - public function load_additional_data(array $questions) { + public function load_additional_data(array $questions): void { parent::load_additional_data($questions); parent::load_question_tags($questions); } diff --git a/classes/capquiz.php b/classes/capquiz.php index 044aff1..23a849e 100755 --- a/classes/capquiz.php +++ b/classes/capquiz.php @@ -26,6 +26,11 @@ namespace mod_capquiz; +use context_module; +use moodle_page; +use renderer_base; +use stdClass; + defined('MOODLE_INTERNAL') || die(); require_once($CFG->libdir . '/questionlib.php'); @@ -43,37 +48,36 @@ */ class capquiz { - /** @var \context_module $context */ + /** @var context_module $context */ private $context; - /** @var \stdClass $cm */ + /** @var stdClass $cm */ private $cm; - /** @var \stdClass $courserecord */ + /** @var stdClass $courserecord */ private $courserecord; - /** @var \stdClass $record */ + /** @var stdClass $record */ private $record; - /** @var \renderer_base|output\renderer $renderer */ - private $renderer; + /** @var renderer_base $renderer */ + private renderer_base $renderer; - /** @var capquiz_question_list $qlist */ - private $qlist; + /** @var ?capquiz_question_list $qlist */ + private ?capquiz_question_list $qlist; - /** @var \moodle_page $page */ - private $page; + /** @var moodle_page $page */ + private moodle_page $page; /** - * capquiz constructor. + * Constructor. + * * @param int $cmid - * @throws \coding_exception - * @throws \dml_exception */ public function __construct(int $cmid) { global $DB, $PAGE; $this->cm = get_coursemodule_from_id('capquiz', $cmid, 0, false, MUST_EXIST); - $this->context = \context_module::instance($cmid); + $this->context = context_module::instance($cmid); $PAGE->set_context($this->context); $this->renderer = $PAGE->get_renderer('mod_capquiz'); $this->courserecord = $DB->get_record('course', ['id' => $this->cm->course], '*', MUST_EXIST); @@ -87,7 +91,7 @@ public function __construct(int $cmid) { * * @param bool $force */ - public function update_grades(bool $force = false) { + public function update_grades(bool $force = false): void { if (!$this->is_grading_completed() || $force) { capquiz_update_grades($this->record); } @@ -95,64 +99,50 @@ public function update_grades(bool $force = false) { /** * Returns the page of the CapQuiz - * - * @return mixed|\moodle_page */ - public function get_page() { + public function get_page(): moodle_page { return $this->page; } /** * Returns the capquiz' id - * - * @return int */ - public function id() : int { + public function id(): int { return $this->record->id; } /** * Returns the capquiz' name - * - * @return string */ - public function name() : string { + public function name(): string { return $this->record->name; } /** * Returns true if the capquiz is published - * - * @return bool */ - public function is_published() : bool { + public function is_published(): bool { return $this->record->published; } /** * Returns true if the capquiz is completely graded - * - * @return bool */ - public function is_grading_completed() : bool { + public function is_grading_completed(): bool { return $this->record->timedue < time() && $this->record->timedue > 0; } /** * Returns the amount of stars needed to pass - * - * @return int */ - public function stars_to_pass() : int { + public function stars_to_pass(): int { return $this->record->stars_to_pass; } /** * Returns the time when the quiz is due - * - * @return int */ - public function time_due() : int { + public function time_due(): int { return $this->record->timedue; } @@ -160,9 +150,8 @@ public function time_due() : int { * Sets a new value for stars to pass * * @param int $stars - * @throws \dml_exception */ - public function set_stars_to_pass(int $stars) { + public function set_stars_to_pass(int $stars): void { global $DB; $this->record->stars_to_pass = $stars; $DB->update_record('capquiz', $this->record); @@ -172,9 +161,8 @@ public function set_stars_to_pass(int $stars) { * Sets a new due time * * @param int $time - * @throws \dml_exception */ - public function set_time_due(int $time) { + public function set_time_due(int $time): void { global $DB; $this->record->timedue = $time; $DB->update_record('capquiz', $this->record); @@ -184,9 +172,8 @@ public function set_time_due(int $time) { * Sets a new default rating * * @param float $rating - * @throws \dml_exception */ - public function set_default_user_rating(float $rating) { + public function set_default_user_rating(float $rating): void { global $DB; $this->record->default_user_rating = $rating; $DB->update_record('capquiz', $this->record); @@ -194,11 +181,8 @@ public function set_default_user_rating(float $rating) { /** * Publishes the capquiz if it can publish it - * - * @return bool - * @throws \dml_exception */ - public function publish() : bool { + public function publish(): bool { global $DB; if (!$this->can_publish()) { return false; @@ -210,10 +194,8 @@ public function publish() : bool { /** * Returns true if the capquiz is publishable - * - * @return bool */ - public function can_publish() : bool { + public function can_publish(): bool { if (!$this->has_question_list() || $this->is_published()) { return false; } @@ -224,9 +206,8 @@ public function can_publish() : bool { * Returns a new question engine based on the user * * @param capquiz_user $user - * @return capquiz_question_engine|null */ - public function question_engine(capquiz_user $user) { + public function question_engine(capquiz_user $user): ?capquiz_question_engine { $quba = $user->question_usage(); if (!$quba) { return null; @@ -238,82 +219,65 @@ public function question_engine(capquiz_user $user) { /** * Returns the capquiz user - * - * @return capquiz_user - * @throws \Exception */ - public function user() : capquiz_user { + public function user(): ?capquiz_user { global $USER; return capquiz_user::load_user($this, $USER->id, $this->context()); } /** * Returns the default rating - * - * @return float */ - public function default_user_rating() : float { + public function default_user_rating(): float { return $this->record->default_user_rating; } /** * Returns true if the capquiz has a question list - * - * @return bool */ - public function has_question_list() : bool { + public function has_question_list(): bool { return $this->qlist !== null; } /** * Returns the quiz' question list - * - * @return capquiz_question_list|null */ - public function question_list() { + public function question_list(): ?capquiz_question_list { return $this->qlist; } /** * Returns the current context - * - * @return \context_module */ - public function context() : \context_module { + public function context(): context_module { return $this->context; } /** * Returns teh current course module - * - * @return \stdClass */ - public function course_module() : \stdClass { + public function course_module(): stdClass { return $this->cm; } /** * Returns the current course - * - * @return \stdClass */ - public function course() : \stdClass { + public function course(): stdClass { return $this->courserecord; } /** * Returns the current renderer - * - * @return \renderer_base */ - public function renderer() : \renderer_base { + public function renderer(): renderer_base { return $this->renderer; } /** * Validates the matchmaking and rating systems */ - public function validate_matchmaking_and_rating_systems() { + public function validate_matchmaking_and_rating_systems(): void { $ratingsystemloader = new capquiz_rating_system_loader($this); if (!$ratingsystemloader->has_rating_system()) { $ratingsystemloader->set_default_rating_system(); diff --git a/classes/capquiz_action_performer.php b/classes/capquiz_action_performer.php index 9fa7414..8e5e304 100755 --- a/classes/capquiz_action_performer.php +++ b/classes/capquiz_action_performer.php @@ -26,6 +26,8 @@ namespace mod_capquiz; +use stdClass; + defined('MOODLE_INTERNAL') || die(); require_once($CFG->libdir . '/questionlib.php'); @@ -48,9 +50,8 @@ class capquiz_action_performer { * * @param string $action The action to perform * @param capquiz $capquiz The capquiz on which the action will be performed - * @throws \Exception */ - public static function perform(string $action, capquiz $capquiz) { + public static function perform(string $action, capquiz $capquiz): void { switch ($action) { case 'redirect': self::redirect(); @@ -93,11 +94,8 @@ public static function perform(string $action, capquiz $capquiz) { /** * Redirects the user to another page - * - * @throws \coding_exception - * @throws \moodle_exception */ - public static function redirect() { + public static function redirect(): void { $url = optional_param('target-url', null, PARAM_TEXT); if ($url) { capquiz_urls::redirect_to_url(new \moodle_url($url)); @@ -108,12 +106,10 @@ public static function redirect() { * Assigns a question list to the capquiz * * @param capquiz $capquiz - * @throws \coding_exception - * @throws \dml_exception */ - public static function assign_question_list(capquiz $capquiz) { + public static function assign_question_list(capquiz $capquiz): void { $qlistid = optional_param('question-list-id', 0, PARAM_INT); - $qlist = capquiz_question_list::load_any($qlistid, $capquiz->context()); + $qlist = capquiz_question_list::load_any($qlistid); if ($qlist) { $capquiz->validate_matchmaking_and_rating_systems(); $qlist->create_instance_copy($capquiz); @@ -124,9 +120,8 @@ public static function assign_question_list(capquiz $capquiz) { * Adds questions from the capquiz' question to the capquiz * * @param capquiz $capquiz - * @throws \coding_exception */ - public static function add_question_to_list(capquiz $capquiz) { + public static function add_question_to_list(capquiz $capquiz): void { $qlist = $capquiz->question_list(); $questionids = required_param('question-id', PARAM_TEXT); $questionids = explode(',', $questionids); @@ -140,9 +135,8 @@ public static function add_question_to_list(capquiz $capquiz) { * Removes a question * * @param capquiz $capquiz - * @throws \coding_exception */ - public static function remove_question_from_list(capquiz $capquiz) { + public static function remove_question_from_list(capquiz $capquiz): void { $questionid = optional_param('question-id', 0, PARAM_INT); if ($questionid && $capquiz->has_question_list()) { self::remove_capquiz_question($questionid, $capquiz->question_list()->id()); @@ -154,9 +148,8 @@ public static function remove_question_from_list(capquiz $capquiz) { * Publishes the capquiz * * @param capquiz $capquiz - * @throws \dml_exception */ - public static function publish_capquiz(capquiz $capquiz) { + public static function publish_capquiz(capquiz $capquiz): void { $capquiz->publish(); } @@ -164,9 +157,8 @@ public static function publish_capquiz(capquiz $capquiz) { * Sets a new question rating on a question * * @param capquiz $capquiz - * @throws \coding_exception */ - public static function set_question_rating(capquiz $capquiz) { + public static function set_question_rating(capquiz $capquiz): void { $questionid = required_param('question-id', PARAM_INT); $question = $capquiz->question_list()->question($questionid); if (!$question) { @@ -183,10 +175,8 @@ public static function set_question_rating(capquiz $capquiz) { * Sets a new default question rating * * @param capquiz $capquiz - * @throws \coding_exception - * @throws \dml_exception */ - public static function set_default_question_rating(capquiz $capquiz) { + public static function set_default_question_rating(capquiz $capquiz): void { $rating = optional_param('rating', null, PARAM_FLOAT); if ($rating !== null) { $capquiz->question_list()->set_default_question_rating($rating); @@ -199,9 +189,8 @@ public static function set_default_question_rating(capquiz $capquiz) { * * @param capquiz $capquiz * @return capquiz_question_list - * @throws \Exception */ - public static function create_question_list_template(capquiz $capquiz) { + public static function create_question_list_template(capquiz $capquiz): capquiz_question_list { $qlist = $capquiz->question_list(); if (!$qlist) { throw new \Exception('Failed to find question list for this CAPQuiz.'); @@ -221,14 +210,13 @@ public static function create_question_list_template(capquiz $capquiz) { * @param int $questionid * @param capquiz_question_list $list * @param float $rating - * @throws \dml_exception */ - private static function create_capquiz_question(int $questionid, capquiz_question_list $list, float $rating) { + private static function create_capquiz_question(int $questionid, capquiz_question_list $list, float $rating): void { global $DB; if ($questionid === 0) { return; } - $ratedquestion = new \stdClass(); + $ratedquestion = new stdClass(); $ratedquestion->question_list_id = $list->id(); $ratedquestion->question_id = $questionid; $ratedquestion->rating = $rating; @@ -241,9 +229,8 @@ private static function create_capquiz_question(int $questionid, capquiz_questio * * @param int $questionid * @param int $qlistid - * @throws \dml_exception */ - private static function remove_capquiz_question(int $questionid, int $qlistid) { + private static function remove_capquiz_question(int $questionid, int $qlistid): void { global $DB; $DB->delete_records('capquiz_question', ['id' => $questionid, 'question_list_id' => $qlistid]); } @@ -252,26 +239,21 @@ private static function remove_capquiz_question(int $questionid, int $qlistid) { * Merges the capquiz' question list to its current context * * @param capquiz $capquiz - * @throws \coding_exception - * @throws \dml_exception */ - private static function merge_question_list(capquiz $capquiz) { + private static function merge_question_list(capquiz $capquiz): void { global $DB; $srcqlistid = required_param('qlistid', PARAM_INT); $srcqlistrecord = $DB->get_record('capquiz_question_list', ['id' => $srcqlistid]); if ($srcqlistrecord) { - $capquiz->question_list()->merge(new capquiz_question_list($srcqlistrecord, $capquiz->context())); + $capquiz->question_list()->merge(new capquiz_question_list($srcqlistrecord)); } capquiz_urls::redirect_to_url(capquiz_urls::view_question_list_url()); } /** * Deletes the question list and its questions from the database - * - * @throws \coding_exception - * @throws \dml_exception */ - private static function delete_question_list() { + private static function delete_question_list(): void { global $DB; $srcqlistid = required_param('qlistid', PARAM_INT); $DB->delete_records('capquiz_question', ['question_list_id' => $srcqlistid]); diff --git a/classes/capquiz_matchmaking_strategy.php b/classes/capquiz_matchmaking_strategy.php index 1d7a9a8..8736d33 100755 --- a/classes/capquiz_matchmaking_strategy.php +++ b/classes/capquiz_matchmaking_strategy.php @@ -25,6 +25,8 @@ namespace mod_capquiz; +use stdClass; + /** * Class capquiz_matchmaking_strategy * @@ -38,24 +40,19 @@ abstract class capquiz_matchmaking_strategy { /** * Sets a new matchmaking strategy configuration * - * @param \stdClass $configuration - * @return mixed + * @param stdClass $configuration */ - abstract public function configure(\stdClass $configuration); + abstract public function configure(stdClass $configuration): void; /** * Returns the current configuration - * - * @return mixed */ - abstract public function configuration(); + abstract public function configuration(): stdClass; /** * Returns the default configuration - * - * @return mixed */ - abstract public function default_configuration(); + abstract public function default_configuration(): stdClass; /** * Returns a new question for the user based on the matchmaking strategy configuration @@ -63,9 +60,8 @@ abstract public function default_configuration(); * @param capquiz_user $user * @param capquiz_question_list $qlist * @param array $inactiveattempts - * @return mixed */ abstract public function next_question_for_user(capquiz_user $user, capquiz_question_list $qlist, - array $inactiveattempts); + array $inactiveattempts): ?capquiz_question; } diff --git a/classes/capquiz_matchmaking_strategy_loader.php b/classes/capquiz_matchmaking_strategy_loader.php index 005b4c3..ee1d8cf 100755 --- a/classes/capquiz_matchmaking_strategy_loader.php +++ b/classes/capquiz_matchmaking_strategy_loader.php @@ -25,6 +25,9 @@ namespace mod_capquiz; +use moodle_url; +use stdClass; + defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/mod/capquiz/classes/matchmaking/capquiz_matchmaking_strategy_registry.php'); @@ -43,19 +46,20 @@ class capquiz_matchmaking_strategy_loader { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; - /** @var \stdClass $record */ - private $record; + /** @var ?stdClass $record */ + private ?stdClass $record = null; /** @var capquiz_matchmaking_strategy_registry $registry */ - private $registry; + private capquiz_matchmaking_strategy_registry $registry; - /** @var \stdClass $configuration */ - private $configuration; + /** @var ?stdClass $configuration */ + private ?stdClass $configuration; /** - * capquiz_matchmaking_strategy_loader constructor. + * Constructor. + * * @param capquiz $capquiz */ public function __construct(capquiz $capquiz) { @@ -68,35 +72,28 @@ public function __construct(capquiz $capquiz) { * Returns localized strategy name * * @param string $name - * @return \lang_string|string - * @throws \coding_exception */ - public static function localized_strategy_name($name) { + public static function localized_strategy_name(string $name): string { // TODO: This is a hack. The database records currently store the names, which makes localization hard. - switch ($name) { - case 'N-closest': - return get_string('n_closest', 'capquiz'); - case 'Chronological': - return get_string('chronological', 'capquiz'); - default: - return get_string('no_strategy_specified', 'capquiz'); - } + return match ($name) { + 'N-closest' => get_string('n_closest', 'capquiz'), + 'Chronological' => get_string('chronological', 'capquiz'), + default => get_string('no_strategy_specified', 'capquiz'), + }; } /** * Returns the selected strategy * - * @return capquiz_matchmaking_strategy|null - * @throws \Exception + * @return ?capquiz_matchmaking_strategy */ - public function selector() { + public function selector(): ?capquiz_matchmaking_strategy { if (!$this->record) { return null; } $strategy = $this->registry->selector($this->record->strategy); - $config = $this->configuration; - if ($config) { - $strategy->configure($config); + if ($this->configuration) { + $strategy->configure($this->configuration); } return $strategy; } @@ -104,11 +101,9 @@ public function selector() { /** * Returns configuration form for the current matchmaking strategy * - * @param \moodle_url $url - * @return mixed|null - * @throws \Exception + * @param moodle_url $url */ - public function configuration_form(\moodle_url $url) { + public function configuration_form(moodle_url $url): mixed { if ($this->record && $this->configuration) { return $this->registry->configuration_form($this->record->strategy, $this->configuration, $url); } @@ -117,21 +112,15 @@ public function configuration_form(\moodle_url $url) { /** * Returns true if this instance has a strategy set - * - * @return bool - * @throws \Exception */ - public function has_strategy() : bool { - return $this->selector() != null; + public function has_strategy(): bool { + return $this->selector() !== null; } /** * Returns the name of the current strategy - * - * @return string - * @throws \coding_exception */ - public function current_strategy_name() : string { + public function current_strategy_name(): string { if ($this->record) { return $this->record->strategy; } @@ -141,28 +130,23 @@ public function current_strategy_name() : string { /** * Configures teh current strategy * - * @param \stdClass $candidateconfig - * @throws \Exception + * @param stdClass $candidateconfig */ - public function configure_current_strategy(\stdClass $candidateconfig) { + public function configure_current_strategy(stdClass $candidateconfig): void { if (!$this->record) { return; } $selector = $this->selector(); $selector->configure($candidateconfig); - $configuration = $selector->configuration(); - if ($configuration) { - $this->record->configuration = $this->serialize($configuration); - } else { - $this->record->configuration = ''; - } + $config = $selector->configuration(); + $this->record->configuration = empty((array)$config) ? '' : $this->serialize($config); $this->update_configuration($this->record); } /** * Sets the default strategy */ - public function set_default_strategy() { + public function set_default_strategy(): void { $this->set_strategy($this->registry->default_selection_strategy()); } @@ -170,19 +154,14 @@ public function set_default_strategy() { * Sets strategy based on the strategy name * * @param string $strategy - * @throws \dml_exception */ - public function set_strategy(string $strategy) { + public function set_strategy(string $strategy): void { $selector = $this->registry->selector($strategy); - $record = new \stdClass; + $record = new stdClass; $record->strategy = $strategy; $record->capquiz_id = $this->capquiz->id(); $defaultconfig = $selector->default_configuration(); - if ($defaultconfig) { - $record->configuration = $this->serialize($defaultconfig); - } else { - $record->configuration = ''; - } + $record->configuration = empty((array)$defaultconfig) ? '' : $this->serialize($defaultconfig); global $DB; if ($this->record) { $record->id = $this->record->id; @@ -195,53 +174,44 @@ public function set_strategy(string $strategy) { /** * Loads the strategy configuration from the database - * - * @throws \dml_exception */ - private function load_configuration() { + private function load_configuration(): void { global $DB; $conditions = ['capquiz_id' => $this->capquiz->id()]; - $configuration = $DB->get_record('capquiz_question_selection', $conditions); - if ($configuration) { - $this->set_configuration($configuration); + $config = $DB->get_record('capquiz_question_selection', $conditions); + if ($config) { + $this->set_configuration($config); } } /** * Updates the strategy configuration and updates the database record * - * @param \stdClass $configuration - * @throws \dml_exception + * @param stdClass $config */ - private function update_configuration(\stdClass $configuration) { + private function update_configuration(stdClass $config): void { global $DB; - if ($DB->update_record('capquiz_question_selection', $configuration)) { - $this->set_configuration($configuration); + if ($DB->update_record('capquiz_question_selection', $config)) { + $this->set_configuration($config); } } /** * Sets this configuration as a new configuration * - * @param \stdClass $record + * @param stdClass $record */ - private function set_configuration(\stdClass $record) { + private function set_configuration(stdClass $record): void { $this->record = $record; - $configuration = $this->deserialize($record->configuration); - if ($configuration) { - $this->configuration = $configuration; - } else { - $this->configuration = null; - } + $this->configuration = $this->deserialize($record->configuration) ?: null; } /** * Returns the current configuration as a JSON string * - * @param \stdClass $configuration - * @return string + * @param stdClass $configuration */ - private function serialize(\stdClass $configuration) : string { + private function serialize(stdClass $configuration): string { return json_encode($configuration); } @@ -249,9 +219,8 @@ private function serialize(\stdClass $configuration) : string { * Takes in JSON encoded configuration string and returns a decoded configuration * * @param string $configuration - * @return mixed */ - private function deserialize(string $configuration) { + private function deserialize(string $configuration): mixed { return json_decode($configuration, false); } diff --git a/classes/capquiz_question.php b/classes/capquiz_question.php index dcf52ac..39bb865 100755 --- a/classes/capquiz_question.php +++ b/classes/capquiz_question.php @@ -26,6 +26,8 @@ namespace mod_capquiz; +use stdClass; + /** * Class capquiz_question * @@ -37,19 +39,18 @@ */ class capquiz_question { - /** @var \stdClass $record */ - private $record; + /** @var stdClass $record */ + private stdClass $record; /** @var capquiz_question_rating $rating */ - private $rating; + private capquiz_question_rating $rating; /** - * capquiz_question constructor. - * @param \stdClass $record - * @throws \coding_exception - * @throws \dml_exception + * Constructor. + * + * @param stdClass $record */ - public function __construct(\stdClass $record) { + public function __construct(stdClass $record) { global $DB; $this->record = $record; // TODO: This query should probably be done in question list. @@ -62,7 +63,7 @@ public function __construct(\stdClass $record) { $this->record->text = $this->record->name; } $rating = capquiz_question_rating::latest_question_rating_by_question($record->id); - if (is_null($rating)) { + if ($rating === null) { $this->rating = capquiz_question_rating::insert_question_rating_entry($this->id(), $this->rating()); } else { $this->rating = $rating; @@ -73,61 +74,45 @@ public function __construct(\stdClass $record) { * Loads a specific question from the database * * @param int $questionid - * @return capquiz_question|null - * @throws \coding_exception - * @throws \dml_exception */ - public static function load(int $questionid) { + public static function load(int $questionid): ?capquiz_question { global $DB; $record = $DB->get_record('capquiz_question', ['id' => $questionid]); - if ($record === false) { - return null; - } - return new capquiz_question($record); + return empty($record) ? null : new capquiz_question($record); } /** * Returns this questions database entry - * - * @return \stdClass */ - public function entry() : \stdClass { + public function entry(): stdClass { return $this->record; } /** * Returns this questions database entry id - * - * @return int */ - public function id() : int { + public function id(): int { return $this->record->id; } /** - * Returns this questions question id - * - * @return int + * Returns this question's question bank question id */ - public function question_id() : int { + public function question_id(): int { return $this->record->question_id; } /** * Returns the id of the question list this question is in - * - * @return int */ - public function question_list_id() : int { + public function question_list_id(): int { return $this->record->question_list_id; } /** * Returns this questions rating - * - * @return float */ - public function rating() : float { + public function rating(): float { return $this->record->rating; } @@ -136,33 +121,28 @@ public function rating() : float { * * @return capquiz_question_rating */ - public function get_capquiz_question_rating() : capquiz_question_rating { + public function get_capquiz_question_rating(): capquiz_question_rating { return $this->rating; } /** * Sets this questions rating and capquiz question rating * - * @param capquiz_question_rating $rating + * @param float $rating * @param bool $manual - * @throws \dml_exception */ - public function set_rating($rating, bool $manual = false) { + public function set_rating(float $rating, bool $manual = false) { global $DB; $this->record->rating = $rating; $DB->update_record('capquiz_question', $this->record); - $questionrating = capquiz_question_rating::create_question_rating($this, $rating, $manual); $this->rating = $questionrating; - } /** * Returns this questions name - * - * @return string */ - public function name() : string { + public function name(): string { return $this->record->name; } @@ -171,7 +151,7 @@ public function name() : string { * * @return string */ - public function text() : string { + public function text(): string { return $this->record->text; } @@ -181,7 +161,7 @@ public function text() : string { * @return int * @throws \dml_exception */ - public function course_id() : int { + public function course_id(): int { global $DB; $sql = 'SELECT c.id AS id FROM {capquiz_question} cq diff --git a/classes/capquiz_question_attempt.php b/classes/capquiz_question_attempt.php index 0e7a13b..6db66f2 100755 --- a/classes/capquiz_question_attempt.php +++ b/classes/capquiz_question_attempt.php @@ -25,6 +25,12 @@ namespace mod_capquiz; +use question_bank; +use question_engine; +use question_state; +use question_usage_by_activity; +use stdClass; + /** * Class capquiz_question_attempt * @@ -35,18 +41,19 @@ */ class capquiz_question_attempt { - /** @var \stdClass $record */ - private $record; + /** @var stdClass $record */ + private stdClass $record; - /** @var \question_usage_by_activity $quba */ - private $quba; + /** @var question_usage_by_activity $quba */ + private question_usage_by_activity $quba; /** - * capquiz_question_attempt constructor. - * @param \question_usage_by_activity $quba - * @param \stdClass $record + * Constructor. + * + * @param question_usage_by_activity $quba + * @param stdClass $record */ - public function __construct(\question_usage_by_activity $quba, \stdClass $record) { + public function __construct(question_usage_by_activity $quba, stdClass $record) { $this->record = $record; $this->quba = $quba; } @@ -56,19 +63,18 @@ public function __construct(\question_usage_by_activity $quba, \stdClass $record * * @param capquiz_user $user * @param capquiz_question $question - * @return capquiz_question_attempt|null */ - public static function create_attempt(capquiz_user $user, capquiz_question $question) { + public static function create_attempt(capquiz_user $user, capquiz_question $question): ?capquiz_question_attempt { $quba = $user->question_usage(); $questions = question_load_questions([$question->question_id()]); $targetquestion = reset($questions); if (!$targetquestion) { return null; } - $questiondefinition = \question_bank::make_question($targetquestion); + $questiondefinition = question_bank::make_question($targetquestion); $slot = $quba->add_question($questiondefinition); $quba->start_question($slot); - \question_engine::save_questions_usage_by_activity($quba); + question_engine::save_questions_usage_by_activity($quba); return self::insert_attempt_entry($user, $question, $slot); } @@ -76,19 +82,14 @@ public static function create_attempt(capquiz_user $user, capquiz_question $ques * Returns the users currently active attempt * * @param capquiz_user $user - * @return capquiz_question_attempt|null */ - public static function active_attempt(capquiz_user $user) { + public static function active_attempt(capquiz_user $user): ?capquiz_question_attempt { global $DB; - try { - $entry = $DB->get_record('capquiz_attempt', [ - 'user_id' => $user->id(), - 'reviewed' => false - ], '*', MUST_EXIST); - return new capquiz_question_attempt($user->question_usage(), $entry); - } catch (\dml_exception $e) { + $entry = $DB->get_record('capquiz_attempt', ['user_id' => $user->id(), 'reviewed' => false]); + if (empty($entry)) { return null; } + return new capquiz_question_attempt($user->question_usage(), $entry); } /** @@ -96,40 +97,30 @@ public static function active_attempt(capquiz_user $user) { * * @param capquiz_user $user * @param int $attemptid - * @return capquiz_question_attempt|null */ - public static function load_attempt(capquiz_user $user, int $attemptid) { + public static function load_attempt(capquiz_user $user, int $attemptid): ?capquiz_question_attempt { global $DB; - try { - $entry = $DB->get_record('capquiz_attempt', [ - 'id' => $attemptid, - 'user_id' => $user->id() - ], '*', MUST_EXIST); - return new capquiz_question_attempt($user->question_usage(), $entry); - } catch (\dml_exception $e) { + $entry = $DB->get_record('capquiz_attempt', ['id' => $attemptid, 'user_id' => $user->id()]); + if (empty($entry)) { return null; } + return new capquiz_question_attempt($user->question_usage(), $entry); } /** * Returns the users previous attempt * * @param capquiz_user $user - * @return capquiz_question_attempt|null */ - public static function previous_attempt(capquiz_user $user) { + public static function previous_attempt(capquiz_user $user): ?capquiz_question_attempt { global $DB; - try { - $sql = 'SELECT * - FROM {capquiz_attempt} - WHERE user_id = :userid - ORDER BY time_reviewed DESC - LIMIT 1'; - $attempt = $DB->get_record_sql($sql, ['userid' => $user->id()], MUST_EXIST); - return new capquiz_question_attempt($user->question_usage(), $attempt); - } catch (\dml_exception $e) { - return null; - } + $sql = 'SELECT * + FROM {capquiz_attempt} + WHERE user_id = :userid + ORDER BY time_reviewed DESC + LIMIT 1'; + $attempt = $DB->get_record_sql($sql, ['userid' => $user->id()], MUST_EXIST); + return new capquiz_question_attempt($user->question_usage(), $attempt); } /** @@ -137,64 +128,51 @@ public static function previous_attempt(capquiz_user $user) { * * @param capquiz_user $user * @return capquiz_question_attempt[] - * @throws \dml_exception */ - public static function inactive_attempts(capquiz_user $user) : array { + public static function inactive_attempts(capquiz_user $user): array { global $DB; - $entries = $DB->get_records('capquiz_attempt', [ + $records = $DB->get_records('capquiz_attempt', [ 'user_id' => $user->id(), 'answered' => true, - 'reviewed' => true + 'reviewed' => true, ]); - $records = []; - foreach ($entries as $entry) { - array_push($records, new capquiz_question_attempt($user->question_usage(), $entry)); - } - return $records; + return array_map(function (stdClass $record) use ($user) { + return new capquiz_question_attempt($user->question_usage(), $record); + }, array_values($records)); } /** * Returns the attempts id - * - * @return int */ - public function id() : int { + public function id(): int { return $this->record->id; } /** * Returns the id of the question - * - * @return int */ - public function question_id() : int { + public function question_id(): int { return $this->record->question_id; } /** * Returns the slot of the question - * - * @return int */ - public function question_slot() : int { + public function question_slot(): int { return $this->record->slot; } /** * Returns true if the attempt has an answer - * - * @return bool */ - public function is_answered() : bool { + public function is_answered(): bool { return $this->record->answered; } /** * Returns true if the answer is correct - * - * @return bool */ - public function is_correctly_answered() : bool { + public function is_correctly_answered(): bool { if (!$this->is_answered()) { return false; } @@ -204,39 +182,30 @@ public function is_correctly_answered() : bool { /** * Returns the state of the question - * - * @return \question_state */ - public function get_state() : \question_state { + public function get_state(): question_state { $moodleattempt = $this->quba->get_question_attempt($this->question_slot()); return $moodleattempt->get_state(); } /** * Returns true if the attempt is reviewed - * - * @return bool */ - public function is_reviewed() : bool { + public function is_reviewed(): bool { return $this->record->reviewed; } /** * Returns true if the attempt is not reviewed - * - * @return bool */ - public function is_pending() : bool { + public function is_pending(): bool { return !$this->is_reviewed(); } /** * Checks if the question is valid - * - * @return bool - * @throws \dml_exception */ - public function is_question_valid() : bool { + public function is_question_valid(): bool { global $DB; $sql = 'SELECT cq.id FROM {capquiz_attempt} ca @@ -249,36 +218,30 @@ public function is_question_valid() : bool { /** * Deletes attempt from database - * - * @throws \dml_exception */ - public function delete() { + public function delete(): void { global $DB; - $DB->execute('DELETE FROM {capquiz_attempt} WHERE id = :id', ['id' => $this->id()]); + $DB->delete_records('capquiz_attempt', ['id' => $this->id()]); } /** * Marks attempt as answered - * - * @throws \dml_exception */ - public function mark_as_answered() { + public function mark_as_answered(): void { global $DB; $submitteddata = $this->quba->extract_responses($this->question_slot()); $this->quba->process_action($this->question_slot(), $submitteddata); $this->record->answered = true; $this->record->time_answered = time(); $this->quba->finish_question($this->question_slot(), time()); - \question_engine::save_questions_usage_by_activity($this->quba); + question_engine::save_questions_usage_by_activity($this->quba); $DB->update_record('capquiz_attempt', $this->record); } /** * Marks attempt as viewed - * - * @throws \dml_exception */ - public function mark_as_reviewed() { + public function mark_as_reviewed(): void { global $DB; $this->record->reviewed = true; $this->record->time_reviewed = time(); @@ -289,15 +252,14 @@ public function mark_as_reviewed() { * Sets current question rating * * @param capquiz_question_rating $rating - * @param false $previous - * @throws \dml_exception + * @param bool $previous */ - public function set_question_rating(capquiz_question_rating $rating, $previous = false) { + public function set_question_rating(capquiz_question_rating $rating, bool $previous = false): void { global $DB; - if (!$previous) { - $this->record->question_rating_id = $rating->id(); - } else { + if ($previous) { $this->record->question_prev_rating_id = $rating->id(); + } else { + $this->record->question_rating_id = $rating->id(); } $DB->update_record('capquiz_attempt', $this->record); } @@ -306,15 +268,14 @@ public function set_question_rating(capquiz_question_rating $rating, $previous = * Sets rating for the previous rating * * @param capquiz_question_rating $rating - * @param false $previous - * @throws \dml_exception + * @param bool $previous */ - public function set_previous_question_rating(capquiz_question_rating $rating, $previous = false) { + public function set_previous_question_rating(capquiz_question_rating $rating, bool $previous = false): void { global $DB; - if (!$previous) { - $this->record->prev_question_rating_id = $rating->id(); - } else { + if ($previous) { $this->record->prev_question_prev_rating_id = $rating->id(); + } else { + $this->record->prev_question_rating_id = $rating->id(); } $DB->update_record('capquiz_attempt', $this->record); } @@ -323,15 +284,14 @@ public function set_previous_question_rating(capquiz_question_rating $rating, $p * Sets the user rating of the attempt * * @param capquiz_user_rating $rating - * @param false $previous - * @throws \dml_exception + * @param bool $previous */ - public function set_user_rating(capquiz_user_rating $rating, $previous = false) { + public function set_user_rating(capquiz_user_rating $rating, bool $previous = false): void { global $DB; - if (!$previous) { - $this->record->user_rating_id = $rating->id(); - } else { + if ($previous) { $this->record->user_prev_rating_id = $rating->id(); + } else { + $this->record->user_rating_id = $rating->id(); } $DB->update_record('capquiz_attempt', $this->record); } @@ -342,20 +302,16 @@ public function set_user_rating(capquiz_user_rating $rating, $previous = false) * @param capquiz_user $user * @param capquiz_question $question * @param int $slot - * @return capquiz_question_attempt|null */ - private static function insert_attempt_entry(capquiz_user $user, capquiz_question $question, int $slot) { + private static function insert_attempt_entry(capquiz_user $user, capquiz_question $question, + int $slot): ?capquiz_question_attempt { global $DB; - $record = new \stdClass(); + $record = new stdClass(); $record->slot = $slot; $record->user_id = $user->id(); $record->question_id = $question->id(); - try { - $DB->insert_record('capquiz_attempt', $record); - return self::active_attempt($user); - } catch (\dml_exception $e) { - return null; - } + $DB->insert_record('capquiz_attempt', $record); + return self::active_attempt($user); } } diff --git a/classes/capquiz_question_engine.php b/classes/capquiz_question_engine.php index 144385f..bbbbe91 100755 --- a/classes/capquiz_question_engine.php +++ b/classes/capquiz_question_engine.php @@ -25,6 +25,8 @@ namespace mod_capquiz; +use question_usage_by_activity; + /** * Class capquiz_question_engine * @@ -36,25 +38,27 @@ class capquiz_question_engine { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; - /** @var \question_usage_by_activity $quba */ - private $quba; + /** @var question_usage_by_activity $quba */ + private question_usage_by_activity $quba; /** @var capquiz_matchmaking_strategy_loader $matchmakingloader */ - private $matchmakingloader; + private capquiz_matchmaking_strategy_loader $matchmakingloader; /** @var capquiz_rating_system_loader $ratingsystemloader */ - private $ratingsystemloader; + private capquiz_rating_system_loader $ratingsystemloader; /** - * capquiz_question_engine constructor. + * Constructor. + * * @param capquiz $capquiz - * @param \question_usage_by_activity $quba + * @param question_usage_by_activity $quba * @param capquiz_matchmaking_strategy_loader $strategyloader * @param capquiz_rating_system_loader $ratingsystemloader */ - public function __construct(capquiz $capquiz, \question_usage_by_activity $quba, + public function __construct(capquiz $capquiz, + question_usage_by_activity $quba, capquiz_matchmaking_strategy_loader $strategyloader, capquiz_rating_system_loader $ratingsystemloader) { $this->capquiz = $capquiz; @@ -67,9 +71,8 @@ public function __construct(capquiz $capquiz, \question_usage_by_activity $quba, * Checks if the user has finished their attempt * * @param capquiz_user $user - * @return bool */ - public function user_is_completed(capquiz_user $user) : bool { + public function user_is_completed(capquiz_user $user): bool { if (capquiz_question_attempt::active_attempt($user)) { return false; } @@ -83,22 +86,16 @@ public function user_is_completed(capquiz_user $user) : bool { * Gets an attempt for the user, returns a new one if there are no active attempts * * @param capquiz_user $user - * @return capquiz_question_attempt|null */ - public function attempt_for_user(capquiz_user $user) { - if ($attempt = capquiz_question_attempt::active_attempt($user)) { - return $attempt; - } - return $this->new_attempt_for_user($user); + public function attempt_for_user(capquiz_user $user): ?capquiz_question_attempt { + $attempt = capquiz_question_attempt::active_attempt($user); + return $attempt !== null ? $attempt : $this->new_attempt_for_user($user); } /** * Calls attempt_for_user with the user parameter as the current user - * - * @return capquiz_question_attempt|null - * @throws \Exception */ - public function attempt_for_current_user() { + public function attempt_for_current_user(): ?capquiz_question_attempt { return $this->attempt_for_user($this->capquiz->user()); } @@ -107,10 +104,9 @@ public function attempt_for_current_user() { * * @param capquiz_user $user */ - public function delete_invalid_attempt(capquiz_user $user) { + public function delete_invalid_attempt(capquiz_user $user): void { $attempt = $this->attempt_for_user($user); - - if (!$attempt->is_question_valid()) { + if ($attempt !== null && !$attempt->is_question_valid()) { $attempt->delete(); } } @@ -121,7 +117,7 @@ public function delete_invalid_attempt(capquiz_user $user) { * @param capquiz_user $user * @param capquiz_question_attempt $attempt */ - public function attempt_answered(capquiz_user $user, capquiz_question_attempt $attempt) { + public function attempt_answered(capquiz_user $user, capquiz_question_attempt $attempt): void { if (!$attempt->is_question_valid()) { return; } @@ -146,9 +142,8 @@ public function attempt_answered(capquiz_user $user, capquiz_question_attempt $a * Sets a new "highest star" score if the new score is the highest score yet * * @param capquiz_user $user - * @throws \dml_exception */ - private function set_new_highest_star_if_attained(capquiz_user $user) { + private function set_new_highest_star_if_attained(capquiz_user $user): void { $qlist = $this->capquiz->question_list(); for ($star = $qlist->max_stars(); $star > 0; $star--) { $required = $qlist->star_rating($star); @@ -164,7 +159,7 @@ private function set_new_highest_star_if_attained(capquiz_user $user) { * * @param capquiz_question_attempt $attempt */ - public function attempt_reviewed(capquiz_question_attempt $attempt) { + public function attempt_reviewed(capquiz_question_attempt $attempt): void { $attempt->mark_as_reviewed(); } @@ -172,22 +167,25 @@ public function attempt_reviewed(capquiz_question_attempt $attempt) { * Creates a new attempt for the user * * @param capquiz_user $user - * @return capquiz_question_attempt|null */ - private function new_attempt_for_user(capquiz_user $user) { + private function new_attempt_for_user(capquiz_user $user): ?capquiz_question_attempt { $question = $this->find_question_for_user($user); - return $question ? capquiz_question_attempt::create_attempt($user, $question) : null; + if ($question === null) { + return null; + } + return capquiz_question_attempt::create_attempt($user, $question); } /** * Finds a new question for the user * * @param capquiz_user $user - * @return mixed - * @throws \dml_exception */ - private function find_question_for_user(capquiz_user $user) { + private function find_question_for_user(capquiz_user $user): ?capquiz_question { $selector = $this->matchmakingloader->selector(); + if ($selector === null) { + return null; + } $questionlist = $this->capquiz->question_list(); $inactiveattempts = capquiz_question_attempt::inactive_attempts($user); return $selector->next_question_for_user($user, $questionlist, $inactiveattempts); @@ -199,19 +197,21 @@ private function find_question_for_user(capquiz_user $user) { * @param capquiz_question_attempt $previous * @param capquiz_question_attempt $current */ - private function update_question_rating(capquiz_question_attempt $previous, capquiz_question_attempt $current) { + private function update_question_rating(capquiz_question_attempt $previous, capquiz_question_attempt $current): void { $ratingsystem = $this->ratingsystemloader->rating_system(); $currentcorrect = $current->is_correctly_answered(); $previouscorrect = $previous->is_correctly_answered(); - $currentquestion = $this->capquiz->question_list()->question($current->question_id()); - $previousquestion = $this->capquiz->question_list()->question($previous->question_id()); - - $current->set_previous_question_rating($previousquestion->get_capquiz_question_rating(), true); - $current->set_question_rating($currentquestion->get_capquiz_question_rating(), true); - - if (!$currentquestion || !$previousquestion) { + $qlist = $this->capquiz->question_list(); + $currentquestion = $qlist->question($current->question_id()); + if (!$currentquestion) { return; } + $previousquestion = $qlist->question($previous->question_id()); + if (!$previousquestion) { + return; + } + $current->set_previous_question_rating($previousquestion->get_capquiz_question_rating(), true); + $current->set_question_rating($currentquestion->get_capquiz_question_rating(), true); if ($previouscorrect && !$currentcorrect) { $ratingsystem->question_victory_ratings($currentquestion, $previousquestion); } else if (!$previouscorrect && $currentcorrect) { diff --git a/classes/capquiz_question_list.php b/classes/capquiz_question_list.php index e32734a..20e2d43 100755 --- a/classes/capquiz_question_list.php +++ b/classes/capquiz_question_list.php @@ -26,6 +26,9 @@ namespace mod_capquiz; +use context_course; +use stdClass; + /** * Class capquiz_question_list * @@ -37,46 +40,38 @@ */ class capquiz_question_list { - /** @var \stdClass $record */ - private $record; + /** @var stdClass $record */ + private stdClass $record; /** @var capquiz_question[] $questions */ - private $questions; + private array $questions; /** - * capquiz_question_list constructor. - * @param \stdClass $record - * @throws \dml_exception + * Constructor. + * + * @param stdClass $record */ - public function __construct(\stdClass $record) { + public function __construct(stdClass $record) { global $DB; $this->record = $record; - $entries = $DB->get_records('capquiz_question', ['question_list_id' => $this->record->id]); - $this->questions = []; - foreach ($entries as $entry) { - $this->questions[] = new capquiz_question($entry); - } + $records = $DB->get_records('capquiz_question', ['question_list_id' => $this->record->id]); + $this->questions = array_map(fn(stdClass $question) => new capquiz_question($question), array_values($records)); } /** * Returns array of ratings * - * @return false|string[] + * @return int[] */ - public function star_ratings_array() { + public function star_ratings_array(): array { $ratings = explode(',', $this->record->star_ratings); - foreach ($ratings as &$rating) { - $rating = (int)$rating; - } - return $ratings; + return array_map(fn(string $rating) => (float)$rating, $ratings); } /** * Returns the count of all ratings (The value needed for a full star score) - * - * @return int */ - public function max_stars() { + public function max_stars(): int { return count($this->star_ratings_array()); } @@ -84,9 +79,8 @@ public function max_stars() { * Returns the value of the star rating $star * * @param int $star - * @return mixed|string */ - public function star_rating(int $star) { + public function star_rating(int $star): float { $stars = $this->star_ratings_array(); return $stars[$star - 1]; } @@ -95,9 +89,8 @@ public function star_rating(int $star) { * Sets the star ratings to new values and updates database * * @param int[] $ratings - * @throws \dml_exception */ - public function set_star_ratings(array $ratings) { + public function set_star_ratings(array $ratings): void { global $DB; $starratings = implode(',', $ratings); if (strlen($starratings) < 250) { @@ -110,10 +103,9 @@ public function set_star_ratings(array $ratings) { * Returns the completion level to the next rating as a percent value * * @param capquiz $capquiz - * @param int $rating - * @return int + * @param float $rating */ - public function next_level_percent(capquiz $capquiz, int $rating) : int { + public function next_level_percent(capquiz $capquiz, float $rating): int { $goal = 0; for ($star = 1; $star <= $this->max_stars(); $star++) { $goal = $this->star_rating($star); @@ -129,49 +121,37 @@ public function next_level_percent(capquiz $capquiz, int $rating) : int { /** * Returns the id - * - * @return int */ - public function id() : int { + public function id(): int { return $this->record->id; } /** * Returns the author user - * - * @return mixed|\stdClass|null - * @throws \dml_exception */ - public function author() { + public function author(): ?stdClass { global $DB; - $record = $DB->get_record('user', ['id' => $this->record->author]); - return $record ? $record : null; + return $DB->get_record('user', ['id' => $this->record->author]) ?: null; } /** * Returns true if the list contains questions - * - * @return bool */ - public function has_questions() : bool { + public function has_questions(): bool { return count($this->questions) > 0; } /** * Returns true if the question list is a template - * - * @return bool */ - public function is_template() : bool { + public function is_template(): bool { return $this->record->is_template; } /** * Returns the default question rating - * - * @return float */ - public function default_question_rating() : float { + public function default_question_rating(): float { return $this->record->default_question_rating; } @@ -179,9 +159,8 @@ public function default_question_rating() : float { * Sets teh default question rating * * @param float $rating - * @throws \dml_exception */ - public function set_default_question_rating(float $rating) { + public function set_default_question_rating(float $rating): void { global $DB; $this->record->default_question_rating = $rating; $DB->update_record('capquiz_question_list', $this->record); @@ -189,46 +168,36 @@ public function set_default_question_rating(float $rating) { /** * Returns the title of the question list - * - * @return string */ - public function title() : string { + public function title(): string { return $this->record->title; } /** * Returns the description of the question list - * - * @return string */ - public function description() : string { + public function description(): string { return $this->record->description; } /** * Returns the time of when the list was created - * - * @return string */ - public function time_created() : string { + public function time_created(): string { return $this->record->time_created; } /** * Returns the last time when the list was modified - * - * @return string */ - public function time_modified() : string { + public function time_modified(): string { return $this->record->time_modified; } /** * Returns the amount of questions in the list - * - * @return int */ - public function question_count() : int { + public function question_count(): int { return count($this->questions); } @@ -237,7 +206,7 @@ public function question_count() : int { * * @return capquiz_question[] */ - public function questions() : array { + public function questions(): array { return $this->questions; } @@ -245,9 +214,8 @@ public function questions() : array { * Returns the question with the id of $questionid * * @param int $questionid - * @return mixed|capquiz_question|null */ - public function question(int $questionid) { + public function question(int $questionid): ?capquiz_question { foreach ($this->questions as $question) { if ($question->id() === $questionid) { return $question; @@ -262,7 +230,7 @@ public function question(int $questionid) { * @param int $questionid * @return mixed|capquiz_question|null */ - public function has_question(int $questionid) { + public function has_question(int $questionid): mixed { foreach ($this->questions as $question) { if ($question->question_id() === $questionid) { return $question; @@ -275,13 +243,12 @@ public function has_question(int $questionid) { * The questions from $that will be imported to this question list. * * @param capquiz_question_list $that The question list to import questions from. - * @throws \dml_exception */ - public function merge(capquiz_question_list $that) { + public function merge(capquiz_question_list $that): void { global $DB; foreach ($that->questions as $question) { if ($this->has_question($question->question_id()) === null) { - $newquestion = new \stdClass(); + $newquestion = new stdClass(); $newquestion->question_list_id = $this->id(); $newquestion->question_id = $question->question_id(); $newquestion->rating = $question->rating(); @@ -295,9 +262,8 @@ public function merge(capquiz_question_list $that) { * Creates a copy of this instance * * @param capquiz $capquiz - * @return capquiz_question_list|null */ - public function create_instance_copy(capquiz $capquiz) { + public function create_instance_copy(capquiz $capquiz): ?capquiz_question_list { return $this->create_copy($capquiz, false); } @@ -305,10 +271,8 @@ public function create_instance_copy(capquiz $capquiz) { * Updates database record * * @param int $capquizid - * @return bool - * @throws \dml_exception */ - public function convert_to_instance(int $capquizid) : bool { + public function convert_to_instance(int $capquizid): bool { global $DB; if ($this->id() || !$this->is_template()) { return false; @@ -323,9 +287,8 @@ public function convert_to_instance(int $capquizid) : bool { * Creates a copy of this instance as template * * @param capquiz $capquiz - * @return capquiz_question_list|null */ - public function create_template_copy(capquiz $capquiz) { + public function create_template_copy(capquiz $capquiz): ?capquiz_question_list { return $this->create_copy($capquiz, true); } @@ -333,15 +296,14 @@ public function create_template_copy(capquiz $capquiz) { * Copies the questions in this list to database * * @param int $qlistid - * @throws \dml_exception */ - private function copy_questions_to_list(int $qlistid) { + private function copy_questions_to_list(int $qlistid): void { global $DB; foreach ($this->questions() as $question) { $record = $question->entry(); $record->id = null; $record->question_list_id = $qlistid; - $capquizquestionid = $DB->insert_record('capquiz_question', $record, true); + $capquizquestionid = $DB->insert_record('capquiz_question', $record); capquiz_question_rating::insert_question_rating_entry($capquizquestionid, $record->rating); } } @@ -351,17 +313,14 @@ private function copy_questions_to_list(int $qlistid) { * * @param capquiz $capquiz * @param bool $template - * @return capquiz_question_list|null The new but identical (apart from identicators) question list instance - * @throws \Throwable - * @throws \coding_exception - * @throws \dml_transaction_exception + * @return ?capquiz_question_list The new but identical (apart from identicators) question list instance */ - private function create_copy(capquiz $capquiz, bool $template) { + private function create_copy(capquiz $capquiz, bool $template): ?capquiz_question_list { global $DB; $record = $this->record; $record->id = null; $record->capquiz_id = $template ? null : $capquiz->id(); - $record->context_id = \context_course::instance($capquiz->course()->id)->id; + $record->context_id = context_course::instance($capquiz->course()->id)->id; $record->is_template = $template; $record->time_created = time(); $record->time_modified = time(); @@ -371,10 +330,9 @@ private function create_copy(capquiz $capquiz, bool $template) { $this->copy_questions_to_list($newid); $DB->commit_delegated_transaction($transaction); $record->id = $newid; - return new capquiz_question_list($record, $capquiz->context()); + return new capquiz_question_list($record); } catch (\dml_exception $exception) { $DB->rollback_delegated_transaction($transaction, $exception); - return null; } } @@ -385,14 +343,14 @@ private function create_copy(capquiz $capquiz, bool $template) { * @param string $title * @param string $description * @param array $ratings - * @return capquiz_question_list|null */ - public static function create_new_instance(capquiz $capquiz, string $title, string $description, array $ratings) { + public static function create_new_instance(capquiz $capquiz, string $title, string $description, + array $ratings): ?capquiz_question_list { global $DB, $USER; if (count($ratings) < 5) { return null; } - $record = new \stdClass(); + $record = new stdClass(); $record->capquiz_id = $capquiz->id(); $record->title = $title; $record->description = $description; @@ -401,60 +359,50 @@ public static function create_new_instance(capquiz $capquiz, string $title, stri $record->is_template = 0; $record->time_created = time(); $record->time_modified = time(); - $record->context_id = \context_course::instance($capquiz->course()->id)->id; - try { - $qlistid = $DB->insert_record('capquiz_question_list', $record); - $qlist = self::load_any($qlistid, $capquiz->context()); - if (!$qlist) { - return null; - } - $capquiz->validate_matchmaking_and_rating_systems(); - return $qlist; - } catch (\Exception $e) { + $record->context_id = context_course::instance($capquiz->course()->id)->id; + $qlistid = $DB->insert_record('capquiz_question_list', $record); + $qlist = self::load_any($qlistid); + if (!$qlist) { return null; } + $capquiz->validate_matchmaking_and_rating_systems(); + return $qlist; } /** * Loads question list from database based on the capquiz * * @param capquiz $capquiz - * @return capquiz_question_list|null - * @throws \dml_exception */ - public static function load_question_list(capquiz $capquiz) { + public static function load_question_list(capquiz $capquiz): ?capquiz_question_list { global $DB; $record = $DB->get_record('capquiz_question_list', ['capquiz_id' => $capquiz->id()]); - return $record ? new capquiz_question_list($record, $capquiz->context()) : null; + return $record ? new capquiz_question_list($record) : null; } /** * Loads question list from database based on the question list id * * @param int $qlistid - * @param \context_module $context - * @return capquiz_question_list|null - * @throws \dml_exception */ - public static function load_any(int $qlistid, $context) { + public static function load_any(int $qlistid): ?capquiz_question_list { global $DB; $record = $DB->get_record('capquiz_question_list', ['id' => $qlistid]); - return $record ? new capquiz_question_list($record, $context) : null; + return $record ? new capquiz_question_list($record) : null; } /** * Loads question list templates * - * @param \context_module $context * @return capquiz_question_list[] * @throws \dml_exception */ - public static function load_question_list_templates($context) : array { + public static function load_question_list_templates(): array { global $DB; $records = $DB->get_records('capquiz_question_list', ['is_template' => 1]); $qlists = []; foreach ($records as $record) { - $qlists[] = new capquiz_question_list($record, $context); + $qlists[] = new capquiz_question_list($record); } return $qlists; } diff --git a/classes/capquiz_question_rating.php b/classes/capquiz_question_rating.php index 5b3b68e..80d2bca 100755 --- a/classes/capquiz_question_rating.php +++ b/classes/capquiz_question_rating.php @@ -39,12 +39,12 @@ class capquiz_question_rating { /** @var stdClass $record */ - private $record; + private stdClass $record; /** - * capquiz_question constructor. + * Constructor. + * * @param stdClass $record - * @throws dml_exception */ public function __construct(stdClass $record) { $this->record = $record; @@ -54,16 +54,11 @@ public function __construct(stdClass $record) { * Loads a question rating from the database with a matching id * * @param int $questionratingid - * @return capquiz_question_rating|null - * @throws dml_exception */ - public static function load_question_rating(int $questionratingid) { + public static function load_question_rating(int $questionratingid): ?capquiz_question_rating { global $DB; $record = $DB->get_record('capquiz_question_rating', ['id' => $questionratingid]); - if ($record === false) { - return null; - } - return new capquiz_question_rating($record); + return empty($record) ? null : new capquiz_question_rating($record); } /** @@ -72,9 +67,9 @@ public static function load_question_rating(int $questionratingid) { * @param capquiz_question $question * @param float $rating * @param bool $manual - * @return capquiz_question_rating|null */ - public static function create_question_rating(capquiz_question $question, float $rating, bool $manual = false) { + public static function create_question_rating(capquiz_question $question, float $rating, + bool $manual = false): capquiz_question_rating { return self::insert_question_rating_entry($question->id(), $rating, $manual); } @@ -84,33 +79,26 @@ public static function create_question_rating(capquiz_question $question, float * @param int $questionid * @param float $rating * @param bool $manual - * @return capquiz_question_rating|null */ - public static function insert_question_rating_entry(int $questionid, float $rating, bool $manual = false) { + public static function insert_question_rating_entry(int $questionid, float $rating, + bool $manual = false): capquiz_question_rating { global $DB; - $record = new stdClass(); $record->capquiz_question_id = $questionid; $record->rating = $rating; $record->manual = $manual; $record->timecreated = time(); - try { - $ratingid = $DB->insert_record('capquiz_question_rating', $record); - $record->id = $ratingid; - return new capquiz_question_rating($record); - } catch (dml_exception $e) { - return null; - } + $ratingid = $DB->insert_record('capquiz_question_rating', $record); + $record->id = $ratingid; + return new capquiz_question_rating($record); } /** * Load information about the latest question rating for an attempt from the database. * * @param int $questionid - * @return capquiz_question_rating - * @throws dml_exception */ - public static function latest_question_rating_by_question($questionid) { + public static function latest_question_rating_by_question(int $questionid): ?capquiz_question_rating { global $DB; $sql = "SELECT cqr.* FROM {capquiz_question_rating} cqr @@ -123,14 +111,11 @@ public static function latest_question_rating_by_question($questionid) { ) AND cq.id = :question_id"; $record = $DB->get_record_sql($sql, ['question_id' => $questionid]); - - return $record ? new capquiz_question_rating($record) : null; + return empty($record) ? null : new capquiz_question_rating($record); } /** * Returns this question ratings id - * - * @return int */ public function id(): int { return $this->record->id; @@ -138,8 +123,6 @@ public function id(): int { /** * Returns the time of when the question rating was created - * - * @return string */ public function timecreated(): string { return $this->record->timecreated; @@ -147,8 +130,6 @@ public function timecreated(): string { /** * Returns the question rating - * - * @return float */ public function rating(): float { return $this->record->rating; @@ -158,9 +139,8 @@ public function rating(): float { * Sets the question rating * * @param float $rating - * @throws dml_exception */ - public function set_rating(float $rating) { + public function set_rating(float $rating): void { global $DB; $this->record->rating = $rating; $DB->update_record('capquiz_question_rating', $this->record); diff --git a/classes/capquiz_rating_system.php b/classes/capquiz_rating_system.php index de15cc4..baad384 100755 --- a/classes/capquiz_rating_system.php +++ b/classes/capquiz_rating_system.php @@ -26,6 +26,8 @@ namespace mod_capquiz; +use stdClass; + /** * Class capquiz_rating_system * @@ -39,24 +41,19 @@ abstract class capquiz_rating_system { /** * Function to configure a rating system * - * @param \stdClass $configuration - * @return mixed + * @param stdClass $config */ - abstract public function configure(\stdClass $configuration); + abstract public function configure(stdClass $config): void; /** * Function to get the rating system configuration - * - * @return mixed */ - abstract public function configuration(); + abstract public function configuration(): stdClass; /** * Function to get the default rating system configuration - * - * @return mixed */ - abstract public function default_configuration(); + abstract public function default_configuration(): stdClass; /** * Updates the users rating based on the rating system and its configuration @@ -64,17 +61,15 @@ abstract public function default_configuration(); * @param capquiz_user $user * @param capquiz_question $question * @param float $score - * @return mixed */ - abstract public function update_user_rating(capquiz_user $user, capquiz_question $question, float $score); + abstract public function update_user_rating(capquiz_user $user, capquiz_question $question, float $score): void; /** * Updates the winning and losing questions ratings * * @param capquiz_question $winner * @param capquiz_question $loser - * @return mixed */ - abstract public function question_victory_ratings(capquiz_question $winner, capquiz_question $loser); + abstract public function question_victory_ratings(capquiz_question $winner, capquiz_question $loser): void; } diff --git a/classes/capquiz_rating_system_loader.php b/classes/capquiz_rating_system_loader.php index bd19853..881fe94 100755 --- a/classes/capquiz_rating_system_loader.php +++ b/classes/capquiz_rating_system_loader.php @@ -25,6 +25,9 @@ namespace mod_capquiz; +use moodle_url; +use stdClass; + defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/mod/capquiz/classes/rating_system/capquiz_rating_system_registry.php'); @@ -41,19 +44,19 @@ class capquiz_rating_system_loader { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; - /** @var \stdClass $record */ - private $record; + /** @var ?stdClass $record */ + private ?stdClass $record = null; /** @var capquiz_rating_system_registry $registry */ - private $registry; + private capquiz_rating_system_registry $registry; - /** @var \stdClass $configuration */ - private $configuration; + /** @var ?stdClass $configuration */ + private ?stdClass $configuration; /** - * capquiz_rating_system_loader constructor. + * Constructor. * * @param capquiz $capquiz */ @@ -65,10 +68,8 @@ public function __construct(capquiz $capquiz) { /** * Returns rating system - * - * @return capquiz_rating_system|null */ - public function rating_system() { + public function rating_system(): ?capquiz_rating_system { if (!$this->record) { return null; } @@ -84,17 +85,16 @@ public function rating_system() { * * @return bool */ - public function has_rating_system() : bool { + public function has_rating_system(): bool { return $this->rating_system() !== null; } /** * Returns configuration form * - * @param \moodle_url $url - * @return null + * @param moodle_url $url */ - public function configuration_form(\moodle_url $url) { + public function configuration_form(moodle_url $url): mixed { if ($this->record && $this->configuration) { return $this->registry->configuration_form($this->record->rating_system, $this->configuration, $url); } @@ -106,7 +106,7 @@ public function configuration_form(\moodle_url $url) { * * @return string rating system name */ - public function current_rating_system_name() : string { + public function current_rating_system_name(): string { if ($this->record) { return $this->record->rating_system; } @@ -114,50 +114,41 @@ public function current_rating_system_name() : string { } /** - * Configures the current rating system + * Configure the current rating system. * - * @param \stdClass $candidateconfig + * @param stdClass $candidateconfig */ - public function configure_current_rating_system(\stdClass $candidateconfig) { + public function configure_current_rating_system(stdClass $candidateconfig): void { if (!$this->record) { return; } $system = $this->rating_system(); $system->configure($candidateconfig); - $configuration = $system->configuration(); - if ($configuration) { - $this->record->configuration = $this->serialize($configuration); - } else { - $this->record->configuration = ''; - } + $config = $system->configuration(); + $this->record->configuration = empty((array)$config) ? '' : $this->serialize($config); $this->update_configuration($this->record); } /** - * sets the default rating system + * Set the default rating system. */ - public function set_default_rating_system() { + public function set_default_rating_system(): void { $this->set_rating_system($this->registry->default_rating_system()); } /** - * Sets rating system defined by $ratingsystem + * Set the rating system * * @param string $ratingsystem - * @throws \dml_exception */ - public function set_rating_system(string $ratingsystem) { + public function set_rating_system(string $ratingsystem): void { global $DB; $system = $this->registry->rating_system($ratingsystem); - $record = new \stdClass; + $record = new stdClass; $record->rating_system = $ratingsystem; $record->capquiz_id = $this->capquiz->id(); $defaultconfig = $system->default_configuration(); - if ($defaultconfig) { - $record->configuration = $this->serialize($defaultconfig); - } else { - $record->configuration = ''; - } + $record->configuration = empty((array)$defaultconfig) ? '' : $this->serialize($defaultconfig); if ($this->record) { $record->id = $this->record->id; $this->update_configuration($record); @@ -169,13 +160,10 @@ public function set_rating_system(string $ratingsystem) { /** * Loads this instances configuration - * - * @throws \dml_exception */ - private function load_configuration() { + private function load_configuration(): void { global $DB; - $conditions = ['capquiz_id' => $this->capquiz->id()]; - $configuration = $DB->get_record('capquiz_rating_system', $conditions); + $configuration = $DB->get_record('capquiz_rating_system', ['capquiz_id' => $this->capquiz->id()]); if ($configuration) { $this->set_configuration($configuration); } @@ -184,10 +172,9 @@ private function load_configuration() { /** * Updates this instances configuration as well as updates the database * - * @param \stdClass $configuration - * @throws \dml_exception + * @param stdClass $configuration */ - private function update_configuration(\stdClass $configuration) { + private function update_configuration(stdClass $configuration): void { global $DB; if ($DB->update_record('capquiz_rating_system', $configuration)) { $this->set_configuration($configuration); @@ -197,9 +184,9 @@ private function update_configuration(\stdClass $configuration) { /** * Sets this instances configuration * - * @param \stdClass $record + * @param stdClass $record */ - private function set_configuration(\stdClass $record) { + private function set_configuration(stdClass $record): void { $this->record = $record; $this->configuration = $this->deserialize($record->configuration); } @@ -207,10 +194,10 @@ private function set_configuration(\stdClass $record) { /** * Serializes the input configuration object * - * @param \stdClass $configuration the configuration to be serialized + * @param stdClass $configuration the configuration to be serialized * @return string json string representing the input configuration */ - private function serialize(\stdClass $configuration) : string { + private function serialize(stdClass $configuration): string { return json_encode($configuration); } @@ -218,9 +205,8 @@ private function serialize(\stdClass $configuration) : string { * Deserializes JSON formatted configuration string * * @param string $configuration The JSON string to be deserialized back into a configuration object - * @return mixed */ - private function deserialize(string $configuration) { + private function deserialize(string $configuration): mixed { return json_decode($configuration, false); } diff --git a/classes/capquiz_urls.php b/classes/capquiz_urls.php index 74b1b29..85e100d 100755 --- a/classes/capquiz_urls.php +++ b/classes/capquiz_urls.php @@ -27,7 +27,6 @@ namespace mod_capquiz; -use coding_exception; use moodle_url; defined('MOODLE_INTERNAL') || die(); @@ -47,44 +46,42 @@ class capquiz_urls { /** @var string The URL to the entrypoint view for the capquiz */ - public static $urlview = '/mod/capquiz/view.php'; + public static string $urlview = '/mod/capquiz/view.php'; /** @var string The URL to update the user attempts and return to the dashboard */ - public static $urlasync = '/mod/capquiz/async.php'; + public static string $urlasync = '/mod/capquiz/async.php'; /** @var string The URL to the error page */ - public static $urlerror = '/mod/capquiz/error.php'; + public static string $urlerror = '/mod/capquiz/error.php'; /** @var string The URL to the action page */ - public static $urlaction = '/mod/capquiz/action.php'; + public static string $urlaction = '/mod/capquiz/action.php'; /** @var string The URL to the classlist view */ - public static $urlviewclasslist = '/mod/capquiz/view_classlist.php'; + public static string $urlviewclasslist = '/mod/capquiz/view_classlist.php'; /** @var string The URL to the grading view */ - public static $urlviewgrading = '/mod/capquiz/view_grading.php'; + public static string $urlviewgrading = '/mod/capquiz/view_grading.php'; /** @var string The URL to the import view */ - public static $urlviewimport = '/mod/capquiz/view_import.php'; + public static string $urlviewimport = '/mod/capquiz/view_import.php'; /** @var string The URL to the report view */ - public static $urlviewreport = '/mod/capquiz/view_report.php'; + public static string $urlviewreport = '/mod/capquiz/view_report.php'; /** @var string The URL for the capquiz editor */ - public static $urledit = '/mod/capquiz/edit.php'; + public static string $urledit = '/mod/capquiz/edit.php'; /** @var string The URL to the create question list view */ - public static $urlviewcreateqlist = '/mod/capquiz/view_create_question_list.php'; + public static string $urlviewcreateqlist = '/mod/capquiz/view_create_question_list.php'; /** @var string The URL to the rating system view */ - public static $urlviewratingsystemconfig = '/mod/capquiz/view_rating_system.php'; + public static string $urlviewratingsystemconfig = '/mod/capquiz/view_rating_system.php'; /** * Returns a redirect url * * @param moodle_url $target - * @return moodle_url - * @throws coding_exception */ public static function redirect(moodle_url $target): moodle_url { $url = self::create_view_url(self::$urlaction); @@ -97,9 +94,6 @@ public static function redirect(moodle_url $target): moodle_url { * Generates a url based on a relative url * * @param string $relativeurl - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function create_view_url(string $relativeurl): moodle_url { global $CFG; @@ -110,9 +104,6 @@ public static function create_view_url(string $relativeurl): moodle_url { /** * Returns the course module id - * - * @return int - * @throws coding_exception */ public static function require_course_module_id_param(): int { $id = optional_param('id', 0, PARAM_INT); @@ -124,21 +115,16 @@ public static function require_course_module_id_param(): int { /** * Redirects to the front page - * - * @throws \moodle_exception */ - public static function redirect_to_front_page() { + public static function redirect_to_front_page(): void { global $CFG; redirect(new moodle_url($CFG->wwwroot)); } /** * Redirects to the dashboard - * - * @throws \moodle_exception - * @throws coding_exception */ - public static function redirect_to_dashboard() { + public static function redirect_to_dashboard(): void { self::redirect_to_url(self::create_view_url(self::$urlview)); } @@ -146,16 +132,15 @@ public static function redirect_to_dashboard() { * Redirects to specified url * * @param moodle_url $url - * @throws \moodle_exception */ - public static function redirect_to_url(moodle_url $url) { + public static function redirect_to_url(moodle_url $url): void { redirect($url); } /** * Redirects to the previous page */ - public static function redirect_to_previous() { + public static function redirect_to_previous(): void { header('Location: ' . $_SERVER['HTTP_REFERER']); exit; } @@ -165,10 +150,8 @@ public static function redirect_to_previous() { * * @param capquiz $capquiz * @param string $url - * @throws \moodle_exception - * @throws coding_exception */ - public static function set_page_url(capquiz $capquiz, string $url) { + public static function set_page_url(capquiz $capquiz, string $url): void { global $PAGE; $PAGE->set_context($capquiz->context()); $PAGE->set_cm($capquiz->course_module()); @@ -178,10 +161,6 @@ public static function set_page_url(capquiz $capquiz, string $url) { /** * Returns url to the front page of the capquiz dashboard - * - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function view_url(): moodle_url { return self::create_view_url(self::$urlview); @@ -191,9 +170,6 @@ public static function view_url(): moodle_url { * Returns the url to the question list view * * @param int $questionpage - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function view_question_list_url(int $questionpage = 0): moodle_url { $url = self::create_view_url(self::$urledit); @@ -203,10 +179,6 @@ public static function view_question_list_url(int $questionpage = 0): moodle_url /** * Returns the url to the rating system view - * - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function view_rating_system_url(): moodle_url { return self::create_view_url(self::$urlviewratingsystemconfig); @@ -214,10 +186,6 @@ public static function view_rating_system_url(): moodle_url { /** * Returns the url to the grading view - * - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function view_grading_url(): moodle_url { return self::create_view_url(self::$urlviewgrading); @@ -225,10 +193,6 @@ public static function view_grading_url(): moodle_url { /** * Returns the url to the classlist/leaderboard view - * - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function view_classlist_url(): moodle_url { return self::create_view_url(self::$urlviewclasslist); @@ -236,10 +200,6 @@ public static function view_classlist_url(): moodle_url { /** * Returns url to the "create question list" view - * - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function view_create_question_list_url(): moodle_url { return self::create_view_url(self::$urlviewcreateqlist); @@ -247,10 +207,6 @@ public static function view_create_question_list_url(): moodle_url { /** * Returns url to the import view - * - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function view_import_url(): moodle_url { return self::create_view_url(self::$urlviewimport); @@ -260,9 +216,8 @@ public static function view_import_url(): moodle_url { * Returns url to the report view * * @param string $mode - * @return moodle_url */ - public static function view_report_url($mode = ''): moodle_url { + public static function view_report_url(string $mode = ''): moodle_url { return self::report_url(self::$urlviewreport, $mode); } @@ -271,11 +226,8 @@ public static function view_report_url($mode = ''): moodle_url { * * @param string $relativeurl * @param string $mode - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ - public static function report_url(string $relativeurl, $mode): moodle_url { + public static function report_url(string $relativeurl, string $mode): moodle_url { $url = self::create_view_url($relativeurl); if ($mode !== '') { $url->param('mode', $mode); @@ -288,9 +240,6 @@ public static function report_url(string $relativeurl, $mode): moodle_url { * the parameters to add question to the list * * @param int $questionid - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function add_question_to_list_url(int $questionid): moodle_url { $url = self::create_view_url(self::$urlaction); @@ -304,9 +253,6 @@ public static function add_question_to_list_url(int $questionid): moodle_url { * the parameters to remove question from the list * * @param int $questionid - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function remove_question_from_list_url(int $questionid): moodle_url { $url = self::create_view_url(self::$urlaction); @@ -320,9 +266,6 @@ public static function remove_question_from_list_url(int $questionid): moodle_ur * the parameters to publish the question list * * @param capquiz_question_list $qlist - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function question_list_publish_url(capquiz_question_list $qlist): moodle_url { $url = self::create_view_url(self::$urlaction); @@ -336,9 +279,6 @@ public static function question_list_publish_url(capquiz_question_list $qlist): * the parameters to create the template * * @param capquiz_question_list $qlist - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function question_list_create_template_url(capquiz_question_list $qlist): moodle_url { $url = self::create_view_url(self::$urlaction); @@ -352,9 +292,6 @@ public static function question_list_create_template_url(capquiz_question_list $ * the parameters to set the question list * * @param capquiz_question_list $qlist - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function question_list_select_url(capquiz_question_list $qlist): moodle_url { $url = self::create_view_url(self::$urlaction); @@ -368,9 +305,6 @@ public static function question_list_select_url(capquiz_question_list $qlist): m * the parameters to set the question rating * * @param int $questionid - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function set_question_rating_url(int $questionid): moodle_url { $url = self::create_view_url(self::$urlaction); @@ -381,10 +315,6 @@ public static function set_question_rating_url(int $questionid): moodle_url { /** * Generates and returns url to regrade all - * - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function regrade_all_url(): moodle_url { $url = self::create_view_url(self::$urlaction); @@ -396,9 +326,6 @@ public static function regrade_all_url(): moodle_url { * Generates and returns url to merge qlist with the parameters to merge the qlist * * @param int $qlistid - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function merge_qlist(int $qlistid): moodle_url { $url = self::create_view_url(self::$urlaction); @@ -411,9 +338,6 @@ public static function merge_qlist(int $qlistid): moodle_url { * Generates and returns url to delete a question list with the parameters to delete the list * * @param int $qlistid - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function delete_qlist(int $qlistid): moodle_url { $url = self::create_view_url(self::$urlaction); @@ -426,9 +350,6 @@ public static function delete_qlist(int $qlistid): moodle_url { * Generates and returns url to submit an attempt * * @param capquiz_question_attempt $attempt - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function response_submit_url(capquiz_question_attempt $attempt): moodle_url { $url = self::create_view_url(self::$urlasync); @@ -441,9 +362,6 @@ public static function response_submit_url(capquiz_question_attempt $attempt): m * Generates and returns url to mark an attempt as reviewed * * @param capquiz_question_attempt $attempt - * @return moodle_url - * @throws \moodle_exception - * @throws coding_exception */ public static function response_reviewed_url(capquiz_question_attempt $attempt): moodle_url { $url = self::create_view_url(self::$urlasync); diff --git a/classes/capquiz_user.php b/classes/capquiz_user.php index e08374d..043aa32 100755 --- a/classes/capquiz_user.php +++ b/classes/capquiz_user.php @@ -26,6 +26,11 @@ namespace mod_capquiz; +use context_module; +use question_engine; +use question_usage_by_activity; +use stdClass; + /** * capquiz_user class * @@ -37,80 +42,69 @@ */ class capquiz_user { - /** @var \stdClass $record */ - private $record; + /** @var stdClass $record */ + private stdClass $record; - /** @var \stdClass $user */ - private $user; + /** @var stdClass $user */ + private stdClass $user; /** @var capquiz_user_rating $rating */ - private $rating; + private capquiz_user_rating $rating; - /** @var \question_usage_by_activity $quba */ - private $quba; + /** @var question_usage_by_activity $quba */ + private question_usage_by_activity $quba; /** - * capquiz_user constructor. + * Constructor. * - * @param \stdClass $record - * @param \context_module $context - * @throws \dml_exception + * @param stdClass $record + * @param context_module $context */ - public function __construct(\stdClass $record, \context_module $context) { + public function __construct(stdClass $record, context_module $context) { global $DB; $this->record = $record; $this->user = $DB->get_record('user', ['id' => $this->record->user_id]); $rating = capquiz_user_rating::latest_user_rating_by_user($record->id); - if (is_null($rating)) { + if ($rating === null) { $this->rating = capquiz_user_rating::insert_user_rating_entry($this->id(), $this->rating()); } else { $this->rating = $rating; } $this->create_question_usage($context); - try { - $this->quba = \question_engine::load_questions_usage_by_activity($this->record->question_usage_id); - } catch (\coding_exception $e) { - $this->quba = null; - } + $this->quba = question_engine::load_questions_usage_by_activity($this->record->question_usage_id); } /** * Verify if user has permission to use question - * - * @return bool */ - private function has_question_usage() : bool { + private function has_question_usage(): bool { return $this->record->question_usage_id !== null; } - /** * Create question usage * - * @param \context_module $context - * @throws \dml_exception + * @param context_module $context */ - public function create_question_usage($context) { + public function create_question_usage(context_module $context): void { global $DB; if ($this->has_question_usage()) { return; } - $quba = \question_engine::make_questions_usage_by_activity('mod_capquiz', $context); + $quba = question_engine::make_questions_usage_by_activity('mod_capquiz', $context); $quba->set_preferred_behaviour('immediatefeedback'); // TODO: Don't suppress the error if it becomes possible to save QUBAs without slots. - @\question_engine::save_questions_usage_by_activity($quba); + @question_engine::save_questions_usage_by_activity($quba); $this->record->question_usage_id = $quba->get_id(); $DB->update_record('capquiz_user', $this->record); } /** - * Return this users quba - * - * @return \question_usage_by_activity|null + * Return this user's quba. */ - public function question_usage() : ?\question_usage_by_activity { + public function question_usage(): ?question_usage_by_activity { return $this->quba; } @@ -119,20 +113,18 @@ public function question_usage() : ?\question_usage_by_activity { * * @param capquiz $capquiz * @param int $moodleuserid - * @param \context_module $context - * @return capquiz_user|null - * @throws \Exception + * @param context_module $context */ - public static function load_user(capquiz $capquiz, int $moodleuserid, \context_module $context) { + public static function load_user(capquiz $capquiz, int $moodleuserid, context_module $context): ?capquiz_user { global $DB; if ($user = self::load_db_entry($capquiz, $moodleuserid, $context)) { return $user; } - $record = new \stdClass(); + $record = new stdClass(); $record->user_id = $moodleuserid; $record->capquiz_id = $capquiz->id(); $record->rating = $capquiz->default_user_rating(); - $capquizuserid = $DB->insert_record('capquiz_user', $record, true); + $capquizuserid = $DB->insert_record('capquiz_user', $record); capquiz_user_rating::insert_user_rating_entry($capquizuserid, $record->rating); return self::load_db_entry($capquiz, $moodleuserid, $context); } @@ -142,9 +134,8 @@ public static function load_user(capquiz $capquiz, int $moodleuserid, \context_m * * @param int $capquizid * @return int count of users in this capquiz - * @throws \dml_exception */ - public static function user_count(int $capquizid) : int { + public static function user_count(int $capquizid): int { global $DB; return $DB->count_records('capquiz_user', ['capquiz_id' => $capquizid]); } @@ -153,115 +144,92 @@ public static function user_count(int $capquizid) : int { * Returns list of all users in this capquiz * * @param int $capquizid - * @param \context_module $context + * @param context_module $context * @return capquiz_user[] - * @throws \dml_exception */ - public static function list_users(int $capquizid, \context_module $context) : array { + public static function list_users(int $capquizid, context_module $context): array { global $DB; - $users = []; - foreach ($DB->get_records('capquiz_user', ['capquiz_id' => $capquizid]) as $user) { - $users[] = new capquiz_user($user, $context); - } - return $users; + $records = $DB->get_records('capquiz_user', ['capquiz_id' => $capquizid]); + return array_map(fn(stdClass $record) => new capquiz_user($record, $context), array_values($records)); } /** - * Return this users id - * - * @return int users id + * Return this user's id */ - public function id() : int { + public function id(): int { return $this->record->id; } /** - * Returns this users username - * - * @return string username + * Returns this user's username */ - public function username() : string { + public function username(): string { return $this->user->username; } /** - * Returns this users first name - * - * @return string first name + * Returns this user's first name */ - public function first_name() : string { + public function first_name(): string { return $this->user->firstname; } /** - * Returns this users last name - * - * @return string last name + * Returns this user's last name */ - public function last_name() : string { + public function last_name(): string { return $this->user->lastname; } /** * Return users rating - * - * @return float */ - public function rating() : float { + public function rating(): float { return $this->record->rating; } /** - * Get this users capquiz rating - * - * @return capquiz_user_rating + * Get this user's capquiz rating */ - public function get_capquiz_user_rating() : capquiz_user_rating { + public function get_capquiz_user_rating(): capquiz_user_rating { return $this->rating; } /** * Return the highest star rating this user has achieved - * - * @return int highest star rating */ - public function highest_stars_achieved() : int { + public function highest_stars_achieved(): int { return $this->record->highest_level; } /** * Return the highest star grade - * - * @return int highest star grade */ - public function highest_stars_graded() : int { + public function highest_stars_graded(): int { return $this->record->stars_graded; } /** - * Set this users highest star rating + * Set this user's highest star rating * * @param int $higheststar - * @throws \dml_exception */ - public function set_highest_star(int $higheststar) { + public function set_highest_star(int $higheststar): void { global $DB; $this->record->highest_level = $higheststar; $DB->update_record('capquiz_user', $this->record); } /** - * Set this users rating + * Set this user's rating * - * @param capquiz_user_rating $rating + * @param float $rating * @param bool $manual - * @throws \dml_exception */ - public function set_rating($rating, bool $manual = false) { + public function set_rating(float $rating, bool $manual = false): void { global $DB; $this->record->rating = $rating; $DB->update_record('capquiz_user', $this->record); - $userrating = capquiz_user_rating::create_user_rating($this, $rating, $manual); $this->rating = $userrating; } @@ -271,19 +239,15 @@ public function set_rating($rating, bool $manual = false) { * * @param capquiz $capquiz * @param int $moodleuserid - * @param \context_module $context - * @return capquiz_user|null - * @throws \dml_exception + * @param context_module $context */ - private static function load_db_entry(capquiz $capquiz, int $moodleuserid, \context_module $context) { + private static function load_db_entry(capquiz $capquiz, int $moodleuserid, context_module $context): ?capquiz_user { global $DB; - $entry = $entry = $DB->get_record('capquiz_user', [ + $entry = $DB->get_record('capquiz_user', [ 'user_id' => $moodleuserid, - 'capquiz_id' => $capquiz->id() + 'capquiz_id' => $capquiz->id(), ]); - return $entry ? new capquiz_user($entry, $context) : null; + return empty($entry) ? null : new capquiz_user($entry, $context); } - - } diff --git a/classes/capquiz_user_rating.php b/classes/capquiz_user_rating.php index 020c555..5bfcd1f 100755 --- a/classes/capquiz_user_rating.php +++ b/classes/capquiz_user_rating.php @@ -25,7 +25,6 @@ namespace mod_capquiz; -use dml_exception; use stdClass; /** @@ -39,12 +38,12 @@ class capquiz_user_rating { /** @var stdClass $record */ - private $record; + private stdClass $record; /** - * capquiz_user constructor. + * Constructor. + * * @param stdClass $record - * @throws dml_exception */ public function __construct(stdClass $record) { $this->record = $record; @@ -54,10 +53,8 @@ public function __construct(stdClass $record) { * Loads and returns user rating from database * * @param int $questionratingid - * @return capquiz_user_rating|null - * @throws dml_exception */ - public static function load_user_rating(int $questionratingid) { + public static function load_user_rating(int $questionratingid): ?capquiz_user_rating { global $DB; $record = $DB->get_record('capquiz_question_rating', ['id' => $questionratingid]); if ($record === false) { @@ -70,22 +67,19 @@ public static function load_user_rating(int $questionratingid) { * Creates and inserts a new user rating to the database * * @param capquiz_user $user - * @param capquiz_user_rating $rating + * @param float $rating * @param bool $manual - * @return capquiz_user_rating|null */ - public static function create_user_rating($user, $rating, $manual = false) { + public static function create_user_rating(capquiz_user $user, float $rating, bool $manual = false): ?capquiz_user_rating { return self::insert_user_rating_entry($user->id(), $rating, $manual); } /** * Load information about the latest user rating for an capquiz user from the database. * - * @param int $userid - * @return capquiz_user_rating - * @throws dml_exception + * @param int $capquizuserid */ - public static function latest_user_rating_by_user($userid) { + public static function latest_user_rating_by_user(int $capquizuserid): ?capquiz_user_rating { global $DB; $sql = "SELECT cur.* FROM {capquiz_user_rating} cur @@ -96,8 +90,8 @@ public static function latest_user_rating_by_user($userid) { JOIN {capquiz_user} cu2 ON cu2.id = cur2.capquiz_user_id WHERE cu2.id = cu.id ) - AND cu.id = :user_id"; - $record = $DB->get_record_sql($sql, ['user_id' => $userid]); + AND cu.id = :capquiz_user_id"; + $record = $DB->get_record_sql($sql, ['capquiz_user_id' => $capquizuserid]); return $record ? new capquiz_user_rating($record) : null; } @@ -105,51 +99,31 @@ public static function latest_user_rating_by_user($userid) { /** * Inserts a new user rating record to the database * - * @param int $userid capquiz_user id + * @param int $capquizuserid * @param float $rating - * @param null $attemptid - * @return capquiz_user_rating|null + * @param bool $manual */ - public static function insert_user_rating_entry(int $userid, float $rating, bool $manual = false) { + public static function insert_user_rating_entry(int $capquizuserid, float $rating, bool $manual = false): capquiz_user_rating { global $DB, $USER; - $record = new stdClass(); - $record->capquiz_user_id = $userid; + $record->capquiz_user_id = $capquizuserid; $record->rating = $rating; $record->manual = $manual; $record->timecreated = time(); $record->user_id = $USER->id; - try { - $ratingid = $DB->insert_record('capquiz_user_rating', $record); - $record->id = $ratingid; - return new capquiz_user_rating($record); - } catch (dml_exception $e) { - return null; - } + $record->id = $DB->insert_record('capquiz_user_rating', $record); + return new capquiz_user_rating($record); } /** * Returns this user ratings id - * - * @return int */ public function id(): int { return $this->record->id; } - /** - * Returns the time this user rating was created - * - * @return string - */ - public function timecreated(): string { - return $this->user->timecreated; - } - /** * Returns this user ratings rating - * - * @return float */ public function rating(): float { return $this->record->rating; @@ -159,9 +133,8 @@ public function rating(): float { * Sets this user ratings rating and updates the database record * * @param float $rating - * @throws dml_exception */ - public function set_rating(float $rating) { + public function set_rating(float $rating): void { global $DB; $this->record->rating = $rating; $DB->update_record('capquiz_user_rating', $this->record); diff --git a/classes/form/view/grading_configuration_form.php b/classes/form/view/grading_configuration_form.php index becea8d..65852fe 100644 --- a/classes/form/view/grading_configuration_form.php +++ b/classes/form/view/grading_configuration_form.php @@ -26,7 +26,7 @@ namespace mod_capquiz\form\view; use mod_capquiz\capquiz; -use mod_capquiz\capquiz_question_list; +use moodle_url; defined('MOODLE_INTERNAL') || die(); @@ -43,14 +43,15 @@ class grading_configuration_form extends \moodleform { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; /** - * grading_configuration_form constructor. + * Constructor. + * * @param capquiz $capquiz - * @param \moodle_url $url + * @param moodle_url $url */ - public function __construct(capquiz $capquiz, \moodle_url $url) { + public function __construct(capquiz $capquiz, moodle_url $url) { $this->capquiz = $capquiz; parent::__construct($url); } @@ -58,7 +59,7 @@ public function __construct(capquiz $capquiz, \moodle_url $url) { /** * Defines form */ - public function definition() { + public function definition(): void { $qlist = $this->capquiz->question_list(); $form = $this->_form; $form->addElement('text', 'default_user_rating', get_string('default_user_rating', 'capquiz')); @@ -106,7 +107,7 @@ public function definition() { * @return array of "element_name"=>"error_description" if there are errors, * or an empty array if everything is OK (true allowed for backwards compatibility too). */ - public function validations($data, $files) { + public function validations($data, $files): array { $errors = []; if (empty($data['default_user_rating'])) { $errors['default_user_rating'] = get_string('default_user_rating_required', 'capquiz'); diff --git a/classes/form/view/matchmaking_strategy_selection_form.php b/classes/form/view/matchmaking_strategy_selection_form.php index 29529f2..5b25326 100755 --- a/classes/form/view/matchmaking_strategy_selection_form.php +++ b/classes/form/view/matchmaking_strategy_selection_form.php @@ -28,6 +28,7 @@ use mod_capquiz\capquiz; use mod_capquiz\capquiz_matchmaking_strategy_loader; use mod_capquiz\capquiz_matchmaking_strategy_registry; +use moodle_url; defined('MOODLE_INTERNAL') || die(); @@ -43,14 +44,15 @@ class matchmaking_strategy_selection_form extends \moodleform { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; /** - * matchmaking_strategy_selection_form constructor. + * Constructor. + * * @param capquiz $capquiz - * @param \moodle_url $url + * @param moodle_url $url */ - public function __construct(capquiz $capquiz, \moodle_url $url) { + public function __construct(capquiz $capquiz, moodle_url $url) { $this->capquiz = $capquiz; parent::__construct($url); } @@ -58,7 +60,7 @@ public function __construct(capquiz $capquiz, \moodle_url $url) { /** * Defines form */ - public function definition() { + public function definition(): void { $form = $this->_form; $loader = new capquiz_matchmaking_strategy_loader($this->capquiz); $registry = new capquiz_matchmaking_strategy_registry($this->capquiz); @@ -89,7 +91,7 @@ public function definition() { * @return array of "element_name"=>"error_description" if there are errors, * or an empty array if everything is OK (true allowed for backwards compatibility too). */ - public function validations($data, $files) { + public function validations($data, $files): array { return []; } diff --git a/classes/form/view/question_list_create_form.php b/classes/form/view/question_list_create_form.php index 6bf17f6..63c5d78 100755 --- a/classes/form/view/question_list_create_form.php +++ b/classes/form/view/question_list_create_form.php @@ -42,7 +42,7 @@ class question_list_create_form extends \moodleform { /** * Defines form */ - public function definition() { + public function definition(): void { $form = $this->_form; $form->addElement('text', 'title', get_string('title', 'capquiz')); $form->setType('title', PARAM_TEXT); @@ -74,7 +74,7 @@ public function definition() { * @return array of "element_name"=>"error_description" if there are errors, * or an empty array if everything is OK (true allowed for backwards compatibility too). */ - public function validations($data, $files) { + public function validations($data, $files): array { $errors = []; if (empty($data['title'])) { $errors['title'] = get_string('title_required', 'capquiz'); diff --git a/classes/form/view/rating_system_selection_form.php b/classes/form/view/rating_system_selection_form.php index 771e7b3..c95401f 100755 --- a/classes/form/view/rating_system_selection_form.php +++ b/classes/form/view/rating_system_selection_form.php @@ -28,6 +28,7 @@ use mod_capquiz\capquiz; use mod_capquiz\capquiz_rating_system_loader; use mod_capquiz\capquiz_rating_system_registry; +use moodle_url; defined('MOODLE_INTERNAL') || die(); @@ -42,15 +43,17 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class rating_system_selection_form extends \moodleform { + /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; /** - * rating_system_selection_form constructor. + * Constructor. + * * @param capquiz $capquiz - * @param \moodle_url $url + * @param moodle_url $url */ - public function __construct(capquiz $capquiz, \moodle_url $url) { + public function __construct(capquiz $capquiz, moodle_url $url) { $this->capquiz = $capquiz; parent::__construct($url); } @@ -58,7 +61,7 @@ public function __construct(capquiz $capquiz, \moodle_url $url) { /** * Defines form */ - public function definition() { + public function definition(): void { $form = $this->_form; $loader = new capquiz_rating_system_loader($this->capquiz); $registry = new capquiz_rating_system_registry(); @@ -69,9 +72,7 @@ public function definition() { if ($loader->current_rating_system_name() === $ratingsystem) { $selectedindex = $index; } - $radioarray[] = $form->createElement('radio', 'rating_system', '', $ratingsystem, $index, [ - $ratingsystem - ]); + $radioarray[] = $form->createElement('radio', 'rating_system', '', $ratingsystem, $index, [$ratingsystem]); $index++; } $form->addGroup($radioarray, 'radioar', '', '
', false); @@ -89,7 +90,7 @@ public function definition() { * @return array of "element_name"=>"error_description" if there are errors, * or an empty array if everything is OK (true allowed for backwards compatibility too). */ - public function validations($data, $files) { + public function validations($data, $files): array { return []; } diff --git a/classes/matchmaking/capquiz_matchmaking_strategy_registry.php b/classes/matchmaking/capquiz_matchmaking_strategy_registry.php index a6d1098..1ec206e 100755 --- a/classes/matchmaking/capquiz_matchmaking_strategy_registry.php +++ b/classes/matchmaking/capquiz_matchmaking_strategy_registry.php @@ -25,6 +25,10 @@ namespace mod_capquiz; +use coding_exception; +use moodle_url; +use stdClass; + defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/mod/capquiz/classes/capquiz_matchmaking_strategy.php'); @@ -43,13 +47,14 @@ class capquiz_matchmaking_strategy_registry { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; /** @var array $strategies */ - private $strategies; + private array $strategies; /** - * capquiz_matchmaking_strategy_registry constructor. + * Constructor. + * * @param capquiz $capquiz */ public function __construct(capquiz $capquiz) { @@ -61,11 +66,10 @@ public function __construct(capquiz $capquiz) { * Returns the specified matchmaking strategy or throws an error if it does not exist * * @param string $strategy - * @return capquiz_matchmaking_strategy - * @throws \Exception */ - public function selector(string $strategy) { - if ($value = $this->strategies[$strategy]) { + public function selector(string $strategy): capquiz_matchmaking_strategy { + $value = $this->strategies[$strategy]; + if ($value) { return array_values($value)[0](); } $this->throw_strategy_exception($strategy); @@ -75,12 +79,10 @@ public function selector(string $strategy) { * Returns a configuration form for the matchmaking strategy * * @param string $strategy - * @param \stdClass $config - * @param \moodle_url $url - * @return mixed - * @throws \Exception + * @param stdClass $config + * @param moodle_url $url */ - public function configuration_form(string $strategy, \stdClass $config, \moodle_url $url) { + public function configuration_form(string $strategy, stdClass $config, moodle_url $url) { $value = $this->strategies[$strategy]; if ($value) { $configfunc = array_values($value)[1]; @@ -93,21 +95,15 @@ public function configuration_form(string $strategy, \stdClass $config, \moodle_ * Returns true if the registry has the specified strategy * * @param string $strategy - * @return bool */ - public function has_strategy(string $strategy) : bool { - if ($value = $this->strategies[$strategy]) { - return true; - } - return false; + public function has_strategy(string $strategy): bool { + return isset($this->strategies[$strategy]); } /** * Returns the default selection strategy - * - * @return string */ - public function default_selection_strategy() : string { + public function default_selection_strategy(): string { // The default selection strategy is added first. // Modify capquiz_matchmaking_strategy_registry::register_selection_strategies() to change this. $selectionstrategies = $this->selection_strategies(); @@ -119,7 +115,7 @@ public function default_selection_strategy() : string { * * @return string[] */ - public function selection_strategies() : array { + public function selection_strategies(): array { $names = []; foreach (array_keys($this->strategies) as $value) { $names[] = $value; @@ -130,26 +126,18 @@ public function selection_strategies() : array { /** * Registers the selection strategies, the first registered will be the default strategy */ - private function register_selection_strategies() { + private function register_selection_strategies(): void { // The first listed will be selected by default when creating a new activity. $capquiz = $this->capquiz; $this->strategies = [ 'N-closest' => [ - function () use ($capquiz) { - return new n_closest_selector($capquiz); - }, - function (\moodle_url $url, \stdClass $configuration) { - return new n_closest_configuration_form($configuration, $url); - } + fn() => new n_closest_selector($capquiz), + fn(moodle_url $url, stdClass $config) => new n_closest_configuration_form($config, $url), ], 'Chronological' => [ - function () use ($capquiz) { - return new chronologic_selector(); - }, - function (\moodle_url $url, \stdClass $configuration) { - return null; - } - ] + fn() => new chronologic_selector(), + fn(moodle_url $url, stdClass $config) => null, + ], ]; } @@ -157,12 +145,11 @@ function (\moodle_url $url, \stdClass $configuration) { * Creates and throws a strategy exception * * @param string $strategy - * @throws \Exception */ private function throw_strategy_exception(string $strategy) { $msg = "The specified strategy '$strategy' does not exist."; $msg .= " Options are {'" . implode("', '", $this->selection_strategies()); $msg .= "'}. This issue must be fixed by a programmer"; - throw new \Exception($msg); + throw new coding_exception($msg); } } diff --git a/classes/matchmaking/chronologic/chronologic_selector.php b/classes/matchmaking/chronologic/chronologic_selector.php index 86cb459..f09e45a 100755 --- a/classes/matchmaking/chronologic/chronologic_selector.php +++ b/classes/matchmaking/chronologic/chronologic_selector.php @@ -25,6 +25,8 @@ namespace mod_capquiz; +use stdClass; + /** * Class chronologic_selector * @@ -38,29 +40,23 @@ class chronologic_selector extends capquiz_matchmaking_strategy { /** * Nothing to configure * - * @param \stdClass $configuration - * @return mixed|void + * @param stdClass $config */ - public function configure(\stdClass $configuration) { - + public function configure(stdClass $config): void { } /** * No configuration needed - * - * @return null */ - public function configuration() { - return null; + public function configuration(): stdClass { + return new stdClass(); } /** * No configuration needed - * - * @return null */ - public function default_configuration() { - return null; + public function default_configuration(): stdClass { + return new stdClass(); } /** @@ -68,13 +64,13 @@ public function default_configuration() { * * @param capquiz_user $user * @param capquiz_question_list $qlist - * @param array $inactiveattempts - * @return capquiz_question|null + * @param capquiz_question_attempt[] $inactiveattempts */ - public function next_question_for_user(capquiz_user $user, capquiz_question_list $qlist, array $inactiveattempts) { + public function next_question_for_user(capquiz_user $user, capquiz_question_list $qlist, + array $inactiveattempts): ?capquiz_question { $answered = function (capquiz_question $q) use ($inactiveattempts) { - foreach ($inactiveattempts as $attempt) { - if ($attempt->question_id() === $q->id()) { + foreach ($inactiveattempts as $inactiveattempt) { + if ($inactiveattempt->question_id() === $q->id()) { return true; } } diff --git a/classes/matchmaking/n_closest/n_closest_configuration_form.php b/classes/matchmaking/n_closest/n_closest_configuration_form.php index c06c97f..6d91a37 100755 --- a/classes/matchmaking/n_closest/n_closest_configuration_form.php +++ b/classes/matchmaking/n_closest/n_closest_configuration_form.php @@ -25,7 +25,8 @@ namespace mod_capquiz; -use mod_capquiz\capquiz; +use moodle_url; +use stdClass; defined('MOODLE_INTERNAL') || die(); @@ -41,25 +42,24 @@ */ class n_closest_configuration_form extends \moodleform { - /** @var \stdClass $configuration */ - private $configuration; + /** @var stdClass $configuration */ + private stdClass $configuration; /** - * n_closest_configuration_form constructor. - * @param \stdClass $configuration - * @param \moodle_url $url + * Constructor. + * + * @param stdClass $configuration + * @param moodle_url $url */ - public function __construct(\stdClass $configuration, \moodle_url $url) { + public function __construct(stdClass $configuration, moodle_url $url) { $this->configuration = $configuration; parent::__construct($url); } /** * Defines form - * - * @throws \coding_exception */ - public function definition() { + public function definition(): void { $form = $this->_form; $form->addElement('text', 'number_of_questions_to_select', get_string('number_of_questions_to_select', 'capquiz')); @@ -89,14 +89,12 @@ public function definition() { /** * Validate the data from the form. * - * * @param array $data array of ("fieldname"=>value) of submitted data * @param array $files array of uploaded files "element_name"=>tmp_file_path * @return array of "element_name"=>"error_description" if there are errors, * or an empty array if everything is OK (true allowed for backwards compatibility too). - * @throws \coding_exception */ - public function validations($data, $files) { + public function validations($data, $files): array { $errors = []; if (empty($data['user_win_probability'])) { $errors['user_win_probability'] = get_string('user_win_probability_required', 'capquiz'); diff --git a/classes/matchmaking/n_closest/n_closest_selector.php b/classes/matchmaking/n_closest/n_closest_selector.php index cc06867..4a2221a 100755 --- a/classes/matchmaking/n_closest/n_closest_selector.php +++ b/classes/matchmaking/n_closest/n_closest_selector.php @@ -25,6 +25,8 @@ namespace mod_capquiz; +use stdClass; + /** * Class n_closest_selector * @@ -36,19 +38,20 @@ class n_closest_selector extends capquiz_matchmaking_strategy { /** @var capquiz The capquiz */ - private $capquiz; + private capquiz $capquiz; /** @var float The propability of the user winning */ - private $userwinprobability; + private float $userwinprobability; /** @var int The number of questions to select */ - private $numquestionstoselect; + private int $numquestionstoselect; /** @var int The number of turns between each time a question can be selected */ - private $preventsamequestionforturns; + private int $preventsamequestionforturns; /** - * n_closest_selector constructor. + * Constructor. + * * @param capquiz $capquiz */ public function __construct(capquiz $capquiz) { @@ -59,10 +62,9 @@ public function __construct(capquiz $capquiz) { /** * Configure the strategy * - * @param \stdClass $configuration - * @return mixed|void + * @param stdClass $configuration */ - public function configure(\stdClass $configuration) /*: void*/ { + public function configure(stdClass $configuration): void { if ($configuration->user_win_probability > 0) { $this->userwinprobability = $configuration->user_win_probability; } @@ -76,11 +78,9 @@ public function configure(\stdClass $configuration) /*: void*/ { /** * Returns the current strategy configuration - * - * @return \stdClass */ - public function configuration() : \stdClass { - $config = new \stdClass; + public function configuration(): stdClass { + $config = new stdClass; $config->prevent_same_question_for_turns = $this->preventsamequestionforturns; $config->user_win_probability = $this->userwinprobability; $config->number_of_questions_to_select = $this->numquestionstoselect; @@ -89,11 +89,9 @@ public function configuration() : \stdClass { /** * Returns the default strategy configuration - * - * @return \stdClass */ - public function default_configuration() : \stdClass { - $config = new \stdClass; + public function default_configuration(): stdClass { + $config = new stdClass; $config->user_win_probability = 0.75; $config->prevent_same_question_for_turns = 0; $config->number_of_questions_to_select = 10; @@ -106,9 +104,9 @@ public function default_configuration() : \stdClass { * @param capquiz_user $user * @param capquiz_question_list $qlist * @param array $inactiveattempts - * @return capquiz_question|null */ - public function next_question_for_user(capquiz_user $user, capquiz_question_list $qlist, array $inactiveattempts) { + public function next_question_for_user(capquiz_user $user, capquiz_question_list $qlist, + array $inactiveattempts): ?capquiz_question { $excluded = $this->determine_excluded_questions($inactiveattempts); $candidates = $this->find_questions_closest_to_rating($user, $excluded); if (count($candidates) === 0) { @@ -126,10 +124,8 @@ public function next_question_for_user(capquiz_user $user, capquiz_question_list * * @param capquiz_user $user * @param array $excludedquestions - * @return array - * @throws \dml_exception */ - private function find_questions_closest_to_rating(capquiz_user $user, array $excludedquestions) : array { + private function find_questions_closest_to_rating(capquiz_user $user, array $excludedquestions): array { global $DB; $sql = 'SELECT * FROM {capquiz_question} WHERE question_list_id = ?'; $sql .= str_repeat(' AND id <> ?', count($excludedquestions)); @@ -152,19 +148,17 @@ private function find_questions_closest_to_rating(capquiz_user $user, array $exc * Returns the ideal question rating * * @param capquiz_user $user - * @return float */ - private function ideal_question_rating(capquiz_user $user) : float { + private function ideal_question_rating(capquiz_user $user): float { return 400.0 * log((1.0 / $this->userwinprobability) - 1.0, 10.0) + $user->rating(); } /** * Identifies questions to exclude and returns them in an array * - * @param array $inactiveattempts - * @return array + * @param capquiz_question_attempt[] $inactiveattempts */ - private function determine_excluded_questions(array $inactiveattempts) : array { + private function determine_excluded_questions(array $inactiveattempts): array { $it = new \ArrayIterator(array_reverse($inactiveattempts, true)); $excluded = []; for ($i = 0; $i < $this->preventsamequestionforturns; $i++) { diff --git a/classes/output/basic_renderer.php b/classes/output/basic_renderer.php index 6ecb5f8..2309030 100755 --- a/classes/output/basic_renderer.php +++ b/classes/output/basic_renderer.php @@ -26,6 +26,8 @@ namespace mod_capquiz\output; use mod_capquiz\capquiz_urls; +use moodle_url; +use renderer_base; /** * Class basic_renderer @@ -39,48 +41,39 @@ class basic_renderer { /** * Renders the home button * - * @param renderer $renderer - * @return string - * @throws \coding_exception - * @throws \moodle_exception + * @param renderer_base $renderer */ - public static function render_home_button(renderer $renderer) { - return self::render_action_button($renderer, capquiz_urls::redirect(capquiz_urls::view_url()), - get_string('home', 'capquiz')); + public static function render_home_button(renderer_base $renderer): string { + $url = capquiz_urls::redirect(capquiz_urls::view_url()); + return self::render_action_button($renderer, $url, get_string('home', 'capquiz')); } /** * Renders a button * - * @param renderer $renderer - * @param \moodle_url $url + * @param renderer_base $renderer + * @param moodle_url $url * @param string $label * @param string $httpmethod The HTTP method to use for the form * @param string[] $params The keys are used as names * @param string $id - * @return string - * @throws \coding_exception - * @throws \moodle_exception */ - public static function render_action_button(renderer $renderer, \moodle_url $url, - string $label, string $httpmethod = 'post', array $params = [], string $id = '') { + public static function render_action_button(renderer_base $renderer, moodle_url $url, string $label, + string $httpmethod = 'post', array $params = [], string $id = ''): string { $paramobjects = []; foreach ($params as $name => $value) { $paramobjects = [ 'name' => $name, - 'value' => $value + 'value' => $value, ]; } - $html = $renderer->render_from_template('capquiz/button', [ - 'button' => [ - 'primary' => true, - 'method' => $httpmethod, - 'url' => $url->out(false), - 'label' => $label, - 'params' => $paramobjects, - 'id' => $id - ] + return $renderer->render_from_template('core/single_button', [ + 'type' => 'primary', + 'method' => $httpmethod, + 'url' => $url->out(false), + 'label' => $label, + 'params' => $paramobjects, + 'id' => $id, ]); - return $html; } } diff --git a/classes/output/classlist_renderer.php b/classes/output/classlist_renderer.php index 09f8c25..17d600c 100755 --- a/classes/output/classlist_renderer.php +++ b/classes/output/classlist_renderer.php @@ -29,6 +29,8 @@ use mod_capquiz\capquiz; use mod_capquiz\capquiz_urls; use mod_capquiz\capquiz_user; +use moodle_page; +use renderer_base; defined('MOODLE_INTERNAL') || die(); @@ -46,19 +48,21 @@ class classlist_renderer { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; - /** @var renderer $renderer */ - private $renderer; - /** @var \moodle_page $page */ - private $page; + /** @var renderer_base $renderer */ + private renderer_base $renderer; + + /** @var moodle_page $page */ + private moodle_page $page; /** - * classlist_renderer constructor. + * Constructor. + * * @param capquiz $capquiz The capquiz whose classlist should be rendered - * @param renderer $renderer The renderer used to render the classlist + * @param renderer_base $renderer The renderer used to render the classlist */ - public function __construct(capquiz $capquiz, renderer $renderer) { + public function __construct(capquiz $capquiz, renderer_base $renderer) { $this->capquiz = $capquiz; $this->renderer = $renderer; $this->page = $capquiz->get_page(); @@ -66,10 +70,8 @@ public function __construct(capquiz $capquiz, renderer $renderer) { /** * Renders the entire classlist of the $capquiz in the constructor - * - * @return bool|string */ - public function render() { + public function render(): bool|string { $cmid = $this->capquiz->course_module()->id; $this->page->requires->js_call_amd('mod_capquiz/edit_questions', 'initialize', [$cmid]); $users = capquiz_user::list_users($this->capquiz->id(), $this->capquiz->context()); @@ -84,21 +86,20 @@ public function render() { 'rating' => round($user->rating(), 2), 'stars' => $user->highest_stars_achieved(), 'graded_stars' => $user->highest_stars_graded(), - 'passing_grade' => $user->highest_stars_graded() >= $this->capquiz->stars_to_pass() + 'passing_grade' => $user->highest_stars_graded() >= $this->capquiz->stars_to_pass(), ]; } - $leaderboard = $this->renderer->render_from_template('capquiz/classlist', [ + return $this->renderer->render_from_template('capquiz/classlist', [ 'users' => $rows, 'regrade' => [ + 'type' => 'primary', 'method' => 'post', 'classes' => 'capquiz-regrade-all', 'url' => capquiz_urls::regrade_all_url()->out(false), - 'primary' => true, 'label' => get_string('regrade_all', 'capquiz'), - 'disabled' => !$this->capquiz->is_grading_completed() - ] + 'disabled' => !$this->capquiz->is_grading_completed(), + ], ]); - return $leaderboard; } } diff --git a/classes/output/grading_configuration_renderer.php b/classes/output/grading_configuration_renderer.php index 22683cc..426669a 100644 --- a/classes/output/grading_configuration_renderer.php +++ b/classes/output/grading_configuration_renderer.php @@ -28,6 +28,8 @@ use mod_capquiz\capquiz; use mod_capquiz\capquiz_urls; use mod_capquiz\form\view\grading_configuration_form; +use moodle_page; +use stdClass; defined('MOODLE_INTERNAL') || die(); @@ -44,16 +46,17 @@ class grading_configuration_renderer { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; /** @var renderer $renderer */ - private $renderer; + private renderer $renderer; - /** @var \moodle_page $page */ - private $page; + /** @var moodle_page $page */ + private moodle_page $page; /** - * grading_configuration_renderer constructor. + * Constructor. + * * @param capquiz $capquiz * @param renderer $renderer */ @@ -65,22 +68,17 @@ public function __construct(capquiz $capquiz, renderer $renderer) { /** * Render grading configuration view - * - * @return bool|string - * @throws \moodle_exception */ - public function render() { + public function render(): bool|string { return $this->renderer->render_from_template('capquiz/configure_grading', [ - 'rating_form' => $this->get_rating_configuration() + 'rating_form' => $this->get_rating_configuration(), ]); } /** * Returns rating configuration form - * - * @return string */ - private function get_rating_configuration() { + private function get_rating_configuration(): string { $url = $this->page->url; $form = new grading_configuration_form($this->capquiz, $url); $formdata = $form->get_data(); @@ -93,11 +91,9 @@ private function get_rating_configuration() { /** * Processes the rating configuration formdata * - * @param object $formdata - * @throws \dml_exception - * @throws \moodle_exception + * @param stdClass $formdata */ - private function process_rating_configuration($formdata) { + private function process_rating_configuration(stdClass $formdata): void { $star = 1; $ratings = []; while (isset($formdata->{"star_rating_$star"})) { diff --git a/classes/output/import_renderer.php b/classes/output/import_renderer.php index 4af590a..8a457b2 100644 --- a/classes/output/import_renderer.php +++ b/classes/output/import_renderer.php @@ -25,8 +25,10 @@ namespace mod_capquiz\output; +use context_course; use mod_capquiz\capquiz; use mod_capquiz\capquiz_urls; +use renderer_base; /** * Class import_renderer @@ -39,17 +41,18 @@ class import_renderer { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; - /** @var renderer $renderer */ - private $renderer; + /** @var renderer_base $renderer */ + private renderer_base $renderer; /** - * import_renderer constructor. + * Constructor. + * * @param capquiz $capquiz The current capquiz - * @param renderer $renderer The renderer to be used by this instance + * @param renderer_base $renderer The renderer to be used by this instance */ - public function __construct(capquiz $capquiz, renderer $renderer) { + public function __construct(capquiz $capquiz, renderer_base $renderer) { $this->capquiz = $capquiz; $this->renderer = $renderer; } @@ -59,9 +62,8 @@ public function __construct(capquiz $capquiz, renderer $renderer) { * * @param int $qlistid the id of the list with the question * @return array Array of all questions in list $qlistid - * @throws \dml_exception */ - private function get_questions_in_list(int $qlistid) : array { + private function get_questions_in_list(int $qlistid): array { global $DB; $sql = 'SELECT cq.id AS id, cq.rating AS rating, @@ -76,13 +78,10 @@ private function get_questions_in_list(int $qlistid) : array { /** * Get list of all questions - * - * @return array - * @throws \dml_exception */ - private function get_question_lists() : array { + private function get_question_lists(): array { global $DB; - $path = \context_course::instance($this->capquiz->course()->id)->path; + $path = context_course::instance($this->capquiz->course()->id)->path; $sql = 'SELECT DISTINCT cql.* FROM {capquiz_question_list} cql JOIN {context} ctx @@ -95,13 +94,8 @@ private function get_question_lists() : array { /** * Render - * - * @return bool|string - * @throws \coding_exception - * @throws \dml_exception - * @throws \moodle_exception */ - public function render() { + public function render(): bool|string { $srcqlists = $this->get_question_lists(); $qlists = []; foreach ($srcqlists as $srcqlist) { @@ -115,17 +109,17 @@ public function render() { 'description' => $srcqlist->description, 'questions' => $questions, 'merge' => [ - 'primary' => true, + 'type' => 'primary', 'method' => 'post', 'url' => capquiz_urls::merge_qlist($srcqlist->id)->out(false), - 'label' => get_string('merge', 'capquiz') + 'label' => get_string('merge', 'capquiz'), ], 'delete' => [ - 'primary' => false, + 'type' => 'danger', 'method' => 'post', 'url' => capquiz_urls::delete_qlist($srcqlist->id)->out(false), - 'label' => get_string('delete') - ] + 'label' => get_string('delete'), + ], ]; } return $this->renderer->render_from_template('capquiz/merge_with_question_list', ['lists' => $qlists]); diff --git a/classes/output/instructor_dashboard_renderer.php b/classes/output/instructor_dashboard_renderer.php index 7621147..c459b7f 100755 --- a/classes/output/instructor_dashboard_renderer.php +++ b/classes/output/instructor_dashboard_renderer.php @@ -28,6 +28,7 @@ use mod_capquiz\capquiz; use mod_capquiz\capquiz_urls; use mod_capquiz\capquiz_user; +use renderer_base; defined('MOODLE_INTERNAL') || die(); @@ -44,27 +45,26 @@ class instructor_dashboard_renderer { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; - /** @var renderer $renderer */ - private $renderer; + /** @var renderer_base $renderer */ + private renderer_base $renderer; /** - * instructor_dashboard_renderer constructor. + * Constructor. + * * @param capquiz $capquiz - * @param renderer $renderer + * @param renderer_base $renderer */ - public function __construct(capquiz $capquiz, renderer $renderer) { + public function __construct(capquiz $capquiz, renderer_base $renderer) { $this->capquiz = $capquiz; $this->renderer = $renderer; } /** * Render instructor dashboard - * - * @return string */ - public function render() { + public function render(): string { $html = $this->render_summary(); $html .= $this->render_publish(); $html .= $this->render_template(); @@ -73,37 +73,24 @@ public function render() { /** * Render the instructor dashboard summary - * - * @return bool|string - * @throws \coding_exception - * @throws \dml_exception - * @throws \moodle_exception */ - private function render_summary() { + private function render_summary(): bool|string { $qlist = $this->capquiz->question_list(); if (!$qlist) { return 'question list error'; } - $strpublished = get_string('published', 'capquiz'); - $strnotpublished = get_string('not_published', 'capquiz'); - $strnoqlistassigned = get_string('no_question_list_assigned', 'capquiz'); - $strnoquestions = get_string('no_questions', 'capquiz'); return $this->renderer->render_from_template('capquiz/instructor_dashboard_summary', [ - 'published_status' => $this->capquiz->is_published() ? $strpublished : $strnotpublished, - 'question_list_title' => $qlist ? $qlist->title() : $strnoqlistassigned, - 'question_count' => $qlist ? $qlist->question_count() : $strnoquestions, - 'enrolled_student_count' => capquiz_user::user_count($this->capquiz->id()) + 'published_status' => get_string($this->capquiz->is_published() ? 'published' : 'not_published', 'capquiz'), + 'question_list_title' => $qlist->title(), + 'question_count' => $qlist->question_count(), + 'enrolled_student_count' => capquiz_user::user_count($this->capquiz->id()), ]); } /** * Renders publish button - * - * @return bool|string - * @throws \coding_exception - * @throws \moodle_exception */ - private function render_publish() { + private function render_publish(): bool|string { $published = $this->capquiz->is_published(); $canpublish = $this->capquiz->can_publish(); $qlist = $this->capquiz->question_list(); @@ -120,18 +107,14 @@ private function render_publish() { } return $this->renderer->render_from_template('capquiz/instructor_dashboard_publish', [ 'publish' => $this->publish_button(), - 'message' => $message ? $message : false + 'message' => $message ?: false, ]); } /** * Renders template - * - * @return bool|string - * @throws \coding_exception - * @throws \moodle_exception */ - private function render_template() { + private function render_template(): bool|string { $qlist = $this->capquiz->question_list(); if (!$qlist) { return 'question list error'; @@ -142,39 +125,33 @@ private function render_template() { } return $this->renderer->render_from_template('capquiz/instructor_dashboard_template', [ 'create_template' => $this->create_template_button(), - 'message' => $message ? $message : false + 'message' => $message ?: false, ]); } /** * Creates publish button - * - * @return array - * @throws \coding_exception */ - private function publish_button() { + private function publish_button(): array { return [ - 'primary' => true, + 'type' => 'primary', 'method' => 'post', 'url' => capquiz_urls::question_list_publish_url($this->capquiz->question_list())->out(false), 'label' => get_string('publish', 'capquiz'), - 'disabled' => !$this->capquiz->can_publish() ? true : false + 'disabled' => !$this->capquiz->can_publish(), ]; } /** * Creates create template button - * - * @return array - * @throws \coding_exception */ - private function create_template_button() { + private function create_template_button(): array { return [ - 'primary' => true, + 'type' => 'primary', 'method' => 'post', 'url' => capquiz_urls::question_list_create_template_url($this->capquiz->question_list())->out(false), 'label' => get_string('create_template', 'capquiz'), - 'disabled' => !$this->capquiz->question_list()->has_questions() ? true : false + 'disabled' => !$this->capquiz->question_list()->has_questions(), ]; } } diff --git a/classes/output/matchmaking_configuration_renderer.php b/classes/output/matchmaking_configuration_renderer.php index b81c15e..c720301 100644 --- a/classes/output/matchmaking_configuration_renderer.php +++ b/classes/output/matchmaking_configuration_renderer.php @@ -28,6 +28,7 @@ use mod_capquiz\capquiz; use mod_capquiz\capquiz_matchmaking_strategy_loader; use mod_capquiz\capquiz_urls; +use moodle_page; defined('MOODLE_INTERNAL') || die(); @@ -44,16 +45,16 @@ class matchmaking_configuration_renderer { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; /** @var renderer $renderer */ - private $renderer; + private renderer $renderer; - /** @var \mod_capquiz\capquiz_matchmaking_strategy_loader $registry */ - private $registry; + /** @var capquiz_matchmaking_strategy_loader $registry */ + private capquiz_matchmaking_strategy_loader $registry; - /** @var \moodle_page $page */ - private $page; + /** @var moodle_page $page */ + private moodle_page $page; /** * matchmaking_configuration_renderer constructor. @@ -69,12 +70,8 @@ public function __construct(capquiz $capquiz, renderer $renderer) { /** * Calls submethod that renders the matchmaking_configuration view - * - * @return bool|string - * @throws \coding_exception - * @throws \moodle_exception */ - public function render() { + public function render(): bool|string { if ($this->registry->has_strategy()) { return $this->render_configuration(); } else { @@ -84,28 +81,19 @@ public function render() { /** * Renders the matchmaking configuration view - * - * @return bool|string - * @throws \moodle_exception */ - private function render_configuration() { - $html = $this->render_form(); + private function render_configuration(): bool|string { $strategy = $this->registry->current_strategy_name(); - $localized = capquiz_matchmaking_strategy_loader::localized_strategy_name($strategy); return $this->renderer->render_from_template('capquiz/matchmaking_configuration', [ - 'strategy' => $localized, - 'form' => $html + 'strategy' => capquiz_matchmaking_strategy_loader::localized_strategy_name($strategy), + 'form' => $this->render_form(), ]); } /** * Returns the rendered matchmaking configuration form - * - * @return \lang_string|string - * @throws \coding_exception - * @throws \moodle_exception */ - private function render_form() { + private function render_form(): string { $url = $this->page->url; if ($form = $this->registry->configuration_form($url)) { $formdata = $form->get_data(); diff --git a/classes/output/matchmaking_strategy_selection_renderer.php b/classes/output/matchmaking_strategy_selection_renderer.php index d398322..76c24ab 100644 --- a/classes/output/matchmaking_strategy_selection_renderer.php +++ b/classes/output/matchmaking_strategy_selection_renderer.php @@ -30,6 +30,8 @@ use mod_capquiz\capquiz_matchmaking_strategy_registry; use mod_capquiz\capquiz_urls; use mod_capquiz\form\view\matchmaking_strategy_selection_form; +use moodle_page; +use moodle_url; /** * class matchmaking_strategy_selection_renderer @@ -41,17 +43,17 @@ */ class matchmaking_strategy_selection_renderer { - /** @var \moodle_url $url */ - private $url; + /** @var moodle_url $url */ + private moodle_url $url; /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; /** @var renderer $renderer */ - private $renderer; + private renderer $renderer; - /** @var \moodle_page $page */ - private $page; + /** @var moodle_page $page */ + private moodle_page $page; /** * matchmaking_strategy_selection_renderer constructor. @@ -69,19 +71,16 @@ public function __construct(capquiz $capquiz, renderer $renderer) { /** * Sets redirect url * - * @param \moodle_url $url + * @param moodle_url $url */ - public function set_redirect_url(\moodle_url $url) { + public function set_redirect_url(moodle_url $url): void { $this->url = $url; } /** * Renders the matchmaking strategy selection form - * - * @return bool|string - * @throws \moodle_exception */ - public function render() { + public function render(): bool|string { $url = $this->page->url; $form = new matchmaking_strategy_selection_form($this->capquiz, $url); $formdata = $form->get_data(); @@ -93,7 +92,7 @@ public function render() { redirect($this->url); } return $this->renderer->render_from_template('capquiz/matchmaking_selection_strategy', [ - 'form' => $form->render() + 'form' => $form->render(), ]); } diff --git a/classes/output/question_attempt_renderer.php b/classes/output/question_attempt_renderer.php index be1c13d..68ea873 100755 --- a/classes/output/question_attempt_renderer.php +++ b/classes/output/question_attempt_renderer.php @@ -25,12 +25,16 @@ namespace mod_capquiz\output; +use core\context\module; use mod_capquiz\capquiz; use mod_capquiz\capquiz_question_list; use mod_capquiz\capquiz_user; use mod_capquiz\capquiz_urls; use mod_capquiz\capquiz_question; use mod_capquiz\capquiz_question_attempt; +use moodle_page; +use question_display_options; +use renderer_base; /** * Class question_attempt_renderer @@ -43,20 +47,21 @@ class question_attempt_renderer { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; - /** @var renderer $renderer */ - private $renderer; + /** @var renderer_base $renderer */ + private renderer_base $renderer; - /** @var \moodle_page $page */ - private $page; + /** @var moodle_page $page */ + private moodle_page $page; /** - * question_attempt_renderer constructor. + * Constructor. + * * @param capquiz $capquiz - * @param renderer $renderer + * @param renderer_base $renderer */ - public function __construct(capquiz $capquiz, renderer $renderer) { + public function __construct(capquiz $capquiz, renderer_base $renderer) { $this->capquiz = $capquiz; $this->renderer = $renderer; $this->render_question_head_html(); @@ -66,7 +71,7 @@ public function __construct(capquiz $capquiz, renderer $renderer) { /** * Renders the question head */ - private function render_question_head_html() { + private function render_question_head_html(): void { $user = $this->capquiz->user(); $qengine = $this->capquiz->question_engine($user); if ($qengine === null) { @@ -80,11 +85,8 @@ private function render_question_head_html() { /** * Renders the question attempt view - * - * @return string - * @throws \coding_exception */ - public function render() : string { + public function render(): string { if (!$this->capquiz->is_published()) { return get_string('nothing_here_yet', 'capquiz'); } @@ -95,8 +97,9 @@ public function render() : string { if ($attempt) { if ($attempt->is_answered()) { return $this->render_review($attempt); - } else if ($attempt->is_pending()) { - return $this->render_attempt($attempt, $this->attempt_display_options()); + } + if ($attempt->is_pending()) { + return $this->render_attempt($attempt, self::attempt_display_options($this->capquiz->context())); } } return get_string('you_finished_capquiz', 'capquiz'); @@ -106,10 +109,9 @@ public function render() : string { * Render the attempt * * @param capquiz_question_attempt $attempt - * @param \question_display_options $options - * @return string + * @param question_display_options $options */ - private function render_attempt(capquiz_question_attempt $attempt, \question_display_options $options) : string { + private function render_attempt(capquiz_question_attempt $attempt, question_display_options $options): string { $user = $this->capquiz->user(); $html = $this->render_progress($user); $html .= $this->render_question_attempt($attempt, $options); @@ -120,10 +122,9 @@ private function render_attempt(capquiz_question_attempt $attempt, \question_dis * Render the attempt review * * @param capquiz_question_attempt $attempt - * @return string */ - private function render_review(capquiz_question_attempt $attempt) : string { - $html = $this->render_attempt($attempt, $this->review_display_options()); + private function render_review(capquiz_question_attempt $attempt): string { + $html = $this->render_attempt($attempt, self::review_display_options($this->capquiz->context())); $html .= $this->render_review_next_button($attempt); return $html; } @@ -132,29 +133,19 @@ private function render_review(capquiz_question_attempt $attempt) : string { * Render the review next button * * @param capquiz_question_attempt $attempt - * @return string - * @throws \coding_exception - * @throws \moodle_exception */ - public function render_review_next_button(capquiz_question_attempt $attempt) : string { - return basic_renderer::render_action_button( - $this->renderer, - capquiz_urls::response_reviewed_url($attempt), - get_string('next', 'capquiz'), - 'post', - [], - 'capquiz_review_next' - ); + public function render_review_next_button(capquiz_question_attempt $attempt): string { + $url = capquiz_urls::response_reviewed_url($attempt); + $label = get_string('next', 'capquiz'); + return basic_renderer::render_action_button($this->renderer, $url, $label, id: 'capquiz_review_next'); } /** * Render a users progress * * @param capquiz_user $user - * @return string - * @throws \moodle_exception */ - private function render_progress(capquiz_user $user) : string { + private function render_progress(capquiz_user $user): string { $qlist = $this->capquiz->question_list(); $percent = $qlist->next_level_percent($this->capquiz, $user->rating()); list($stars, $blankstars, $nostars) = $this->user_star_progress($user, $qlist); @@ -163,10 +154,10 @@ private function render_progress(capquiz_user $user) : string { 'down' => $percent < 0 ? ['percent' => -$percent] : false, 'stars' => $stars, 'blankstars' => $blankstars, - 'nostars' => $nostars + 'nostars' => $nostars, ]; return $this->renderer->render_from_template('capquiz/student_progress', [ - 'progress' => ['student' => $student] + 'progress' => ['student' => $student], ]); } @@ -174,12 +165,9 @@ private function render_progress(capquiz_user $user) : string { * Render the question attempt * * @param capquiz_question_attempt $attempt - * @param \question_display_options $options - * @return string - * @throws \coding_exception - * @throws \moodle_exception + * @param question_display_options $options */ - public function render_question_attempt(capquiz_question_attempt $attempt, \question_display_options $options) : string { + public function render_question_attempt(capquiz_question_attempt $attempt, question_display_options $options): string { $user = $this->capquiz->user(); $quba = $user->question_usage(); $this->page->requires->js_module('core_question_engine'); @@ -187,12 +175,12 @@ public function render_question_attempt(capquiz_question_attempt $attempt, \ques 'attempt' => [ 'url' => capquiz_urls::response_submit_url($attempt)->out(false), 'body' => $quba->render_question($attempt->question_slot(), $options, $attempt->question_id()), - 'slots' => '' + 'slots' => '', ], 'gradingdone' => $this->capquiz->is_grading_completed(), 'finalgrade' => $user->highest_stars_graded(), 'gradingpass' => $user->highest_stars_graded() >= $this->capquiz->stars_to_pass(), - 'duedate' => userdate($this->capquiz->time_due(), get_string('strftimedatetime', 'langconfig')) + 'duedate' => userdate($this->capquiz->time_due(), get_string('strftimedatetime', 'langconfig')), ]); } @@ -201,10 +189,8 @@ public function render_question_attempt(capquiz_question_attempt $attempt, \ques * * @param capquiz_user $user * @param capquiz_question_attempt $attempt - * @return string - * @throws \moodle_exception */ - public function render_metainfo(capquiz_user $user, capquiz_question_attempt $attempt) : string { + public function render_metainfo(capquiz_user $user, capquiz_question_attempt $attempt): string { $question = capquiz_question::load($attempt->question_id()); if ($question == null) { return 'Question was not found.'; @@ -213,13 +199,13 @@ public function render_metainfo(capquiz_user $user, capquiz_question_attempt $at 'metainfo' => [ 'rating' => [ 'student' => $user->rating(), - 'question' => $question->rating() + 'question' => $question->rating(), ], 'question' => [ 'capquiz_id' => $question->id(), - 'moodle_id' => $question->question_id() - ] - ] + 'moodle_id' => $question->question_id(), + ], + ], ]); } @@ -230,7 +216,7 @@ public function render_metainfo(capquiz_user $user, capquiz_question_attempt $at * @param capquiz_question_list $qlist * @return array[] */ - private function user_star_progress(capquiz_user $user, capquiz_question_list $qlist) : array { + private function user_star_progress(capquiz_user $user, capquiz_question_list $qlist): array { $stars = []; $blankstars = []; $nostars = []; @@ -251,33 +237,33 @@ private function user_star_progress(capquiz_user $user, capquiz_question_list $q /** * Returns the display options for the attempt review * - * @return \question_display_options + * @param module $context */ - private function review_display_options() : \question_display_options { - $options = new \question_display_options(); - $options->context = $this->capquiz->context(); + public static function review_display_options(module $context): question_display_options { + $options = new question_display_options(); + $options->context = $context; $options->readonly = true; - $options->flags = \question_display_options::VISIBLE; - $options->marks = \question_display_options::VISIBLE; - $options->rightanswer = \question_display_options::VISIBLE; - $options->numpartscorrect = \question_display_options::VISIBLE; - $options->manualcomment = \question_display_options::HIDDEN; + $options->flags = question_display_options::VISIBLE; + $options->marks = question_display_options::VISIBLE; + $options->rightanswer = question_display_options::VISIBLE; + $options->numpartscorrect = question_display_options::VISIBLE; + $options->manualcomment = question_display_options::HIDDEN; return $options; } /** * Returns the display options for the attempt * - * @return \question_display_options + * @param module $context */ - private function attempt_display_options() : \question_display_options { - $options = new \question_display_options(); - $options->context = $this->capquiz->context(); - $options->flags = \question_display_options::HIDDEN; - $options->marks = \question_display_options::HIDDEN; - $options->rightanswer = \question_display_options::HIDDEN; - $options->numpartscorrect = \question_display_options::HIDDEN; - $options->manualcomment = \question_display_options::HIDDEN; + public static function attempt_display_options(module $context): question_display_options { + $options = new question_display_options(); + $options->context = $context; + $options->flags = question_display_options::HIDDEN; + $options->marks = question_display_options::HIDDEN; + $options->rightanswer = question_display_options::HIDDEN; + $options->numpartscorrect = question_display_options::HIDDEN; + $options->manualcomment = question_display_options::HIDDEN; return $options; } diff --git a/classes/output/question_bank_renderer.php b/classes/output/question_bank_renderer.php index 74aed63..661b538 100644 --- a/classes/output/question_bank_renderer.php +++ b/classes/output/question_bank_renderer.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * This file defines a class used to render a question bank * @@ -27,7 +28,7 @@ use mod_capquiz\capquiz; use mod_capquiz\capquiz_urls; use mod_capquiz\bank\question_bank_view; -use \html_writer; +use moodle_page; /** * Class question_bank_renderer @@ -40,46 +41,32 @@ class question_bank_renderer { /** @var capquiz $capquiz */ - private $capquiz; - - /** @var renderer $renderer */ - private $renderer; - - /** @var array $pagevars */ - private $pagevars; + private capquiz $capquiz; - /** @var \moodle_page $page */ - private $page; + /** @var moodle_page $page */ + private moodle_page $page; /** * question_bank_renderer constructor. * @param capquiz $capquiz - * @param renderer $renderer */ - public function __construct(capquiz $capquiz, renderer $renderer) { + public function __construct(capquiz $capquiz) { $this->capquiz = $capquiz; - $this->renderer = $renderer; $this->page = $capquiz->get_page(); } /** * Creates question bank view - * - * @return question_bank_view */ - public function create_view() { + public function create_view(): question_bank_view { list($url, $contexts, $cmid, $cm, $capquizrecord, $pagevars) = $this->setup_question_edit(); - $this->pagevars = $pagevars; - return new question_bank_view($contexts, $url, $this->capquiz->course(), $this->capquiz->course_module()); + return new question_bank_view($contexts, $url, $this->capquiz->course(), $this->capquiz->course_module(), $pagevars); } /** * Renders question bank - * - * @return string - * @throws \coding_exception */ - public function render( ) { + public function render(): string { // phpcs:disable // $questionsperpage = optional_param('qperpage', 10, PARAM_INT); // $questionpage = optional_param('qpage', 0, PARAM_INT); @@ -88,8 +75,10 @@ public function render( ) { // phpcs:disable // $html = "

" . get_string('available_questions', 'capquiz') . "

"; // phpcs:enable - $qbank = $questionview->render( $this->pagevars, 'editq' ); - return html_writer::div(html_writer::div($qbank, 'bd'), 'questionbankformforpopup'); + ob_start(); + $questionview->display(); + $qbank = ob_get_clean(); + return \html_writer::div(\html_writer::div($qbank, 'bd'), 'questionbankformforpopup'); } /** @@ -97,14 +86,14 @@ public function render( ) { * The original function expects the course module id parameter to be "cmid", but this module gets passed "id" * Moodle coding standard does not allow us to override $_GET or $_POST before calling question_edit_setup() */ - private function setup_question_edit() { + private function setup_question_edit(): array { $params = []; $params['cmid'] = capquiz_urls::require_course_module_id_param(); $params['qpage'] = optional_param('qpage', null, PARAM_INT); $params['cat'] = optional_param('cat', null, PARAM_SEQUENCE); $params['category'] = optional_param('category', null, PARAM_SEQUENCE); $params['qperpage'] = optional_param('qperpage', null, PARAM_INT); - for ($i = 1; $i <= question_bank_view::MAX_SORTS; $i++) { + for ($i = 1; $i <= \core_question\local\bank\view::MAX_SORTS; $i++) { $param = 'qbs' . $i; if ($sort = optional_param($param, '', PARAM_TEXT)) { $params[$param] = $sort; @@ -119,7 +108,7 @@ private function setup_question_edit() { $params['qtagids'] = optional_param_array('qtagids', null, PARAM_INT); $this->page->set_pagelayout('admin'); $edittab = 'editq'; - return question_build_edit_resources($edittab, capquiz_urls::$urledit, $params); + return question_build_edit_resources($edittab, capquiz_urls::$urledit, $params); } } diff --git a/classes/output/question_list_creator_renderer.php b/classes/output/question_list_creator_renderer.php index a0dc718..be869e3 100644 --- a/classes/output/question_list_creator_renderer.php +++ b/classes/output/question_list_creator_renderer.php @@ -22,12 +22,14 @@ * @copyright 2018 NTNU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + namespace mod_capquiz\output; use mod_capquiz\capquiz; use mod_capquiz\capquiz_urls; use mod_capquiz\capquiz_question_list; use mod_capquiz\form\view\question_list_create_form; +use moodle_page; defined('MOODLE_INTERNAL') || die(); @@ -44,16 +46,17 @@ class question_list_creator_renderer { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; /** @var renderer $renderer */ - private $renderer; + private renderer $renderer; - /** @var \moodle_page $PAGE */ - private $page; + /** @var moodle_page $PAGE */ + private moodle_page $page; /** - * question_list_creator_renderer constructor. + * Constructor. + * * @param capquiz $capquiz The capquiz whose question list creator should be rendered * @param renderer $renderer The renderer used to render the question list creator */ @@ -65,11 +68,8 @@ public function __construct(capquiz $capquiz, renderer $renderer) { /** * Renders the question list creator - * - * @return bool|string - * @throws \moodle_exception */ - public function render() { + public function render(): bool|string { $url = $this->page->url; $form = new question_list_create_form($url); $formdata = $form->get_data(); @@ -79,7 +79,7 @@ public function render() { $formdata->level_2_rating, $formdata->level_3_rating, $formdata->level_4_rating, - $formdata->level_5_rating + $formdata->level_5_rating, ]; $title = $formdata->title; $description = $formdata->description; @@ -90,7 +90,7 @@ public function render() { capquiz_urls::redirect_to_front_page(); } return $this->renderer->render_from_template('capquiz/create_question_list', [ - 'form' => $form->render() + 'form' => $form->render(), ]); } diff --git a/classes/output/question_list_renderer.php b/classes/output/question_list_renderer.php index 7bba271..0f360de 100644 --- a/classes/output/question_list_renderer.php +++ b/classes/output/question_list_renderer.php @@ -29,6 +29,8 @@ use mod_capquiz\capquiz; use mod_capquiz\capquiz_urls; use mod_capquiz\capquiz_question_list; +use moodle_page; +use moodle_url; /** * Class question_list_renderer @@ -42,16 +44,17 @@ class question_list_renderer { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; /** @var renderer $renderer */ - private $renderer; + private renderer $renderer; - /** @var \moodle_page $page */ - private $page; + /** @var moodle_page $page */ + private moodle_page $page; /** - * question_list_renderer constructor. + * Constructor. + * * @param capquiz $capquiz The capquiz whose question list should be rendered * @param renderer $renderer The renderer used to render the question list */ @@ -63,57 +66,50 @@ public function __construct(capquiz $capquiz, renderer $renderer) { /** * Renders question list - * - * @return bool|string - * @throws \coding_exception */ - public function render() { + public function render(): bool|string { $cmid = $this->capquiz->course_module()->id; $this->page->requires->js_call_amd('mod_capquiz/edit_questions', 'initialize', [$cmid]); $qlist = $this->capquiz->question_list(); - if ($qlist && $qlist->has_questions()) { + if ($qlist?->has_questions()) { return $this->render_questions($qlist); } $title = get_string('question_list', 'capquiz'); $noquestions = get_string('question_list_no_questions', 'capquiz'); - return "

$title

$noquestions

"; + return "

$title

$noquestions

"; } /** * Renders all the individual questions * * @param capquiz_question_list $qlist - * @return bool|string - * @throws \coding_exception - * @throws \moodle_exception */ - private function render_questions(capquiz_question_list $qlist) { - global $CFG; + private function render_questions(capquiz_question_list $qlist): bool|string { $rows = []; $questions = $qlist->questions(); for ($i = 0; $i < $qlist->question_count(); $i++) { $question = $questions[$i]; $courseid = $question->course_id(); - $editurl = new \moodle_url($CFG->wwwroot . '/question/question.php', [ - 'courseid' => $courseid, - 'id' => $question->question_id() + $editurl = new moodle_url('/question/bank/editquestion/question.php', [ + 'cmid' => $this->page->cm->id, + 'id' => $question->question_id(), ]); - $previewurl = new \moodle_url($CFG->wwwroot . '/question/preview.php', [ - 'courseid' => $courseid, - 'id' => $question->question_id() + $previewurl = new moodle_url('/question/bank/previewquestion/preview.php', [ + 'cmid' => $this->page->cm->id, + 'id' => $question->question_id(), ]); $targetblank = ['name' => 'target', 'value' => '_blank']; $edit = $courseid === 0 ? false : [ 'url' => $editurl->out(false), 'label' => get_string('edit'), 'classes' => 'fa fa-edit', - 'attributes' => [$targetblank] + 'attributes' => [$targetblank], ]; $preview = $courseid === 0 ? false : [ 'url' => $previewurl->out(false), 'label' => get_string('preview'), 'classes' => 'fa fa-search-plus', - 'attributes' => [$targetblank] + 'attributes' => [$targetblank], ]; $rows[] = [ 'index' => $i + 1, @@ -124,10 +120,10 @@ private function render_questions(capquiz_question_list $qlist) { 'delete' => [ 'url' => capquiz_urls::remove_question_from_list_url($question->id())->out(false), 'label' => get_string('remove', 'capquiz'), - 'classes' => 'fa fa-trash' + 'classes' => 'fa fa-trash', ], 'edit' => $edit, - 'preview' => $preview + 'preview' => $preview, ]; } $message = null; @@ -137,7 +133,7 @@ private function render_questions(capquiz_question_list $qlist) { return $this->renderer->render_from_template('capquiz/question_list', [ 'default_rating' => $qlist->default_question_rating(), 'questions' => $rows, - 'message' => $message ? $message : false + 'message' => $message ?: false, ]); } diff --git a/classes/output/question_list_selection_renderer.php b/classes/output/question_list_selection_renderer.php index 5d22f00..f882c82 100755 --- a/classes/output/question_list_selection_renderer.php +++ b/classes/output/question_list_selection_renderer.php @@ -25,8 +25,10 @@ namespace mod_capquiz\output; +use context_module; use mod_capquiz\capquiz_question_list; use mod_capquiz\capquiz_urls; +use renderer_base; /** * Class question_list_selection_renderer @@ -38,38 +40,31 @@ */ class question_list_selection_renderer { - /** @var renderer $renderer */ - private $renderer; - - /** @var \context_module $context */ - private $context; + /** @var renderer_base $renderer */ + private renderer_base $renderer; /** - * question_list_selection_renderer constructor. - * @param renderer $renderer The renderer used to render the question list selection - * @param \context_module $context + * Constructor. + * + * @param renderer_base $renderer The renderer used to render the question list selection */ - public function __construct(renderer $renderer, \context_module $context) { + public function __construct(renderer_base $renderer) { $this->renderer = $renderer; - $this->context = $context; } /** * Renders the question list selection - * - * @return bool|string - * @throws \moodle_exception */ - public function render() { - $templates = capquiz_question_list::load_question_list_templates($this->context); + public function render(): bool|string { + $templates = capquiz_question_list::load_question_list_templates(); $lists = []; foreach ($templates as $template) { $lists[] = [ 'title' => $template->title(), 'description' => $template->description(), 'author' => $template->author()->username, - 'created' => date("Y-m-d H:i:s", substr($template->time_created(), 0, 10)), - 'url' => capquiz_urls::question_list_select_url($template) + 'created' => date('Y-m-d H:i:s', substr($template->time_created(), 0, 10)), + 'url' => capquiz_urls::question_list_select_url($template), ]; } @@ -77,11 +72,10 @@ public function render() { $params = $createurl->params(); $createurl->remove_all_params(); $createlabel = get_string('create_question_list', 'capquiz'); - $create = basic_renderer::render_action_button($this->renderer, $createurl, $createlabel, 'get', $params); return $this->renderer->render_from_template('capquiz/question_list_selection', [ 'lists' => $lists, - 'create' => $create + 'create' => basic_renderer::render_action_button($this->renderer, $createurl, $createlabel, 'get', $params), ]); } diff --git a/classes/output/rating_system_configuration_renderer.php b/classes/output/rating_system_configuration_renderer.php index 025fac5..5a4df1f 100644 --- a/classes/output/rating_system_configuration_renderer.php +++ b/classes/output/rating_system_configuration_renderer.php @@ -28,6 +28,7 @@ use mod_capquiz\capquiz; use mod_capquiz\capquiz_rating_system_loader; use mod_capquiz\capquiz_urls; +use moodle_page; defined('MOODLE_INTERNAL') || die(); @@ -44,16 +45,16 @@ class rating_system_configuration_renderer { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; /** @var renderer $renderer */ - private $renderer; + private renderer $renderer; /** @var capquiz_rating_system_loader $registry */ - private $registry; + private capquiz_rating_system_loader $registry; - /** @var \moodle_page $page */ - private $page; + /** @var moodle_page $page */ + private moodle_page $page; /** * rating_system_configuration_renderer constructor. @@ -69,11 +70,8 @@ public function __construct(capquiz $capquiz, renderer $renderer) { /** * Calls submethod that renders the rating_system_configuration view - * - * @return bool|string - * @throws \moodle_exception */ - public function render() { + public function render(): bool|string { if ($this->registry->has_rating_system()) { return $this->render_configuration(); } else { @@ -83,25 +81,18 @@ public function render() { /** * Renders the rating configuration view - * - * @return bool|string - * @throws \moodle_exception */ - private function render_configuration() { - $html = $this->render_form(); + private function render_configuration(): bool|string { return $this->renderer->render_from_template('capquiz/rating_system_configuration', [ 'strategy' => $this->registry->current_rating_system_name(), - 'form' => $html + 'form' => $this->render_form(), ]); } /** * Renders the rating configuration form - * - * @return string - * @throws \moodle_exception */ - private function render_form() { + private function render_form(): string { $url = $this->page->url; if ($form = $this->registry->configuration_form($url)) { $formdata = $form->get_data(); diff --git a/classes/output/rating_system_selection_renderer.php b/classes/output/rating_system_selection_renderer.php index 5a9f5c6..d53dd9f 100644 --- a/classes/output/rating_system_selection_renderer.php +++ b/classes/output/rating_system_selection_renderer.php @@ -30,6 +30,8 @@ use mod_capquiz\capquiz_rating_system_registry; use mod_capquiz\capquiz_urls; use mod_capquiz\form\view\rating_system_selection_form; +use moodle_page; +use moodle_url; /** * Class rating_system_selection_renderer @@ -41,17 +43,17 @@ */ class rating_system_selection_renderer { - /** @var \moodle_url $url */ - private $url; + /** @var moodle_url $url */ + private moodle_url $url; /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; /** @var renderer $renderer */ - private $renderer; + private renderer $renderer; - /** @var \moodle_page $page */ - private $page; + /** @var moodle_page $page */ + private moodle_page $page; /** * rating_system_selection_renderer constructor. @@ -69,19 +71,16 @@ public function __construct(capquiz $capquiz, renderer $renderer) { /** * Sets redirect url * - * @param \moodle_url $url + * @param moodle_url $url */ - public function set_redirect_url(\moodle_url $url) { + public function set_redirect_url(moodle_url $url): void { $this->url = $url; } /** * Renders the rating system selection form - * @return bool|string - * @throws \dml_exception - * @throws \moodle_exception */ - public function render() { + public function render(): bool|string { $url = $this->page->url; $form = new rating_system_selection_form($this->capquiz, $url); $formdata = $form->get_data(); @@ -91,9 +90,8 @@ public function render() { $loader->set_rating_system($registry->rating_systems()[$formdata->rating_system]); redirect($this->url); } - return $this->renderer->render_from_template('capquiz/rating_system_selection', [ - 'form' => $form->render() + 'form' => $form->render(), ]); } diff --git a/classes/output/renderer.php b/classes/output/renderer.php index d927c52..16c09db 100755 --- a/classes/output/renderer.php +++ b/classes/output/renderer.php @@ -25,8 +25,12 @@ namespace mod_capquiz\output; +use core_renderer; use mod_capquiz\capquiz; use mod_capquiz\capquiz_urls; +use moodle_url; +use renderer_base; +use tabobject; defined('MOODLE_INTERNAL') || die(); @@ -54,10 +58,8 @@ class renderer extends \plugin_renderer_base { /** * Returns a reference to the current renderer - * - * @return \core_renderer|\renderer_base */ - public function output_renderer() { + public function output_renderer(): core_renderer|renderer_base { return $this->output; } @@ -66,23 +68,18 @@ public function output_renderer() { * * @param string $name Name of the tab * @param string $title Title of the tab - * @param \moodle_url $link Link - * @return \tabobject - * @throws \coding_exception + * @param moodle_url $link Link */ - private function tab(string $name, string $title, \moodle_url $link) { - $title = get_string($title, 'capquiz'); - return new \tabobject($name, $link, $title); + private function tab(string $name, string $title, moodle_url $link): tabobject { + return new tabobject($name, $link, get_string($title, 'capquiz')); } /** * Creates all tabs * * @param string $activetab The currently active cab - * @return bool|string - * @throws \coding_exception */ - private function tabs(string $activetab) { + private function tabs(string $activetab): bool|string { $tabs = [ $this->tab('view_dashboard', 'dashboard', capquiz_urls::view_url()), $this->tab('view_rating_system', 'rating_system', capquiz_urls::view_rating_system_url()), @@ -98,162 +95,112 @@ private function tabs(string $activetab) { /** * Display a tabbed view * - * @param renderer $renderer The renderer to render the tab - * @param string $activetab The currently active tab - * @throws \coding_exception + * @param string $view + * @param string $activetab */ - public function display_tabbed_view($renderer, string $activetab) { - $html = $this->output->header(); - $html .= $this->tabs($activetab); - $html .= $renderer->render(); - $html .= $this->output->footer(); - echo $html; + public function display_tabbed_view(string $view, string $activetab): void { + echo $this->output->header(); + echo $this->tabs($activetab); + echo $view; + echo $this->output->footer(); } /** * Display multiple tabbed views * - * @param renderer[] $renderers The renderers to render the tabs + * @param string[] $views The renderers to render the tabs * @param string $activetab The currently active tab - * @throws \coding_exception */ - public function display_tabbed_views(array $renderers, string $activetab) { - $html = $this->output->header(); - $html .= $this->tabs($activetab); - foreach ($renderers as $renderer) { - $html .= $renderer->render(); + public function display_tabbed_views(array $views, string $activetab): void { + echo $this->output->header(); + echo $this->tabs($activetab); + foreach ($views as $view) { + echo $view; } - $html .= $this->output->footer(); - echo $html; - } - - /** - * Display view - * - * @param renderer $renderer renderer to render the view - * @throws \coding_exception - */ - public function display_view($renderer) { - $html = $this->output->header(); - $html .= $renderer->render(); - $html .= $this->output->footer(); - echo $html; + echo $this->output->footer(); } /** - * Display multiple views + * Display view. * - * @param renderer[] $renderers renderers to render the views - * @throws \coding_exception + * @param string $view */ - public function display_views(array $renderers) { - $html = $this->output->header(); - foreach ($renderers as $renderer) { - $html .= $renderer->render(); - } - $html .= $this->output->footer(); - echo $html; + public function display_view(string $view): void { + echo $this->output->header(); + echo $view; + echo $this->output->footer(); } /** * Display the question attempt view * - * @param capquiz $capquiz The current capquiz - * @throws \coding_exception + * @param capquiz $capquiz */ - public function display_question_attempt_view(capquiz $capquiz) { - $this->display_view(new question_attempt_renderer($capquiz, $this)); + public function display_question_attempt_view(capquiz $capquiz): void { + $renderer = new question_attempt_renderer($capquiz, $this); + $this->display_view($renderer->render()); } /** * Display the instructor dashboard * - * @param capquiz $capquiz The current capquiz - * @throws \coding_exception + * @param capquiz $capquiz */ - public function display_instructor_dashboard(capquiz $capquiz) { - $this->display_tabbed_view(new instructor_dashboard_renderer($capquiz, $this), 'view_dashboard'); + public function display_instructor_dashboard(capquiz $capquiz): void { + $renderer = new instructor_dashboard_renderer($capquiz, $this); + $this->display_tabbed_view($renderer->render(), 'view_dashboard'); } /** * Display the question list create view * - * @param capquiz $capquiz The current capquiz - * @throws \coding_exception + * @param capquiz $capquiz */ - public function display_question_list_create_view(capquiz $capquiz) { - $this->display_view(new question_list_creator_renderer($capquiz, $this)); + public function display_question_list_create_view(capquiz $capquiz): void { + $renderer = new question_list_creator_renderer($capquiz, $this); + $this->display_view($renderer->render()); } /** * Display the choose question list view - * - * @param capquiz $capquiz The current capquiz - * @throws \coding_exception */ - public function display_choose_question_list_view(capquiz $capquiz) { - $this->display_view(new question_list_selection_renderer($this, $capquiz->context())); + public function display_choose_question_list_view(): void { + $renderer = new question_list_selection_renderer($this); + $this->display_view($renderer->render()); } /** * Display the unauthorized view - * - * @throws \coding_exception */ - public function display_unauthorized_view() { - $this->display_view(new unauthorized_view_renderer($this)); + public function display_unauthorized_view(): void { + $renderer = new unauthorized_view_renderer($this); + $this->display_view($renderer->render()); } /** * Display the question list view * - * @param capquiz $capquiz The current capquiz - * @throws \coding_exception + * @param capquiz $capquiz */ - public function display_question_list_view(capquiz $capquiz) { - $render = new class($capquiz, $this) { - private $capquiz; - private $renderer; - - /** - * constructor. - * @param capquiz $capquiz - * @param renderer $renderer - */ - public function __construct(capquiz $capquiz, renderer $renderer) { - $this->capquiz = $capquiz; - $this->renderer = $renderer; - } - - /** - * Renders question list - * - * @return string - */ - public function render() { - $html = '
'; - $r1 = new question_list_renderer($this->capquiz, $this->renderer); - $r2 = new question_bank_renderer($this->capquiz, $this->renderer); - $html .= '
' . $r1->render() . '
'; - $html .= '
' . $r2->render() . '
'; - return $html . '
'; - } - }; - $this->display_tabbed_view($render, 'view_questions'); + public function display_question_list_view(capquiz $capquiz): void { + $r1 = new question_list_renderer($capquiz, $this); + $r2 = new question_bank_renderer($capquiz); + $html = '
' . $r1->render() . '
'; + $html .= '
' . $r2->render() . '
'; + $this->display_tabbed_view($html, 'view_questions'); } /** * Display the rating system configuration * - * @param capquiz $capquiz The current capquiz - * @throws \coding_exception + * @param capquiz $capquiz */ - public function display_rating_system_configuration(capquiz $capquiz) { + public function display_rating_system_configuration(capquiz $capquiz): void { $this->display_tabbed_views([ - new matchmaking_strategy_selection_renderer($capquiz, $this), - new matchmaking_configuration_renderer($capquiz, $this), - new rating_system_selection_renderer($capquiz, $this), - new rating_system_configuration_renderer($capquiz, $this) + (new matchmaking_strategy_selection_renderer($capquiz, $this))->render(), + (new matchmaking_configuration_renderer($capquiz, $this))->render(), + (new rating_system_selection_renderer($capquiz, $this))->render(), + (new rating_system_configuration_renderer($capquiz, $this))->render(), ], 'view_rating_system'); } @@ -261,40 +208,40 @@ public function display_rating_system_configuration(capquiz $capquiz) { /** * Display the leaderboard view * - * @param capquiz $capquiz The current capquiz - * @throws \coding_exception + * @param capquiz $capquiz */ - public function display_leaderboard(capquiz $capquiz) { - $this->display_tabbed_view(new classlist_renderer($capquiz, $this), 'view_classlist'); + public function display_leaderboard(capquiz $capquiz): void { + $renderer = new classlist_renderer($capquiz, $this); + $this->display_tabbed_view($renderer->render(), 'view_classlist'); } /** * Display the import view * - * @param capquiz $capquiz The current capquiz - * @throws \coding_exception + * @param capquiz $capquiz */ - public function display_import(capquiz $capquiz) { - $this->display_tabbed_view(new import_renderer($capquiz, $this), 'view_import'); + public function display_import(capquiz $capquiz): void { + $renderer = new import_renderer($capquiz, $this); + $this->display_tabbed_view($renderer->render(), 'view_import'); } /** * Display the grading configuration view * - * @param capquiz $capquiz The current capquiz - * @throws \coding_exception + * @param capquiz $capquiz */ - public function display_grading_configuration(capquiz $capquiz) { - $this->display_tabbed_view(new grading_configuration_renderer($capquiz, $this), 'view_grading'); + public function display_grading_configuration(capquiz $capquiz): void { + $renderer = new grading_configuration_renderer($capquiz, $this); + $this->display_tabbed_view($renderer->render(), 'view_grading'); } /** * Display the report view * - * @param capquiz $capquiz The current capquiz - * @throws \coding_exception + * @param capquiz $capquiz */ - public function display_report(capquiz $capquiz) { - $this->display_tabbed_view(new report_renderer($capquiz, $this), 'view_report'); + public function display_report(capquiz $capquiz): void { + $renderer = new report_renderer($capquiz); + $this->display_tabbed_view($renderer->render(), 'view_report'); } } diff --git a/classes/output/report_renderer.php b/classes/output/report_renderer.php index a2768ea..f6936ed 100644 --- a/classes/output/report_renderer.php +++ b/classes/output/report_renderer.php @@ -29,6 +29,7 @@ use mod_capquiz\capquiz; use mod_capquiz\capquiz_urls; use mod_capquiz\report\capquiz_report_factory; +use moodle_page; use tabobject; defined('MOODLE_INTERNAL') || die(); @@ -46,33 +47,25 @@ class report_renderer { /** @var capquiz $capquiz */ - private $capquiz; + private capquiz $capquiz; - /** @var renderer $renderer */ - private $renderer; - - /** @var \moodle_page $page */ - private $page; + /** @var moodle_page $page */ + private moodle_page $page; /** - * report_renderer constructor. + * Constructor. + * * @param capquiz $capquiz - * @param renderer $renderer */ - public function __construct(capquiz $capquiz, renderer $renderer) { + public function __construct(capquiz $capquiz) { $this->capquiz = $capquiz; - $this->renderer = $renderer; $this->page = $capquiz->get_page(); } /** * Renders report - * - * @return \lang_string|string - * @throws \coding_exception - * @throws capquiz_exception */ - public function render() { + public function render(): string { global $CFG; $html = ''; $download = optional_param('download', '', PARAM_RAW); @@ -82,21 +75,21 @@ public function render() { if (empty($reportlist)) { return get_string('noreports', 'capquiz'); } - if ($mode == '') { + if ($mode === '') { // Default to first accessible report and redirect. capquiz_urls::redirect_to_url(capquiz_urls::view_report_url(reset($reportlist))); } if (!in_array($mode, $reportlist)) { throw new capquiz_exception('erroraccessingreport', 'capquiz', - $CFG->wwwroot.'/mod/capquiz/view.php?id=' . $this->capquiz->course()->id); + $CFG->wwwroot . '/mod/capquiz/view.php?id=' . $this->capquiz->course()->id); } $report = capquiz_report_factory::make($mode); $this->setup_report(); - $row = array(); + $row = []; foreach ($reportlist as $rep) { - $row[] = new tabobject('capquiz_' . $rep, capquiz_urls::view_report_url($rep), - get_string('pluginname', 'capquizreport_' . $rep)); + $url = capquiz_urls::view_report_url($rep); + $row[] = new tabobject('capquiz_' . $rep, $url, get_string('pluginname', 'capquizreport_' . $rep)); } $tabs[] = $row; @@ -105,15 +98,13 @@ public function render() { ob_start(); $report->display($this->capquiz, $this->capquiz->course_module(), $this->capquiz->course(), $download); $html .= ob_get_clean(); - return $html; - } /** * Sets pagelayout to "report" */ - private function setup_report() { + private function setup_report(): void { $this->page->set_pagelayout('report'); } } diff --git a/classes/output/unauthorized_view_renderer.php b/classes/output/unauthorized_view_renderer.php index 2ae5dd3..2ea302e 100755 --- a/classes/output/unauthorized_view_renderer.php +++ b/classes/output/unauthorized_view_renderer.php @@ -34,11 +34,12 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class unauthorized_view_renderer { + /** @var renderer */ - private $renderer; + private renderer $renderer; /** - * unauthorized_view_renderer constructor. + * Constructor. * * @param renderer $renderer */ @@ -48,11 +49,8 @@ public function __construct(renderer $renderer) { /** * Renders the "unauthorized" view - * - * @return bool|string - * @throws \moodle_exception */ - public function render() { + public function render(): bool|string { return $this->renderer->render_from_template('capquiz/unauthorized', []); } diff --git a/classes/plugininfo/capquizreport.php b/classes/plugininfo/capquizreport.php index 88c2958..ea6ab49 100644 --- a/classes/plugininfo/capquizreport.php +++ b/classes/plugininfo/capquizreport.php @@ -42,25 +42,23 @@ class capquizreport extends base { /** * Return URL used for management of plugins of this type. - * - * @return moodle_url */ - public static function get_manage_url() { - return new moodle_url('/mod/capquiz/adminmanageplugins.php', array('subtype' => 'capquizreport')); + public static function get_manage_url(): moodle_url { + return new moodle_url('/mod/capquiz/adminmanageplugins.php', ['subtype' => 'capquizreport']); } /** * Finds all enabled plugins, the result may include missing plugins. + * * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ - public static function get_enabled_plugins() { + public static function get_enabled_plugins(): ?array { global $DB; - $plugins = core_plugin_manager::instance()->get_installed_plugins('capquizreport'); if (!$plugins) { - return array(); + return []; } - $installed = array(); + $installed = []; foreach ($plugins as $plugin => $version) { $installed[] = 'capquizreport_' . $plugin; } @@ -75,20 +73,17 @@ public static function get_enabled_plugins() { unset($plugins[$name]); } - $enabled = array(); + $enabled = []; foreach ($plugins as $plugin => $version) { $enabled[$plugin] = $plugin; } - return $enabled; } /** * Is it possible to uninstall this plugin? - * - * @return bool */ - public function is_uninstall_allowed() { + public function is_uninstall_allowed(): bool { return true; } @@ -102,7 +97,7 @@ public function is_uninstall_allowed() { * @param string $parentnodename * @param bool $hassiteconfig whether the current user has moodle/site:config capability */ - public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { + public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig): void { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. @@ -127,10 +122,8 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h /** * Returns the node name used in admin settings menu for this plugin settings (if applicable) - * - * @return string */ - public function get_settings_section_name() { + public function get_settings_section_name(): string { return $this->type . '_' . $this->name; } } diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index 33bca8e..1e34a07 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -26,7 +26,6 @@ namespace mod_capquiz\privacy; -use coding_exception; use context; use context_module; use core_privacy\local\metadata\collection; @@ -35,8 +34,6 @@ use core_privacy\local\request\helper; use core_privacy\local\request\transform; use core_privacy\local\request\writer; -use dml_exception; -use moodle_exception; use question_display_options; use stdClass; @@ -56,9 +53,10 @@ class provider implements \core_privacy\local\request\plugin\provider { /** - * Returns meta data about this system. + * Returns metadata about this system. + * * @param collection $items The initialised collection to add metadata to. - * @return collection A listing of user data stored through this system. + * @return collection A listing of user data stored through this system. */ public static function get_metadata(collection $items): collection { // The table 'capquiz' stores a record for each capquiz. @@ -69,7 +67,7 @@ public static function get_metadata(collection $items): collection { $items->add_database_table('capquiz_attempt', [ 'userid' => 'privacy:metadata:capquiz_attempt:userid', 'time_answered' => 'privacy:metadata:capquiz_attempt:time_answered', - 'time_reviewed' => 'privacy:metadata:capquiz_attempt:time_reviewed' + 'time_reviewed' => 'privacy:metadata:capquiz_attempt:time_reviewed', ], 'privacy:metadata:capquiz_attempt'); // The 'capquiz_question' table is used to map the usage of a question used in a CAPQuiz activity. @@ -102,7 +100,7 @@ public static function get_metadata(collection $items): collection { 'capquiz_user_id' => 'privacy:metadata:capquiz_user_rating:capquiz_user_id', 'rating' => 'privacy:metadata:capquiz_user_rating:rating', 'manual' => 'privacy:metadata:capquiz_user_rating:manual', - 'timecreated' => 'privacy:metadata:capquiz_user_rating:timecreated' + 'timecreated' => 'privacy:metadata:capquiz_user_rating:timecreated', ], 'privacy:metadata:capquiz_user_rating'); // CAPQuiz links to the 'core_question' subsystem for all question functionality. @@ -136,7 +134,7 @@ public static function get_contexts_for_userid(int $userid): contextlist { $contextlist->add_from_sql($sql, [ 'contextlevel' => CONTEXT_MODULE, 'modname' => 'capquiz', - 'userid' => $userid + 'userid' => $userid, ]); return $contextlist; } @@ -145,13 +143,10 @@ public static function get_contexts_for_userid(int $userid): contextlist { * Export all user data for the specified user, in the specified contexts. * * @param approved_contextlist $contextlist The approved contexts to export information for. - * @throws coding_exception - * @throws dml_exception - * @throws moodle_exception */ - public static function export_user_data(approved_contextlist $contextlist) { + public static function export_user_data(approved_contextlist $contextlist): void { global $DB; - if (empty($contextlist)) { + if ($contextlist->count() === 0) { return; } $user = $contextlist->get_user(); @@ -185,7 +180,7 @@ public static function export_user_data(approved_contextlist $contextlist) { $params = [ 'contextlevel' => CONTEXT_MODULE, 'modname' => 'capquiz', - 'userid' => $user->id + 'userid' => $user->id, ]; $params += $contextparams; $qubaidforcontext = []; @@ -208,7 +203,7 @@ public static function export_user_data(approved_contextlist $contextlist) { // where X is the attempt number. $subcontext = [ get_string('attempts', 'capquiz'), - get_string('attempt', 'capquiz') . " $attempt->capattemptid" + get_string('attempt', 'capquiz') . " $attempt->capattemptid", ]; writer::with_context($context)->export_data($subcontext, $data); @@ -240,8 +235,6 @@ public static function export_user_data(approved_contextlist $contextlist) { * * @param context $context The context to export the users rating for * @param int $userid the specified users id - * @throws coding_exception - * @throws dml_exception */ public static function export_user_rating(context $context, int $userid) { global $DB; @@ -262,7 +255,7 @@ public static function export_user_rating(context $context, int $userid) { $data->timecreated = transform::datetime($rating->timecreated); $subcontext = [ get_string('userratings', 'capquiz'), - get_string('userrating', 'capquiz') . " $rating->ratingid" + get_string('userrating', 'capquiz') . " $rating->ratingid", ]; writer::with_context($context)->export_data($subcontext, $data); } @@ -273,7 +266,7 @@ public static function export_user_rating(context $context, int $userid) { * * @param context $context The specific context to delete data for. */ - public static function delete_data_for_all_users_in_context(context $context) { + public static function delete_data_for_all_users_in_context(context $context): void { global $DB; if ($context->contextlevel != CONTEXT_MODULE) { return; @@ -296,7 +289,7 @@ public static function delete_data_for_all_users_in_context(context $context) { * * @param approved_contextlist $contextlist The approved contexts and user information to delete information for. */ - public static function delete_data_for_user(approved_contextlist $contextlist) { + public static function delete_data_for_user(approved_contextlist $contextlist): void { global $DB; if (empty($contextlist->count())) { return; diff --git a/classes/rating_system/capquiz_rating_system_registry.php b/classes/rating_system/capquiz_rating_system_registry.php index ca9c235..efdd352 100755 --- a/classes/rating_system/capquiz_rating_system_registry.php +++ b/classes/rating_system/capquiz_rating_system_registry.php @@ -25,6 +25,10 @@ namespace mod_capquiz; +use coding_exception; +use moodle_url; +use stdClass; + defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/mod/capquiz/classes/rating_system/elo_rating/elo_rating_system.php'); @@ -41,10 +45,10 @@ class capquiz_rating_system_registry { /** @var callable[][] $systems */ - private $systems; + private array $systems; /** - * capquiz_rating_system_registry constructor. + * Constructor. */ public function __construct() { $this->register_rating_systems(); @@ -54,28 +58,25 @@ public function __construct() { * Returns rating system * * @param string $system - * @return capquiz_rating_system - * @throws \Exception */ - public function rating_system($system) { - if ($value = $this->systems[$system]) { - return array_values($value)[0](); + public function rating_system(string $system): capquiz_rating_system { + $value = $this->systems[$system]; + if (!$value) { + $this->throw_rating_system_exception($system); } - // The rating system $system@ does not exist. - $this->throw_rating_system_exception($system); + return array_values($value)[0](); } /** * Returns configuration form * * @param string $system - * @param \stdClass $configuration - * @param \moodle_url $url - * @return mixed - * @throws \Exception + * @param stdClass $configuration + * @param moodle_url $url */ - public function configuration_form($system, \stdClass $configuration, \moodle_url $url) { - if ($value = $this->systems[$system]) { + public function configuration_form(string $system, stdClass $configuration, moodle_url $url) { + $value = $this->systems[$system]; + if ($value) { $configfunc = array_values($value)[1]; return $configfunc($url, $configuration); } @@ -86,18 +87,15 @@ public function configuration_form($system, \stdClass $configuration, \moodle_ur * Checks if this instance has a rating system * * @param string $system - * @return bool */ - public function has_rating_system($system) : bool { + public function has_rating_system(string $system): bool { return isset($this->systems[$system]); } /** * Returns the default rating system - * - * @return string */ - public function default_rating_system() : string { + public function default_rating_system(): string { // Default rating system is added first. // Modify caquiz_rating_system_registry::register_rating_systems() to change this. $ratingsystems = $this->rating_systems(); @@ -105,32 +103,24 @@ public function default_rating_system() : string { } /** - * Returns teh kays/names of all rating systems + * Returns the names of all rating systems. * * @return string[] */ - public function rating_systems() : array { - $names = []; - foreach (array_keys($this->systems) as $value) { - $names[] = $value; - } - return $names; + public function rating_systems(): array { + return array_keys($this->systems); } /** * Registers rating systems */ - private function register_rating_systems() { + private function register_rating_systems(): void { // The first listed will be selected by default when creating a new activity. $this->systems = [ 'Elo' => [ - function () { - return new elo_rating_system(); - }, - function (\moodle_url $url, \stdClass $configuration) { - return new elo_rating_system_form($configuration, $url); - } - ] + fn() => new elo_rating_system(), + fn(moodle_url $url, stdClass $config) => new elo_rating_system_form($config, $url), + ], ]; } @@ -138,12 +128,11 @@ function (\moodle_url $url, \stdClass $configuration) { * Creates and throws exception * * @param string $system - * @throws \Exception */ - private function throw_rating_system_exception($system) { + private function throw_rating_system_exception(string $system) { $msg = "The specified rating system '$system' does not exist."; $msg .= " Options are {'" . implode("', '", $this->rating_systems()); $msg .= "'}. This issue must be fixed by a programmer"; - throw new \Exception($msg); + throw new coding_exception($msg); } } diff --git a/classes/rating_system/elo_rating/elo_rating_system.php b/classes/rating_system/elo_rating/elo_rating_system.php index 2c04438..b888d38 100755 --- a/classes/rating_system/elo_rating/elo_rating_system.php +++ b/classes/rating_system/elo_rating/elo_rating_system.php @@ -25,6 +25,8 @@ namespace mod_capquiz; +use stdClass; + /** * Class elo_rating_system * @@ -36,32 +38,30 @@ class elo_rating_system extends capquiz_rating_system { /** @var float $studentkfactor */ - private $studentkfactor; + private float $studentkfactor; /** @var float $questionkfactor */ - private $questionkfactor; + private float $questionkfactor; /** * Configures the rating system * - * @param \stdClass $configuration + * @param stdClass $config */ - public function configure(\stdClass $configuration) { - if ($configuration->student_k_factor) { - $this->studentkfactor = $configuration->student_k_factor; + public function configure(stdClass $config): void { + if ($config->student_k_factor) { + $this->studentkfactor = $config->student_k_factor; } - if ($configuration->question_k_factor) { - $this->questionkfactor = $configuration->question_k_factor; + if ($config->question_k_factor) { + $this->questionkfactor = $config->question_k_factor; } } /** * Returns the current configuration - * - * @return \stdClass */ - public function configuration() { - $config = new \stdClass; + public function configuration(): stdClass { + $config = new stdClass; $config->student_k_factor = $this->studentkfactor; $config->question_k_factor = $this->questionkfactor; return $config; @@ -69,11 +69,9 @@ public function configuration() { /** * Returns the default configuration - * - * @return \stdClass */ - public function default_configuration() { - $config = new \stdClass; + public function default_configuration(): stdClass { + $config = new stdClass; $config->student_k_factor = 32; $config->question_k_factor = 8; return $config; @@ -85,10 +83,8 @@ public function default_configuration() { * @param capquiz_user $user * @param capquiz_question $question * @param float $score - * @return mixed|void - * @throws \dml_exception */ - public function update_user_rating(capquiz_user $user, capquiz_question $question, float $score) { + public function update_user_rating(capquiz_user $user, capquiz_question $question, float $score): void { $current = $user->rating(); $factor = $this->studentkfactor; $newrating = $current + $factor * ($score - $this->expected_result($current, $question->rating())); @@ -100,9 +96,8 @@ public function update_user_rating(capquiz_user $user, capquiz_question $questio * * @param capquiz_question $winner * @param capquiz_question $loser - * @return mixed|void */ - public function question_victory_ratings(capquiz_question $winner, capquiz_question $loser) { + public function question_victory_ratings(capquiz_question $winner, capquiz_question $loser): void { $loserating = $loser->rating(); $winrating = $winner->rating(); $factor = $this->questionkfactor; @@ -118,9 +113,8 @@ public function question_victory_ratings(capquiz_question $winner, capquiz_quest * * @param float $a * @param float $b - * @return float */ - private function expected_result(float $a, float $b) : float { + private function expected_result(float $a, float $b): float { $exponent = ($b - $a) / 400.0; return 1.0 / (1.0 + pow(10.0, $exponent)); } diff --git a/classes/rating_system/elo_rating/elo_rating_system_form.php b/classes/rating_system/elo_rating/elo_rating_system_form.php index f6f1c5e..05f35d2 100755 --- a/classes/rating_system/elo_rating/elo_rating_system_form.php +++ b/classes/rating_system/elo_rating/elo_rating_system_form.php @@ -25,7 +25,8 @@ namespace mod_capquiz; -use mod_capquiz\capquiz; +use moodle_url; +use stdClass; defined('MOODLE_INTERNAL') || die(); @@ -41,39 +42,38 @@ */ class elo_rating_system_form extends \moodleform { - /** @var \stdClass $configuration */ - private $configuration; + /** @var stdClass $config */ + private stdClass $config; /** - * elo_rating_system_form constructor. - * @param \stdClass $configuration - * @param \moodle_url $url + * Constructor. + * + * @param stdClass $config + * @param moodle_url $url */ - public function __construct(\stdClass $configuration, \moodle_url $url) { - $this->configuration = $configuration; + public function __construct(stdClass $config, moodle_url $url) { + $this->config = $config; parent::__construct($url); } /** * Defines rating system form - * - * @throws \coding_exception */ - public function definition() /*: void*/ { + public function definition(): void { $form = $this->_form; $form->addElement('text', 'student_k_factor', get_string('student_k_factor', 'capquiz')); $form->setType('student_k_factor', PARAM_INT); $form->addRule('student_k_factor', get_string('student_k_factor_specified_rule', 'capquiz'), 'required', null, 'client'); $form->addRule('student_k_factor', get_string('k_factor_numeric_rule', 'capquiz'), 'numeric', null, 'client'); - $form->setDefault('student_k_factor', $this->configuration->student_k_factor); + $form->setDefault('student_k_factor', $this->config->student_k_factor); $form->addHelpButton('student_k_factor', 'student_k_factor', 'capquiz'); $form->addElement('text', 'question_k_factor', get_string('question_k_factor', 'capquiz')); $form->setType('question_k_factor', PARAM_INT); $form->addRule('question_k_factor', get_string('question_k_factor_specified_rule', 'capquiz'), 'required', null, 'client'); $form->addRule('question_k_factor', get_string('k_factor_numeric_rule', 'capquiz'), 'numeric', null, 'client'); - $form->setDefault('question_k_factor', $this->configuration->question_k_factor); + $form->setDefault('question_k_factor', $this->config->question_k_factor); $form->addHelpButton('question_k_factor', 'question_k_factor', 'capquiz'); $this->add_action_buttons(false); diff --git a/db/access.php b/db/access.php index d646432..0c22e13 100755 --- a/db/access.php +++ b/db/access.php @@ -32,8 +32,8 @@ 'legacy' => [ 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ] + 'manager' => CAP_ALLOW, + ], ], 'mod/capquiz:student' => [ 'captype' => 'write', @@ -42,8 +42,8 @@ 'student' => CAP_ALLOW, 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ] + 'manager' => CAP_ALLOW, + ], ], 'mod/capquiz:addinstance' => [ 'captype' => 'write', @@ -51,8 +51,8 @@ 'legacy' => [ 'editingteacher' => CAP_ALLOW, 'coursecreator' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ] + 'manager' => CAP_ALLOW, + ], ], // View the capquiz reports. 'mod/capquiz:viewreports' => [ @@ -62,8 +62,8 @@ 'archetypes' => [ 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ] + 'manager' => CAP_ALLOW, + ], ], // Delete attempts using the overview report. 'mod/capquiz:deleteattempts' => [ @@ -72,8 +72,8 @@ 'contextlevel' => CONTEXT_MODULE, 'archetypes' => [ 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ] + 'manager' => CAP_ALLOW, + ], ], // Edit the quiz settings, add and remove questions. 'mod/capquiz:manage' => [ @@ -82,7 +82,7 @@ 'contextlevel' => CONTEXT_MODULE, 'archetypes' => [ 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ] + 'manager' => CAP_ALLOW, + ], ], ]; diff --git a/db/subplugins.php b/db/subplugins.php index 2500de9..fd47741 100644 --- a/db/subplugins.php +++ b/db/subplugins.php @@ -19,6 +19,7 @@ * * Currently only used for backwards compatibility, the sub-plugin definitions are in subplugins.json * + * @package mod_capquiz * @author André Storhaug * @copyright 2019 Norwegian University of Science and Technology (NTNU) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later @@ -28,10 +29,10 @@ // phpcs:disable /* -$subplugins = array( +$subplugins = [ 'capquizreport' => 'mod/capquiz/report', -); +]; */ // phpcs:enable -$subplugins = (array) json_decode(file_get_contents(__DIR__."/subplugins.json"))->plugintypes; +$subplugins = (array)json_decode(file_get_contents(__DIR__ . '/subplugins.json'))->plugintypes; diff --git a/db/upgrade.php b/db/upgrade.php index 8f48c0d..bb69056 100755 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -81,7 +81,7 @@ function xmldb_capquiz_upgrade($oldversion) { $qlist->level_2_rating, $qlist->level_3_rating, $qlist->level_4_rating, - $qlist->level_5_rating + $qlist->level_5_rating, ]); $DB->update_record('capquiz_question_list', $qlist); } @@ -105,11 +105,11 @@ function xmldb_capquiz_upgrade($oldversion) { $utable->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); // Adding keys to table capquiz_user_rating. - $utable->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); - $utable->add_key('capquiz_user_id', XMLDB_KEY_FOREIGN, array('capquiz_user_id'), 'capquiz_user', array('id')); + $utable->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); + $utable->add_key('capquiz_user_id', XMLDB_KEY_FOREIGN, ['capquiz_user_id'], 'capquiz_user', ['id']); // Adding indexes to table capquiz_user_rating. - $utable->add_index('timecreated', XMLDB_INDEX_NOTUNIQUE, array('timecreated')); + $utable->add_index('timecreated', XMLDB_INDEX_NOTUNIQUE, ['timecreated']); // Conditionally launch create table for enrol_lti_lti2_consumer. if (!$dbman->table_exists($utable)) { @@ -127,11 +127,11 @@ function xmldb_capquiz_upgrade($oldversion) { $qtable->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); // Adding keys to table capquiz_question_rating. - $qtable->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); - $qtable->add_key('capquiz_question_id', XMLDB_KEY_FOREIGN, array('capquiz_question_id'), 'capquiz_question', array('id')); + $qtable->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); + $qtable->add_key('capquiz_question_id', XMLDB_KEY_FOREIGN, ['capquiz_question_id'], 'capquiz_question', ['id']); // Adding indexes to table capquiz_question_rating. - $qtable->add_index('timecreated', XMLDB_INDEX_NOTUNIQUE, array('timecreated')); + $qtable->add_index('timecreated', XMLDB_INDEX_NOTUNIQUE, ['timecreated']); // Conditionally launch create table for capquiz_question_rating. if (!$dbman->table_exists($qtable)) { @@ -143,27 +143,27 @@ function xmldb_capquiz_upgrade($oldversion) { $aqrfield = new xmldb_field( 'question_rating_id', XMLDB_TYPE_INTEGER, 11, null, null, null, null); $aqrkey = new xmldb_key( - 'question_rating_id', XMLDB_KEY_FOREIGN, array('question_rating_id'), 'capquiz_question_rating', array('id')); + 'question_rating_id', XMLDB_KEY_FOREIGN, ['question_rating_id'], 'capquiz_question_rating', ['id']); $aqprevrfield = new xmldb_field( 'question_prev_rating_id', XMLDB_TYPE_INTEGER, 11, null, null, null, null); $aqprevrkey = new xmldb_key( 'question_prev_rating_id', - XMLDB_KEY_FOREIGN, array('question_prev_rating_id'), 'capquiz_question_rating', array('id')); + XMLDB_KEY_FOREIGN, ['question_prev_rating_id'], 'capquiz_question_rating', ['id']); $aprevqrfield = new xmldb_field( 'prev_question_rating_id', XMLDB_TYPE_INTEGER, 11, null, null, null, null); $aprevqrkey = new xmldb_key( 'prev_question_rating_id', - XMLDB_KEY_FOREIGN, array('prev_question_rating_id'), 'capquiz_question_rating', array('id')); + XMLDB_KEY_FOREIGN, ['prev_question_rating_id'], 'capquiz_question_rating', ['id']); $aprevqprevrfield = new xmldb_field( 'prev_question_prev_rating_id', XMLDB_TYPE_INTEGER, 11, null, null, null, null); $aprevqprevrkey = new xmldb_key( 'prev_question_prev_rating_id', - XMLDB_KEY_FOREIGN, array('prev_question_prev_rating_id'), 'capquiz_question_rating', array('id')); + XMLDB_KEY_FOREIGN, ['prev_question_prev_rating_id'], 'capquiz_question_rating', ['id']); if (!$dbman->field_exists($atable, $aqrfield)) { $dbman->add_field($atable, $aqrfield); @@ -185,13 +185,13 @@ function xmldb_capquiz_upgrade($oldversion) { $aurfield = new xmldb_field( 'user_rating_id', XMLDB_TYPE_INTEGER, 11, null, null, null, null); $aurkey = new xmldb_key( - 'user_rating_id', XMLDB_KEY_FOREIGN, array('user_rating_id'), 'capquiz_user_rating', array('id')); + 'user_rating_id', XMLDB_KEY_FOREIGN, ['user_rating_id'], 'capquiz_user_rating', ['id']); $aprevurfield = new xmldb_field( 'user_prev_rating_id', XMLDB_TYPE_INTEGER, 11, null, null, null, null); $aprevurkey = new xmldb_key( 'user_prev_rating_id', - XMLDB_KEY_FOREIGN, array('user_prev_rating_id'), 'capquiz_user_rating', array('id')); + XMLDB_KEY_FOREIGN, ['user_prev_rating_id'], 'capquiz_user_rating', ['id']); if (!$dbman->field_exists($atable, $aurfield)) { $dbman->add_field($atable, $aurfield); diff --git a/edit.php b/edit.php index 1929d59..7d34ce5 100755 --- a/edit.php +++ b/edit.php @@ -35,16 +35,8 @@ $context = \context_module::instance($cmid); require_capability('mod/capquiz:instructor', $context); -try { - $cmid = capquiz_urls::require_course_module_id_param(); - $capquiz = new capquiz($cmid); - capquiz_urls::set_page_url($capquiz, capquiz_urls::$urledit); - $bankrenderer = new output\question_bank_renderer($capquiz, $capquiz->renderer()); - $bankview = $bankrenderer->create_view(); - $renderer = $capquiz->renderer(); - $renderer->display_question_list_view($capquiz); - -} catch (\coding_exception $e) { - debugging ( "Exception: ".$e ); - capquiz_urls::redirect_to_front_page(); -} /* */ +$capquiz = new capquiz($cmid); +capquiz_urls::set_page_url($capquiz, capquiz_urls::$urledit); +$bankrenderer = new output\question_bank_renderer($capquiz, $capquiz->renderer()); +$bankview = $bankrenderer->create_view(); +$capquiz->renderer()->display_question_list_view($capquiz); diff --git a/lang/en/capquiz.php b/lang/en/capquiz.php index beb4089..3493b32 100755 --- a/lang/en/capquiz.php +++ b/lang/en/capquiz.php @@ -116,14 +116,13 @@ $string['need_to_log_in'] = 'You need to log in'; -$string['no_questions'] = 'No questions'; $string['no_enrolled_students'] = 'No students are enrolled'; $string['no_questions_added_to_list'] = 'No questions added to the list'; $string['no_matchmaking_strategy_selected'] = 'No selection strategy has been specified'; $string['nothing_to_configure_for_strategy'] = 'There is nothing to configure for this strategy'; $string['update_rating_explanation'] = '

The question ratings can be edited below. Changes are saved automatically.

'; -$string['question_list_no_questions'] = 'This capquiz has no questions. Add some questions from the list to the right'; +$string['question_list_no_questions'] = 'This capquiz has no questions. Add some questions from the question bank below.'; $string['n_closest'] = 'N-closest'; $string['chronological'] = 'Chronological'; $string['no_strategy_specified'] = 'No strategy specified'; @@ -178,7 +177,6 @@ $string['publish_no_questions_in_list'] = '

There doesn\'t seem to be any questions in the question list for this CAPQuiz instance. You must have at least one question before you can publish

'; $string['publish_already_published'] = '

This CAPQuiz is already published

'; -$string['no_question_list_assigned'] = 'No question list has been assigned'; $string['published'] = 'Published'; $string['not_published'] = 'Not published'; $string['question_list_not_published'] = 'The question list is not yet published'; diff --git a/lib.php b/lib.php index 02271ec..a89e2f6 100755 --- a/lib.php +++ b/lib.php @@ -25,6 +25,7 @@ */ use mod_capquiz\capquiz; +use mod_capquiz\output\question_attempt_renderer; defined('MOODLE_INTERNAL') || die(); @@ -34,9 +35,8 @@ * Add this capquiz instance to the database * * @param stdClass $modformdata The data submitted from the form - * @return bool|int */ -function capquiz_add_instance(stdClass $modformdata) { +function capquiz_add_instance(stdClass $modformdata): bool|int { global $DB; $modformdata->time_modified = time(); $modformdata->time_created = time(); @@ -48,9 +48,8 @@ function capquiz_add_instance(stdClass $modformdata) { * Update this instance in the database * * @param stdClass $capquiz database record - * @return bool */ -function capquiz_update_instance(stdClass $capquiz) { +function capquiz_update_instance(stdClass $capquiz): bool { global $DB; $capquiz->id = $capquiz->instance; $DB->update_record('capquiz', $capquiz); @@ -63,26 +62,22 @@ function capquiz_update_instance(stdClass $capquiz) { * * @param int $cmid Course module id for the instance to be deleted */ -function capquiz_delete_instance(int $cmid) { +function capquiz_delete_instance(int $cmid): void { $capquiz = new capquiz($cmid); - if ($capquiz) { - $user = $capquiz->user(); - if ($user) { - $quba = $user->question_usage(); - \question_engine::delete_questions_usage_by_activity($quba->get_id()); - } + $user = $capquiz->user(); + if ($user !== null) { + $quba = $user->question_usage(); + question_engine::delete_questions_usage_by_activity($quba->get_id()); } } /** * Implementation of the reset course functionality, delete all the assignment submissions for course $data->courseid. * - * @param object $data + * @param stdClass $data * @return array containing the statusreport from execution - * @throws coding_exception - * @throws dml_exception */ -function capquiz_reset_userdata($data) { +function capquiz_reset_userdata(stdClass $data): array { global $DB; $status = []; $strmodname = get_string('modulenameplural', 'capquiz'); @@ -99,7 +94,7 @@ function capquiz_reset_userdata($data) { continue; } foreach ($users as $user) { - \question_engine::delete_questions_usage_by_activity($user->question_usage_id); + question_engine::delete_questions_usage_by_activity($user->question_usage_id); $DB->delete_records('capquiz_attempt', ['user_id' => $user->id]); } $DB->delete_records('capquiz_user', ['capquiz_id' => $instance->id]); @@ -112,9 +107,8 @@ function capquiz_reset_userdata($data) { * Finds all assignment notifications that have yet to be mailed out, and mails them. * * Cron function to be run periodically according to the moodle cron. - * @return bool */ -function capquiz_cron() { +function capquiz_cron(): bool { return true; } @@ -123,9 +117,8 @@ function capquiz_cron() { * * @param settings_navigation $settings * @param navigation_node $capquiznode - * @return void */ -function capquiz_extend_settings_navigation($settings, $capquiznode) { +function capquiz_extend_settings_navigation(settings_navigation $settings, navigation_node $capquiznode): void { global $PAGE, $CFG; // Require {@link https://github.com/moodle/moodle/blob/master/lib/questionlib.php} @@ -140,9 +133,8 @@ function capquiz_extend_settings_navigation($settings, $capquiznode) { * * @param stdClass $capquiz database record * @param int $userid int or 0 for all users - * @return array */ -function capquiz_get_user_grades(stdClass $capquiz, int $userid = 0) { +function capquiz_get_user_grades(stdClass $capquiz, int $userid = 0): array { global $DB; $params = ['capquiz_id' => $capquiz->id]; if ($userid > 0) { @@ -168,15 +160,15 @@ function capquiz_get_user_grades(stdClass $capquiz, int $userid = 0) { * Create grade item for given assignment. * * @param stdClass $capquiz record with extra cmidnumber - * @param array $grades optional array/object of grade(s); 'reset' means reset grades in gradebook + * @param array|string|null $grades optional array/object of grade(s); 'reset' means reset grades in gradebook * @return int 0 if ok, error code otherwise */ -function capquiz_grade_item_update(stdClass $capquiz, $grades = null) { +function capquiz_grade_item_update(stdClass $capquiz, $grades = null): int { global $DB; $capquiz->cmidnumber = get_coursemodule_from_instance('capquiz', $capquiz->id)->id; $params = [ 'itemname' => $capquiz->name, - 'idnumber' => $capquiz->cmidnumber + 'idnumber' => $capquiz->cmidnumber, ]; $params['gradetype'] = GRADE_TYPE_VALUE; $params['grademax'] = 5; @@ -191,7 +183,7 @@ function capquiz_grade_item_update(stdClass $capquiz, $grades = null) { 'itemtype' => 'mod', 'itemmodule' => 'capquiz', 'iteminstance' => $capquiz->id, - 'outcomeid' => null + 'outcomeid' => null, ]); $item->gradepass = $capquiz->stars_to_pass; $item->update(); @@ -210,7 +202,7 @@ function capquiz_grade_item_update(stdClass $capquiz, $grades = null) { * @param int $userid specific user only, 0 means all * @param bool $nullifnone */ -function capquiz_update_grades(stdClass $capquiz, int $userid = 0, $nullifnone = true) { +function capquiz_update_grades(stdClass $capquiz, int $userid = 0, $nullifnone = true): void { $grades = capquiz_get_user_grades($capquiz, $userid); if ($grades) { capquiz_grade_item_update($capquiz, $grades); @@ -230,7 +222,7 @@ function capquiz_update_grades(stdClass $capquiz, int $userid = 0, $nullifnone = * @param int $courseid id of the course to be reset * @param string $type Optional type of assignment to limit the reset to a particular assignment type */ -function capquiz_reset_gradebook($courseid, $type = '') { +function capquiz_reset_gradebook($courseid, $type = ''): void { global $DB; $instances = $DB->get_records('capquiz', ['course' => $courseid]); foreach ($instances as $instance) { @@ -238,6 +230,40 @@ function capquiz_reset_gradebook($courseid, $type = '') { } } +/** + * Serve question files. + * + * @param stdClass $course + * @param stdClass $context + * @param string $component + * @param string $filearea + * @param int $qubaid + * @param int $slot + * @param array $args + * @param bool $forcedownload + * @param array $options + * @see quiz_question_pluginfile + */ +function capquiz_question_pluginfile(stdClass $course, stdClass $context, string $component, string $filearea, + int $qubaid, int $slot, array $args, bool $forcedownload, array $options = []): void { + global $DB; + $user = $DB->get_record('capquiz_user', ['question_usage_id' => $qubaid]); + $cm = get_coursemodule_from_instance('capquiz', $user->capquiz_id, $course->id, false, MUST_EXIST); + require_login($course, false, $cm); + $quba = question_engine::load_questions_usage_by_activity($qubaid); + $displayoptions = question_attempt_renderer::attempt_display_options(context_module::instance($cm->id)); + if (!$quba->check_file_access($slot, $displayoptions, $component, $filearea, $args, $forcedownload)) { + send_file_not_found(); + } + $fs = get_file_storage(); + $relativepath = implode('/', $args); + $fullpath = "/$context->id/$component/$filearea/$relativepath"; + $file = $fs->get_file_by_hash(sha1($fullpath)); + if (!$file || $file->is_directory()) { + send_file_not_found(); + } + send_stored_file($file, 0, 0, $forcedownload, $options); +} // Ugly hack to make 3.11 and 4.0 work seamlessly. if (!defined('FEATURE_MOD_PURPOSE')) { @@ -251,9 +277,8 @@ function capquiz_reset_gradebook($courseid, $type = '') { * Checks if $feature is supported * * @param string $feature - * @return mixed */ -function capquiz_supports($feature) { +function capquiz_supports(string $feature) { switch ($feature) { case FEATURE_MOD_INTRO: case FEATURE_BACKUP_MOODLE2: diff --git a/mod_form.php b/mod_form.php index 31e0f80..bbf9629 100755 --- a/mod_form.php +++ b/mod_form.php @@ -38,10 +38,8 @@ class mod_capquiz_mod_form extends moodleform_mod { /** * Defines the corm - * - * @throws coding_exception */ - public function definition() { + public function definition(): void { $form = $this->_form; $form->addElement('text', 'name', get_string('name'), ['size' => '64']); $form->setType('name', PARAM_TEXT); diff --git a/report/attempts/attempts_form.php b/report/attempts/attempts_form.php index 4f65453..6b86efc 100644 --- a/report/attempts/attempts_form.php +++ b/report/attempts/attempts_form.php @@ -49,9 +49,8 @@ class capquizreport_attempts_settings_form extends capquiz_attempts_report_form * @return array of "element_name"=>"error_description" if there are errors, * or an empty array if everything is OK (true allowed for backwards compatibility too). */ - public function validation($data, $files) { + public function validation($data, $files): array { $errors = parent::validation($data, $files); - if (!($data['urating'] || $data['uprevrating'] || $data['qprevrating'] @@ -61,7 +60,6 @@ public function validation($data, $files) { || $data['right'])) { $errors['coloptions'] = get_string('reportmustselectstate', 'quiz'); } - return $errors; } @@ -70,22 +68,15 @@ public function validation($data, $files) { * * @param MoodleQuickForm $mform the form to add preference fields to */ - protected function other_preference_fields(MoodleQuickForm $mform) { - $mform->addGroup(array( - $mform->createElement('advcheckbox', 'ansstate', '', - get_string('ansstate', 'capquizreport_attempts')), - $mform->createElement('advcheckbox', 'urating', '', - get_string('urating', 'capquizreport_attempts')), - $mform->createElement('advcheckbox', 'uprevrating', '', - get_string('uprevrating', 'capquizreport_attempts')), - $mform->createElement('advcheckbox', 'qprevrating', '', - get_string('qprevrating', 'capquizreport_attempts')), - $mform->createElement('advcheckbox', 'qtext', '', - get_string('questiontext', 'quiz_responses')), - $mform->createElement('advcheckbox', 'resp', '', - get_string('response', 'quiz_responses')), - $mform->createElement('advcheckbox', 'right', '', - get_string('rightanswer', 'quiz_responses')), - ), 'coloptions', get_string('showthe', 'quiz_responses'), array(' '), false); + protected function other_preference_fields(MoodleQuickForm $mform): void { + $mform->addGroup([ + $mform->createElement('advcheckbox', 'ansstate', '', get_string('ansstate', 'capquizreport_attempts')), + $mform->createElement('advcheckbox', 'urating', '', get_string('urating', 'capquizreport_attempts')), + $mform->createElement('advcheckbox', 'uprevrating', '', get_string('uprevrating', 'capquizreport_attempts')), + $mform->createElement('advcheckbox', 'qprevrating', '', get_string('qprevrating', 'capquizreport_attempts')), + $mform->createElement('advcheckbox', 'qtext', '', get_string('questiontext', 'quiz_responses')), + $mform->createElement('advcheckbox', 'resp', '', get_string('response', 'quiz_responses')), + $mform->createElement('advcheckbox', 'right', '', get_string('rightanswer', 'quiz_responses')), + ], 'coloptions', get_string('showthe', 'quiz_responses'), [' '], false); } } diff --git a/report/attempts/attempts_options.php b/report/attempts/attempts_options.php index 9bd18c8..175f967 100644 --- a/report/attempts/attempts_options.php +++ b/report/attempts/attempts_options.php @@ -28,12 +28,12 @@ use context_module; use mod_capquiz\report\capquiz_attempts_report; use mod_capquiz\report\capquiz_attempts_report_options; +use stdClass; defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/mod/capquiz/report/attemptsreport_options.php'); - /** * Class to store the options for a {@see capquiz_attempts_report}. * @@ -67,7 +67,7 @@ class capquizreport_attempts_options extends capquiz_attempts_report_options { /** * Get the current value of the settings to pass to the settings form. */ - public function get_initial_form_data() { + public function get_initial_form_data(): stdClass { $toform = parent::get_initial_form_data(); $toform->ansstate = $this->showansstate; $toform->urating = $this->showurating; @@ -84,7 +84,7 @@ public function get_initial_form_data() { * Set the fields of this object from the form data. * @param object $fromform The data from $mform->get_data() from the settings form. */ - public function setup_from_form_data($fromform) { + public function setup_from_form_data($fromform): void { parent::setup_from_form_data($fromform); $this->showansstate = $fromform->ansstate; @@ -99,7 +99,7 @@ public function setup_from_form_data($fromform) { /** * Set the fields of this object from the URL parameters. */ - public function setup_from_params() { + public function setup_from_params(): void { parent::setup_from_params(); $this->showansstate = optional_param('ansstate', $this->showansstate, PARAM_BOOL); @@ -115,7 +115,7 @@ public function setup_from_params() { * Set the fields of this object from the user's preferences. * (For those settings that are backed by user-preferences). */ - public function setup_from_user_preferences() { + public function setup_from_user_preferences(): void { parent::setup_from_user_preferences(); $this->showansstate = get_user_preferences('capquizreport_attempts_ansstate', $this->showansstate); @@ -131,7 +131,7 @@ public function setup_from_user_preferences() { * Update the user preferences so they match the settings in this object. * (For those settings that are backed by user-preferences). */ - public function update_user_preferences() { + public function update_user_preferences(): void { parent::update_user_preferences(); set_user_preference('capquizreport_attempts_ansstate', $this->showansstate); @@ -146,7 +146,7 @@ public function update_user_preferences() { /** * Check the settings, and remove any 'impossible' combinations. */ - public function resolve_dependencies() { + public function resolve_dependencies(): void { parent::resolve_dependencies(); if (!$this->showansstate @@ -170,9 +170,10 @@ public function resolve_dependencies() { /** * Get the URL parameters required to show the report with these options. + * * @return array URL parameter name => value. */ - protected function get_url_params() { + protected function get_url_params(): array { $params = parent::get_url_params(); $params['ansstate'] = $this->showansstate; $params['urating'] = $this->showurating; diff --git a/report/attempts/attempts_table.php b/report/attempts/attempts_table.php index ae3f0c7..16e974c 100644 --- a/report/attempts/attempts_table.php +++ b/report/attempts/attempts_table.php @@ -25,18 +25,18 @@ namespace capquizreport_attempts; +use core\context; use core\dml\sql_join; use mod_capquiz\report\capquiz_attempts_report_options; use mod_capquiz\report\capquiz_attempts_report_table; use moodle_url; -use quiz_responses_options; +use stdClass; defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/mod/capquiz/report/attemptsreport_table.php'); require_once($CFG->dirroot . '/mod/quiz/locallib.php'); - /** * This is a table subclass for displaying the capquiz attempts report. * @@ -55,7 +55,7 @@ class capquizreport_attempts_table extends capquiz_attempts_report_table { * @param array $questions * @param moodle_url $reporturl */ - public function __construct($capquiz, $context, capquiz_attempts_report_options $options, + public function __construct($capquiz, context $context, capquiz_attempts_report_options $options, sql_join $studentsjoins, $questions, $reporturl) { parent::__construct('mod-capquiz-report-attempts-report', $capquiz, $context, $options, $studentsjoins, $questions, $reporturl); @@ -73,7 +73,6 @@ public function build_table() { if (!$this->rawdata) { return; } - $this->strtimeformat = str_replace(',', ' ', get_string('strftimedatetimeseconds', 'capquiz')); parent::build_table(); } @@ -83,75 +82,58 @@ public function build_table() { * * @param string $colname The column name * @param stdClass $attempt The attempt - * @return mixed string or NULL + * @return ?string */ - public function other_cols($colname, $attempt) { - switch ($colname) { - case 'question': - return $this->data_col($attempt->slot, 'questionsummary', $attempt); - case 'response': - return $this->data_col($attempt->slot, 'responsesummary', $attempt); - case 'right': - return $this->data_col($attempt->slot, 'rightanswer', $attempt); - default: - return null; - } + public function other_cols($colname, $attempt): ?string { + return match ($colname) { + 'question' => $this->data_col($attempt->slot, 'questionsummary', $attempt), + 'response' => $this->data_col($attempt->slot, 'responsesummary', $attempt), + 'right' => $this->data_col($attempt->slot, 'rightanswer', $attempt), + default => null, + }; } /** * Format a single column, used in other_cols * - * @param integer $slot attempts slot + * @param int $slot * @param string $field - * @param object $attempt - * @return string + * @param stdClass $attempt */ - public function data_col($slot, $field, $attempt) { + public function data_col(int $slot, string $field, stdClass $attempt): string { if ($attempt->usageid == 0) { return '-'; } $value = $this->field_from_extra_data($attempt, $slot, $field); - - if (is_null($value)) { - $summary = '-'; - } else { - $summary = trim($value); - } - + $summary = $value !== null ? trim($value) : '-'; if ($this->is_downloading() && $this->is_downloading() != 'html') { return $summary; } $summary = s($summary); - if ($this->is_downloading()) { return $summary; } - if ($field === 'responsesummary') { return $this->make_review_link($summary, $attempt, $slot); - - } else if ($field === 'questionsummary') { + } + if ($field === 'questionsummary') { return $this->make_preview_link($summary, $attempt, $slot); - - } else { - return $summary; } + return $summary; } /** * Column text from the extra data loaded in load_extra_data(), before html formatting etc. * - * @param object $attempt + * @param stdClass $attempt * @param int $slot * @param string $field - * @return string */ - protected function field_from_extra_data($attempt, $slot, $field) { + protected function field_from_extra_data(stdClass $attempt, int $slot, string $field): string { if (!isset($this->lateststeps[$attempt->usageid][$slot])) { return '-'; } $stepdata = $this->lateststeps[$attempt->usageid][$slot]; - if (property_exists($stepdata, $field . 'full')) { $value = $stepdata->{$field . 'full'}; } else { @@ -162,14 +144,12 @@ protected function field_from_extra_data($attempt, $slot, $field) { /** * Generate the display of the answer state column. - * @param object $attempt the table row being output. + * + * @param stdClass $attempt the table row being output. * @return string HTML content to go inside the td. */ - public function col_answerstate($attempt) { - if (is_null($attempt->attempt)) { - return '-'; - } - if ($attempt->usageid == 0) { + public function col_answerstate(stdClass $attempt): string { + if ($attempt->attempt === null || $attempt->usageid === 0) { return '-'; } $state = $this->slot_state($attempt, $attempt->slot); @@ -182,54 +162,41 @@ public function col_answerstate($attempt) { /** * Generate the display of the user rating column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_userrating($attempt) { - if ($attempt->userrating) { - return $attempt->userrating; - } else { - return '-'; - } + public function col_userrating(stdClass $attempt): string { + return $attempt->userrating ?: '-'; } /** * Generate the display of the question rating column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_questionrating($attempt) { - if ($attempt->questionrating) { - return $attempt->questionrating; - } else { - return '-'; - } + public function col_questionrating(stdClass $attempt): string { + return $attempt->questionrating ?: '-'; } /** * Generate the display of the users's previous rating column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_userprevrating($attempt) { - if ($attempt->userrating) { - return $attempt->prevuserrating; - } else { - return '-'; - } + public function col_userprevrating(stdClass $attempt): string { + return $attempt->userrating ? $attempt->prevuserrating : '-'; } /** * Generate the display of the question's previous rating column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + + * @param stdClass $attempt the table row being output. */ - public function col_questionprevrating($attempt) { + public function col_questionprevrating(stdClass $attempt): string { global $OUTPUT; if ($attempt->prevquestionrating) { - $warningicon = $OUTPUT->pix_icon('i/warning', get_string('rating_manually_updated', 'capquizreport_attempts'), - 'moodle', array('class' => 'icon')); - + $warningalt = get_string('rating_manually_updated', 'capquizreport_attempts'); + $warningicon = $OUTPUT->pix_icon('i/warning', $warningalt, 'moodle', ['class' => 'icon']); if (!$this->is_downloading() && $attempt->manualprevqrating) { return $warningicon . $attempt->prevquestionrating; } else { @@ -242,25 +209,20 @@ public function col_questionprevrating($attempt) { /** * Generate the display of the question's previous rating manual column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_questionprevratingmanual($attempt) { - if (is_null($attempt->manualprevqrating)) { + public function col_questionprevratingmanual(stdClass $attempt): string { + if ($attempt->manualprevqrating === null) { return '-'; } - $ismanual = ($attempt->manualprevqrating) ? 'true' : 'false'; - $manualprevqrating = get_string($ismanual, 'capquiz'); - return $manualprevqrating; + return get_string($attempt->manualprevqrating ? 'true' : 'false', 'capquiz'); } /** - * Does this report require the detailed information for each question from the - * question_attempts_steps table? - * - * @return bool + * Does this report require the detailed information for each question from the question_attempts_steps table? */ - protected function requires_latest_steps_loaded() { + protected function requires_latest_steps_loaded(): bool { if ($this->options->showansstate || $this->options->showqtext || $this->options->showresponses @@ -288,13 +250,14 @@ protected function is_latest_step_column($column) { /** * A chance for subclasses to modify the SQL after the count query has been generated, * and before the full query is constructed. + * * @param string $fields SELECT list. * @param string $from JOINs part of the SQL. * @param string $where WHERE clauses. * @param array $params Query params. * @return array with 4 elements ($fields, $from, $where, $params) as from base_sql. */ - protected function update_sql_after_count($fields, $from, $where, $params) { + protected function update_sql_after_count($fields, $from, $where, $params): array { $fields .= ', cq.question_id AS moodlequestionid, cqr.rating AS questionrating, diff --git a/report/attempts/report.php b/report/attempts/report.php index e7baa25..8e504ba 100644 --- a/report/attempts/report.php +++ b/report/attempts/report.php @@ -26,7 +26,9 @@ namespace capquizreport_attempts; use context_course; +use mod_capquiz\capquiz; use mod_capquiz\report\capquiz_attempts_report; +use stdClass; defined('MOODLE_INTERNAL') || die(); @@ -51,17 +53,16 @@ class capquizreport_attempts_report extends capquiz_attempts_report { * @param stdClass $course - course object * @param string $download - type of download being requested */ - public function display($capquiz, $cm, $course, $download) { - global $OUTPUT, $DB; + public function display($capquiz, $cm, $course, $download): bool { + global $DB; - list($studentsjoins) = $this->init( - 'attempts', 'capquizreport_attempts\capquizreport_attempts_settings_form', $capquiz, $cm, $course); + list($studentsjoins) = $this->init('attempts', 'capquizreport_attempts\capquizreport_attempts_settings_form', + $capquiz, $cm, $course); $this->options = new capquizreport_attempts_options('attempts', $capquiz, $cm, $course); if ($fromform = $this->form->get_data()) { $this->options->process_settings_from_form($fromform); - } else { $this->options->process_settings_from_params(); } @@ -72,15 +73,16 @@ public function display($capquiz, $cm, $course, $download) { $questions = capquiz_report_get_questions($capquiz); // Prepare for downloading, if applicable. - $courseshortname = format_string($course->shortname, true, - array('context' => context_course::instance($course->id))); + $courseshortname = format_string($course->shortname, true, ['context' => context_course::instance($course->id)]); $table = new capquizreport_attempts_table($capquiz, $this->context, $this->options, $studentsjoins, $questions, $this->options->get_url()); + $filename = capquiz_report_download_filename(get_string('attemptsfilename', 'capquizreport_attempts'), $courseshortname, $capquiz->name()); - $table->is_downloading($this->options->download, $filename, - $courseshortname . ' ' . format_string($capquiz->name(), true)); + + $table->is_downloading($this->options->download, $filename, $courseshortname . ' ' . format_string($capquiz->name())); + if ($table->is_downloading()) { raise_memory_limit(MEMORY_EXTRA); } @@ -103,8 +105,7 @@ public function display($capquiz, $cm, $course, $download) { // Start output. if (!$table->is_downloading()) { // Only print headers if not asked to download data. - $this->print_standard_header_and_messages($cm, $course, $capquiz, - $this->options, $hasquestions, $hasstudents); + $this->print_standard_header_and_messages($cm, $course, $capquiz, $this->options, $hasquestions, $hasstudents); // Print the display options. $this->form->display(); @@ -115,8 +116,8 @@ public function display($capquiz, $cm, $course, $download) { $table->setup_sql_queries($studentsjoins); // Define table columns. - $columns = array(); - $headers = array(); + $columns = []; + $headers = []; if (!$table->is_downloading() && $this->options->checkboxcolumn) { $columns[] = 'checkbox'; diff --git a/report/attemptsreport.php b/report/attemptsreport.php index 3e4bc10..6e4182e 100644 --- a/report/attemptsreport.php +++ b/report/attemptsreport.php @@ -26,9 +26,11 @@ namespace mod_capquiz\report; use context_module; +use core\context\module; use core\dml\sql_join; -use mod_quiz_attempts_report_form; -use mod_quiz_attempts_report_options; +use mod_capquiz\capquiz; +use mod_quiz\local\reports\attempts_report_options; +use mod_quiz\local\reports\attempts_report_options_form; use moodle_url; use stdClass; use table_sql; @@ -38,7 +40,6 @@ require_once($CFG->libdir . '/tablelib.php'); require_once($CFG->dirroot . '/mod/capquiz/report/report.php'); - /** * Base class for capquiz reports that are basically a table with one row for each attempt. * @@ -62,13 +63,13 @@ abstract class capquiz_attempts_report extends report { /** @var string the mode this report is. */ protected $mode; - /** @var object the capquiz context. */ - protected $context; + /** @var module the capquiz context. */ + protected module $context; - /** @var mod_quiz_attempts_report_form The settings form to use. */ + /** @var attempts_report_options_form The settings form to use. */ protected $form; - /** @var object mod_quiz_attempts_report_options the options affecting this report. */ + /** @var attempts_report_options the options affecting this report. */ protected $options = null; /** @@ -86,27 +87,20 @@ abstract class capquiz_attempts_report extends report { * 3 => \core\dml\sql_join Contains joins, wheres, params for all the students to show in the report. * Will be the same as either element 1 or 2. */ - protected function init($mode, $formclass, $capquiz, $cm, $course) { + protected function init(string $mode, string $formclass, $capquiz, $cm, $course) { $this->mode = $mode; - $this->context = context_module::instance($cm->id); - $studentsjoins = get_enrolled_with_capabilities_join($this->context); - - $this->form = new $formclass($this->get_base_url(), - array('capquiz' => $capquiz, 'context' => $this->context)); - - return array($studentsjoins); + $this->form = new $formclass($this->get_base_url(), ['capquiz' => $capquiz, 'context' => $this->context]); + return [$studentsjoins]; } /** * Get the base URL for this report. - * @return moodle_url the URL. */ - protected function get_base_url() { - return new moodle_url('/mod/capquiz/view_report.php', - array('id' => $this->context->instanceid, 'mode' => $this->mode)); + protected function get_base_url(): moodle_url { + return new moodle_url('/mod/capquiz/view_report.php', ['id' => $this->context->instanceid, 'mode' => $this->mode]); } /** @@ -118,19 +112,21 @@ protected function get_base_url() { * * @param stdClass $cm the course_module information. * @param stdClass $course the course settings. - * @param stdClass $capquiz the capquiz settings. - * @param mod_quiz_attempts_report_options $options the current report settings. + * @param capquiz $capquiz the capquiz settings. + * @param attempts_report_options $options the current report settings. * @param bool $hasquestions whether there are any questions in the capquiz. * @param bool $hasstudents whether there are any relevant students. */ - protected function print_standard_header_and_messages($cm, $course, $capquiz, - $options, $hasquestions, $hasstudents) { + protected function print_standard_header_and_messages(stdClass $cm, stdClass $course, capquiz $capquiz, + attempts_report_options $options, bool $hasquestions, + bool $hasstudents): void { global $OUTPUT; - echo $this->print_header_and_tabs($cm, $course, $capquiz, $this->mode); + $this->print_header_and_tabs($cm, $course, $capquiz, $this->mode); // Print information on the number of existing attempts. - if ($strattemptnum = capquiz_num_attempt_summary($capquiz, true)) { + $strattemptnum = capquiz_num_attempt_summary($capquiz, true); + if (!empty($strattemptnum)) { echo '
' . $strattemptnum . '
'; } @@ -141,16 +137,16 @@ protected function print_standard_header_and_messages($cm, $course, $capquiz, } else if (!$hasstudents) { echo $OUTPUT->notification(get_string('nostudentsyet')); } - } /** * Add all the user-related columns to the $columns and $headers arrays. + * * @param table_sql $table the table being constructed. * @param array $columns the list of columns. Added to. * @param array $headers the columns headings. Added to. */ - protected function add_user_columns($table, &$columns, &$headers) { + protected function add_user_columns(table_sql $table, array &$columns, array &$headers): void { global $CFG; if (!$table->is_downloading() && $CFG->grade_report_showuserimage) { $columns[] = 'picture'; @@ -168,11 +164,11 @@ protected function add_user_columns($table, &$columns, &$headers) { // When downloading, some extra fields are always displayed (because // there's no space constraint) so do not include in extra-field list. - $extrafields = - $table->is_downloading() ? - \core_user\fields::for_identity($this->context)->including( - 'institution', 'department', 'email')->get_required_fields() : - \core_user\fields::for_identity($this->context)->get_required_fields(); + $fields = \core_user\fields::for_identity($this->context); + if ($table->is_downloading()) { + $fields = $fields->including('institution', 'department', 'email')->get_required_fields(); + } + $extrafields = $fields->get_required_fields(); foreach ($extrafields as $field) { $columns[] = $field; @@ -193,60 +189,63 @@ protected function add_user_columns($table, &$columns, &$headers) { /** * Add the state column to the $columns and $headers arrays. + * * @param array $columns the list of columns. Added to. * @param array $headers the columns headings. Added to. */ - protected function add_questionid_column(&$columns, &$headers) { + protected function add_questionid_column(array &$columns, array &$headers): void { $columns[] = 'questionid'; $headers[] = get_string('questionid', 'capquiz'); } /** * Add the state column to the $columns and $headers arrays. + * * @param array $columns the list of columns. Added to. * @param array $headers the columns headings. Added to. */ - protected function add_moodlequestionid_column(&$columns, &$headers) { + protected function add_moodlequestionid_column(array &$columns, array &$headers): void { $columns[] = 'moodlequestionid'; $headers[] = get_string('moodlequestionid', 'capquiz'); } /** * Add the state column to the $columns and $headers arrays. + * * @param array $columns the list of columns. Added to. * @param array $headers the columns headings. Added to. */ - protected function add_uesrid_column(&$columns, &$headers) { + protected function add_uesrid_column(array &$columns, array &$headers): void { $columns[] = 'userid'; $headers[] = get_string('userid', 'capquiz'); } /** * Add all the time-related columns to the $columns and $headers arrays. + * * @param array $columns the list of columns. Added to. * @param array $headers the columns headings. Added to. */ - protected function add_time_columns(&$columns, &$headers) { + protected function add_time_columns(array &$columns, array &$headers): void { $columns[] = 'timeanswered'; $headers[] = get_string('timeanswered', 'capquiz'); $columns[] = 'timereviewed'; $headers[] = get_string('timereviewed', 'capquiz'); - } /** * Set the display options for the user-related columns in the table. + * * @param table_sql $table the table being constructed. */ - protected function configure_user_columns($table) { + protected function configure_user_columns(table_sql $table): void { $table->column_suppress('picture'); $table->column_suppress('fullname'); $extrafields = \core_user\fields::for_identity($this->context)->get_required_fields(); foreach ($extrafields as $field) { $table->column_suppress($field); } - $table->column_class('picture', 'picture'); $table->column_class('lastname', 'bold'); $table->column_class('firstname', 'bold'); @@ -255,34 +254,33 @@ protected function configure_user_columns($table) { /** * Process any submitted actions. - * @param object $quiz the capquiz settings. - * @param object $cm the cm object for the capquiz. + * + * @param stdClass $capquiz + * @param stdClass $cm the cm object for the capquiz. * @param sql_join $allowedjoins (joins, wheres, params) the users whose attempt this user is allowed to modify. * @param moodle_url $redirecturl where to redircet to after a successful action. */ - protected function process_actions($quiz, $cm, sql_join $allowedjoins, $redirecturl) { + protected function process_actions(stdClass $capquiz, stdClass $cm, sql_join $allowedjoins, moodle_url $redirecturl): void { if (optional_param('delete', 0, PARAM_BOOL) && confirm_sesskey()) { - if ($attemptids = optional_param_array('attemptid', array(), PARAM_INT)) { + if ($attemptids = optional_param_array('attemptid', [], PARAM_INT)) { require_capability('mod/capquiz:deleteattempts', $this->context); - $this->delete_selected_attempts($quiz, $cm, $attemptids, $allowedjoins); + $this->delete_selected_attempts($capquiz, $cm, $attemptids, $allowedjoins); redirect($redirecturl); } } } /** - * Delete the capquiz attempts - * @param object $capquiz the capquiz settings. Attempts that don't belong to - * this capquiz are not deleted. - * @param object $cm the course_module object. + * Delete the capquiz attempts. + * + * @param stdClass $capquiz the capquiz settings. Attempts that don't belong to this capquiz are not deleted. + * @param stdClass $cm the course_module object. * @param array $attemptids the list of attempt ids to delete. * @param sql_join $allowedjoins (joins, wheres, params) This list of userids that are visible in the report. * Users can only delete attempts that they are allowed to see in the report. * Empty means all users. */ - protected function delete_selected_attempts($capquiz, $cm, $attemptids, sql_join $allowedjoins) { - global $DB; + protected function delete_selected_attempts(stdClass $capquiz, stdClass $cm, array $attemptids, sql_join $allowedjoins) { // TODO implement to add support for attempt deletion. - } } diff --git a/report/attemptsreport_form.php b/report/attemptsreport_form.php index 6a490aa..559dcf2 100644 --- a/report/attemptsreport_form.php +++ b/report/attemptsreport_form.php @@ -32,7 +32,6 @@ require_once($CFG->libdir . '/formslib.php'); - /** * Base class for the settings form for {@see capquiz_attempts_report}s. * @@ -58,23 +57,18 @@ public function validation($data, $files) { /** * Defines the form */ - protected function definition() { + protected function definition(): void { $mform = $this->_form; - $mform->addElement('header', 'preferencespage', - get_string('reportwhattoinclude', 'quiz')); - + $mform->addElement('header', 'preferencespage', get_string('reportwhattoinclude', 'quiz')); $this->standard_attempt_fields($mform); $this->other_attempt_fields($mform); - $mform->addElement('header', 'preferencesuser', - get_string('reportdisplayoptions', 'quiz')); - + $mform->addElement('header', 'preferencesuser', get_string('reportdisplayoptions', 'quiz')); $this->standard_preference_fields($mform); $this->other_preference_fields($mform); - $mform->addElement('submit', 'submitbutton', - get_string('showreport', 'quiz')); + $mform->addElement('submit', 'submitbutton', get_string('showreport', 'quiz')); } /** @@ -82,19 +76,17 @@ protected function definition() { * * @param MoodleQuickForm $mform the form to add attempt fields to */ - protected function standard_attempt_fields(MoodleQuickForm $mform) { - - $mform->addElement('select', 'attempts', get_string('reportattemptsfrom', 'quiz'), array( + protected function standard_attempt_fields(MoodleQuickForm $mform): void { + $mform->addElement('select', 'attempts', get_string('reportattemptsfrom', 'quiz'), [ capquiz_attempts_report::ENROLLED_WITH => get_string('reportuserswith', 'quiz'), // phpcs:disable // capquiz_attempts_report::ENROLLED_WITHOUT => get_string('reportuserswithout', 'quiz'), // capquiz_attempts_report::ENROLLED_ALL => get_string('reportuserswithorwithout', 'quiz'), // phpcs:enable capquiz_attempts_report::ALL_WITH => get_string('reportusersall', 'quiz'), - )); + ]); - $mform->addElement('advcheckbox', 'onlyanswered', '', - get_string('reportshowonlyanswered', 'capquiz')); + $mform->addElement('advcheckbox', 'onlyanswered', '', get_string('reportshowonlyanswered', 'capquiz')); $mform->addHelpButton('onlyanswered', 'reportshowonlyanswered', 'capquiz'); } diff --git a/report/attemptsreport_options.php b/report/attemptsreport_options.php index fe36227..5451f1f 100644 --- a/report/attemptsreport_options.php +++ b/report/attemptsreport_options.php @@ -33,7 +33,6 @@ require_once($CFG->libdir . '/formslib.php'); - /** * Base class for the options that control what is visible in an {@see quiz_attempts_report}. * @@ -83,42 +82,40 @@ class capquiz_attempts_report_options { * @param object $course the course settings for the coures this capquiz is in. */ public function __construct(string $mode, capquiz $capquiz, object $cm, object $course) { - $this->mode = $mode; - $this->capquiz = $capquiz; - $this->cm = $cm; - $this->course = $course; + $this->mode = $mode; + $this->capquiz = $capquiz; + $this->cm = $cm; + $this->course = $course; } /** * Get the URL parameters required to show the report with these options. + * * @return array URL parameter name => value. */ - protected function get_url_params() { - $params = array( - 'id' => $this->cm->id, - 'mode' => $this->mode, - 'attempts' => $this->attempts, + protected function get_url_params(): array { + return [ + 'id' => $this->cm->id, + 'mode' => $this->mode, + 'attempts' => $this->attempts, 'onlyanswered' => $this->onlyanswered, - ); - - return $params; + ]; } /** * Get the URL to show the report with these options. - * @return moodle_url the URL. */ - public function get_url() { + public function get_url(): moodle_url { return new moodle_url('/mod/capquiz/view_report.php', $this->get_url_params()); } /** * Process the data we get when the settings form is submitted. This includes - * updating the fields of this class, and updating the user preferences - * where appropriate. - * @param object $fromform The data from $mform->get_data() from the settings form. + * updating the fields of this class, and updating the user preferences where appropriate. + * + * @param stdClass $fromform The data from $mform->get_data() from the settings form. */ - public function process_settings_from_form($fromform) { + public function process_settings_from_form(stdClass $fromform): void { $this->setup_from_form_data($fromform); $this->resolve_dependencies(); $this->update_user_preferences(); @@ -128,7 +125,7 @@ public function process_settings_from_form($fromform) { * Set up this preferences object using optional_param (using user_preferences * to set anything not specified by the params. */ - public function process_settings_from_params() { + public function process_settings_from_params(): void { $this->setup_from_user_preferences(); $this->setup_from_params(); $this->resolve_dependencies(); @@ -137,59 +134,57 @@ public function process_settings_from_params() { /** * Get the current value of the settings to pass to the settings form. */ - public function get_initial_form_data() { + public function get_initial_form_data(): stdClass { $toform = new stdClass(); - $toform->attempts = $this->attempts; + $toform->attempts = $this->attempts; $toform->onlyanswered = $this->onlyanswered; - $toform->pagesize = $this->pagesize; - + $toform->pagesize = $this->pagesize; return $toform; } /** * Set the fields of this object from the form data. - * @param object $fromform The data from $mform->get_data() from the settings form. + * @param stdClass $fromform The data from $mform->get_data() from the settings form. */ - public function setup_from_form_data($fromform) { - $this->attempts = $fromform->attempts; + public function setup_from_form_data(stdClass $fromform): void { + $this->attempts = $fromform->attempts; $this->onlyanswered = !empty($fromform->onlyanswered); - $this->pagesize = $fromform->pagesize; + $this->pagesize = $fromform->pagesize; } /** * Set the fields of this object from the URL parameters. */ - public function setup_from_params() { - $this->attempts = optional_param('attempts', $this->attempts, PARAM_ALPHAEXT); + public function setup_from_params(): void { + $this->attempts = optional_param('attempts', $this->attempts, PARAM_ALPHAEXT); $this->onlyanswered = optional_param('onlyanswered', $this->onlyanswered, PARAM_BOOL); - $this->pagesize = optional_param('pagesize', $this->pagesize, PARAM_INT); - $this->download = optional_param('download', $this->download, PARAM_ALPHA); + $this->pagesize = optional_param('pagesize', $this->pagesize, PARAM_INT); + $this->download = optional_param('download', $this->download, PARAM_ALPHA); } /** * Set the fields of this object from the user's preferences. * (For those settings that are backed by user-preferences). */ - public function setup_from_user_preferences() { + public function setup_from_user_preferences(): void { $this->pagesize = get_user_preferences('capquiz_report_pagesize', $this->pagesize); } /** - * Update the user preferences so they match the settings in this object. + * Update the user preferences, so they match the settings in this object. * (For those settings that are backed by user-preferences). */ - public function update_user_preferences() { + public function update_user_preferences(): void { set_user_preference('capquiz_report_pagesize', $this->pagesize); } /** * Check the settings, and remove any 'impossible' combinations. */ - public function resolve_dependencies() { + public function resolve_dependencies(): void { if ($this->pagesize < 1) { $this->pagesize = capquiz_attempts_report::DEFAULT_PAGE_SIZE; } } - } diff --git a/report/attemptsreport_table.php b/report/attemptsreport_table.php index 1b6c8c6..173bbbf 100644 --- a/report/attemptsreport_table.php +++ b/report/attemptsreport_table.php @@ -26,25 +26,22 @@ namespace mod_capquiz\report; use coding_exception; +use core\context; +use core\context\module; use core\dml\sql_join; use html_writer; -use mod_capquiz\capquiz_question_attempt; -use mod_quiz_attempts_report_options; use moodle_url; use qubaid_condition; use qubaid_list; use question_engine_data_mapper; use question_state; -use quiz_attempt; use stdClass; use table_sql; -use user_picture; defined('MOODLE_INTERNAL') || die(); require_once($CFG->libdir . '/tablelib.php'); - /** * Base class for the table used by a {@see capquiz_attempts_report}. * @@ -89,7 +86,8 @@ abstract class capquiz_attempts_report_table extends table_sql { protected $includecheckboxes; /** - * Constructor + * Constructor. + * * @param string $uniqueid * @param object $quiz * @param context $context @@ -98,9 +96,8 @@ abstract class capquiz_attempts_report_table extends table_sql { * @param array $questions * @param moodle_url $reporturl */ - public function __construct($uniqueid, $quiz, $context, - capquiz_attempts_report_options $options, sql_join $studentsjoins, - $questions, $reporturl) { + public function __construct($uniqueid, $quiz, context $context, capquiz_attempts_report_options $options, + sql_join $studentsjoins, $questions, $reporturl) { parent::__construct($uniqueid); $this->capquiz = $quiz; $this->context = $context; @@ -113,11 +110,11 @@ public function __construct($uniqueid, $quiz, $context, /** * Generate the display of the checkbox column. - * @param object $attempt the table row being output. + * @param stdClass $attempt the table row being output. * @return string HTML content to go inside the td. */ - public function col_checkbox($attempt) { - if ($attempt->attempt) { + public function col_checkbox(stdClass $attempt): string { + if (property_exists($attempt, 'attempt')) { return ''; } else { return ''; @@ -126,10 +123,10 @@ public function col_checkbox($attempt) { /** * Generate the display of the user's full name column. + * * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. */ - public function col_fullname($attempt) { + public function col_fullname($attempt): string { $html = parent::col_fullname($attempt); if ($this->is_downloading() || empty($attempt->attempt)) { return $html; @@ -144,68 +141,48 @@ public function col_fullname($attempt) { /** * Generate the display of the time answered column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_timeanswered($attempt) { - if ($attempt->attempt) { - return userdate($attempt->timeanswered, $this->strtimeformat); - } else { - return '-'; - } + public function col_timeanswered(stdClass $attempt): string { + return property_exists($attempt, 'attempt') ? userdate($attempt->timeanswered, $this->strtimeformat) : '-'; } /** * Generate the display of the time answered column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_timereviewed($attempt) { - if ($attempt->attempt) { - return userdate($attempt->timereviewed, $this->strtimeformat); - } else { - return '-'; - } + public function col_timereviewed(stdClass $attempt) { + return property_exists($attempt, 'attempt') ? userdate($attempt->timereviewed, $this->strtimeformat) : '-'; } /** * Generate the display of the question id column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_questionid($attempt) { - if ($attempt->questionid) { - return $attempt->questionid; - } else { - return '-'; - } + public function col_questionid(stdClass $attempt): string { + return $attempt->questionid ?: '-'; } /** * Generate the display of the moodle question rating column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_moodlequestionid($attempt) { - if ($attempt->moodlequestionid) { - return $attempt->moodlequestionid; - } else { - return '-'; - } + public function col_moodlequestionid(stdClass $attempt): string { + return $attempt->moodlequestionid ?: '-'; } /** * Generate the display of the user id column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_userid($attempt) { - if ($attempt->userid) { - return $attempt->userid; - } else { - return '-'; - } + public function col_userid(stdClass $attempt): string { + return $attempt->userid ?: '-'; } /** @@ -215,9 +192,7 @@ public function col_userid($attempt) { * @param object $attempt data for the row of the table being output. * @param int $slot the number used to identify this question within this usage. */ - public function make_review_link($data, $attempt, $slot) { - global $OUTPUT; - + public function make_review_link($data, $attempt, $slot): string { $feedbackimg = ''; $state = $this->slot_state($attempt, $slot); if ($state->is_finished() && $state != question_state::$needsgrading) { @@ -225,9 +200,9 @@ public function make_review_link($data, $attempt, $slot) { } $output = html_writer::tag('span', $feedbackimg . html_writer::tag('span', - $data, array('class' => $state->get_state_class(true))), array('class' => 'que')); + $data, ['class' => $state->get_state_class(true)]), ['class' => 'que']); - $reviewparams = array('attempt' => $attempt->attempt, 'slot' => $slot); + $reviewparams = ['attempt' => $attempt->attempt, 'slot' => $slot]; if (isset($attempt->try)) { $reviewparams['step'] = $this->step_no_for_try($attempt->usageid, $slot, $attempt->try); } @@ -236,8 +211,7 @@ public function make_review_link($data, $attempt, $slot) { // phpcs:disable /*$url = new moodle_url('/mod/capquiz/reviewquestion.php', $reviewparams); $output = $OUTPUT->action_link($url, $output, - new popup_action('click', $url, 'reviewquestion', - array('height' => 450, 'width' => 650)), + new popup_action('click', $url, 'reviewquestion', array('height' => 450, 'width' => 650)), array('title' => get_string('reviewresponse', 'quiz')));*/ // phpcs:enable return $output; @@ -252,30 +226,21 @@ public function make_review_link($data, $attempt, $slot) { */ public function make_preview_link($data, $attempt, $slot) { global $OUTPUT; - $questionid = $this->slot_questionid($attempt, $slot); - - $output = html_writer::tag('span', html_writer::tag('span', $data), - array('class' => 'que')); - + $output = html_writer::tag('span', html_writer::tag('span', $data), ['class' => 'que']); $url = \qbank_previewquestion\helper::question_preview_url($questionid)->out(false); - - $output = $OUTPUT->action_link($url, $output, - new \popup_action('click', $url, 'previewquestion', - array('height' => 450, 'width' => 650)), - array('title' => get_string('previewquestion', 'quiz'))); - - return $output; + return $OUTPUT->action_link($url, $output, new \popup_action('click', $url, 'previewquestion', [ + 'height' => 450, 'width' => 650]), ['title' => get_string('previewquestion', 'quiz')]); } /** * Find the state for $slot given after this try. * - * @param object $attempt the row data + * @param stdClass $attempt * @param int $slot * @return question_state */ - protected function slot_state($attempt, $slot) { + protected function slot_state(stdClass $attempt, int $slot): question_state { $stepdata = $this->lateststeps[$attempt->usageid][$slot]; return question_state::get($stepdata->state); } @@ -283,36 +248,33 @@ protected function slot_state($attempt, $slot) { /** * Returns the id of the question * - * @param object $attempt the row data + * @param stdClass $attempt * @param int $slot - * @return question_id */ - protected function slot_questionid($attempt, $slot) { + protected function slot_questionid(stdClass $attempt, int $slot): int { $stepdata = $this->lateststeps[$attempt->usageid][$slot]; return $stepdata->questionid; } /** * Return an appropriate icon (green tick, red cross, etc.) for a grade. + * * @param float $fraction grade on a scale 0..1. - * @return string html fragment. */ - protected function icon_for_fraction($fraction) { + protected function icon_for_fraction(float $fraction): string { global $OUTPUT; - $feedbackclass = question_state::graded_state_for_fraction($fraction)->get_feedback_class(); - return $OUTPUT->pix_icon('i/grade_' . $feedbackclass, get_string($feedbackclass, 'question'), - 'moodle', array('class' => 'icon')); + $feedbackalt = get_string($feedbackclass, 'question'); + return $OUTPUT->pix_icon('i/grade_' . $feedbackclass, $feedbackalt, 'moodle', ['class' => 'icon']); } /** * The grade for this slot after this try. * - * @param object $attempt the row data + * @param stdClass $attempt * @param int $slot - * @return float */ - protected function slot_fraction($attempt, $slot) { + protected function slot_fraction(stdClass $attempt, int $slot): float { $stepdata = $this->lateststeps[$attempt->usageid][$slot]; return $stepdata->fraction; } @@ -322,7 +284,7 @@ protected function slot_fraction($attempt, $slot) { * * @param sql_join $allowedjoins (joins, wheres, params) defines allowed users for the report. */ - public function setup_sql_queries($allowedjoins) { + public function setup_sql_queries(sql_join $allowedjoins): void { list($fields, $from, $where, $params) = $this->base_sql($allowedjoins); // The WHERE clause is vital here, because some parts of tablelib.php will expect to @@ -344,11 +306,11 @@ public function base_sql(sql_join $allowedstudentsjoins) { $fields = 'DISTINCT ' . $DB->sql_concat('u.id', "'#'", 'COALESCE(ca.id, 0)') . ' AS uniqueid,'; - $extrafields = - \core_user\fields::for_identity($this->context)->including( - 'id', 'idnumber', 'firstname', 'lastname', 'picture', - 'imagealt', 'institution', 'department', 'email' - )->get_sql('u')->selects; + $extrafields = \core_user\fields::for_identity($this->context) + ->including( + 'id', 'idnumber', 'firstname', 'lastname', 'picture', 'imagealt', 'institution', 'department', 'email' + ) + ->get_sql('u')->selects; // phpcs:disable // $allnames = get_all_user_name_fields(true, 'u'); // phpcs:enable @@ -380,7 +342,7 @@ public function base_sql(sql_join $allowedstudentsjoins) { $from .= "\nJOIN {capquiz_attempt} ca ON ca.user_id = cu.id AND ca.slot = qa.slot"; $from .= "\nJOIN {capquiz_question} cq ON cq.question_list_id = cql.id AND cq.id = ca.question_id"; - $params = array('capquizid' => $this->capquiz->id()); + $params = ['capquizid' => $this->capquiz->id()]; switch ($this->options->attempts) { case capquiz_attempts_report::ALL_WITH: @@ -415,7 +377,7 @@ public function base_sql(sql_join $allowedstudentsjoins) { $where .= " AND ca.answered = 1"; } - return array($fields, $from, $where, $params); + return [$fields, $from, $where, $params]; } /** @@ -438,9 +400,8 @@ protected function update_sql_after_count($fields, $from, $where, $params) { * @param bool $useinitialsbar do you want to use the initials bar. Bar * will only be used if there is a fullname column defined for the table. */ - public function query_db($pagesize, $useinitialsbar = true) { + public function query_db($pagesize, $useinitialsbar = true): void { parent::query_db($pagesize, $useinitialsbar); - if ($this->requires_extra_data()) { $this->load_extra_data(); } @@ -457,8 +418,8 @@ protected function requires_extra_data() { } /** - * Does this report require the detailed information for each question from the - * question_attempts_steps table? + * Does this report require the detailed information for each question from the question_attempts_steps table? + * * @return bool should {@see load_extra_data} call {@see load_question_latest_steps}? */ protected function requires_latest_steps_loaded() { @@ -470,49 +431,40 @@ protected function requires_latest_steps_loaded() { * limits the query to just the question usages shown in this report page or alternatively for all attempts if downloading a * full report. */ - protected function load_extra_data() { + protected function load_extra_data(): void { $this->lateststeps = $this->load_question_latest_steps(); } /** * Load information about the latest state of selected questions in selected attempts. - * * The results are returned as an two dimensional array $qubaid => $slot => $dataobject * - * @param qubaid_condition|null $qubaids used to restrict which usages are included - * in the query. See {@see qubaid_condition}. + * @param ?qubaid_condition $qubaids used to restrict which usages are included in the query. See {@see qubaid_condition}. * @return array of records. See the SQL in this function to see the fields available. */ - protected function load_question_latest_steps(qubaid_condition $qubaids = null) { + protected function load_question_latest_steps(?qubaid_condition $qubaids = null): array { if ($qubaids === null) { $qubaids = $this->get_qubaids_condition(); } - $dm = new question_engine_data_mapper(); - $latesstepdata = $dm->load_questions_usages_latest_steps( - $qubaids, array_map(function($o) { - return $o->slot; - }, $this->questions)); - - $lateststeps = array(); + $latesstepdata = $dm->load_questions_usages_latest_steps($qubaids, array_map(fn($o) => $o->slot, $this->questions)); + $lateststeps = []; foreach ($latesstepdata as $step) { $lateststeps[$step->questionusageid][$step->slot] = $step; } - return $lateststeps; } /** - * Get an appropriate qubaid_condition for loading more data about the - * attempts we are displaying. - * @return qubaid_condition + * Get an appropriate qubaid_condition for loading more data about the attempts we are displaying. + * + * @return qubaid_list */ - protected function get_qubaids_condition() { - if (is_null($this->rawdata)) { - throw new coding_exception( - 'Cannot call get_qubaids_condition until the main data has been loaded.'); + protected function get_qubaids_condition(): qubaid_list { + if ($this->rawdata === null) { + throw new coding_exception('Cannot call get_qubaids_condition until the main data has been loaded.'); } - $qubaids = array(); + $qubaids = []; foreach ($this->rawdata as $attempt) { if ($attempt->usageid > 0) { $qubaids[] = $attempt->usageid; @@ -523,9 +475,10 @@ protected function get_qubaids_condition() { /** * Get the columns to sort by, in the form required by {@see construct_order_by()}. + * * @return array column name => SORT_... constant. */ - public function get_sort_columns() { + public function get_sort_columns(): array { // Add attemptid as a final tie-break to the sort. This ensures that // Attempts by the same student appear in order when just sorting by name. $sortcolumns = parent::get_sort_columns(); @@ -540,13 +493,10 @@ public function wrap_html_start() { if ($this->is_downloading() || !$this->includecheckboxes) { return; } - $url = $this->options->get_url(); $url->param('sesskey', sesskey()); - echo '
'; echo '
'; - echo html_writer::input_hidden_params($url); echo '
'; } @@ -563,10 +513,8 @@ public function wrap_html_finish() { } echo '
'; - echo '' . - get_string('selectall', 'quiz') . ' / '; - echo '' . - get_string('selectnone', 'quiz') . ' '; + echo '' . get_string('selectall', 'quiz') . ' / '; + echo '' . get_string('selectnone', 'quiz') . ' '; $PAGE->requires->js_amd_inline(" require(['jquery'], function($) { $('#checkattempts').click(function(e) { @@ -610,7 +558,7 @@ protected function submit_buttons() { echo ''; $PAGE->requires->event_handler('#deleteattemptsbutton', 'click', 'M.util.show_confirm_dialog', - array('message' => get_string('deleteattemptcheck', 'quiz'))); + ['message' => get_string('deleteattemptcheck', 'quiz')]); } } diff --git a/report/questions/questions_form.php b/report/questions/questions_form.php index ba7586e..e11134d 100644 --- a/report/questions/questions_form.php +++ b/report/questions/questions_form.php @@ -45,20 +45,16 @@ class capquizreport_questions_settings_form extends capquiz_attempts_report_form /** * Defines the form */ - protected function definition() { + protected function definition(): void { $mform = $this->_form; $this->standard_attempt_fields($mform); $this->other_attempt_fields($mform); - - $mform->addElement('header', 'preferencesuser', - get_string('reportdisplayoptions', 'quiz')); + $mform->addElement('header', 'preferencesuser', get_string('reportdisplayoptions', 'quiz')); $this->standard_preference_fields($mform); $this->other_preference_fields($mform); - - $mform->addElement('submit', 'submitbutton', - get_string('showreport', 'quiz')); + $mform->addElement('submit', 'submitbutton', get_string('showreport', 'quiz')); } /** @@ -66,7 +62,7 @@ protected function definition() { * * @param MoodleQuickForm $mform the form to add attempt fields to */ - protected function standard_attempt_fields(MoodleQuickForm $mform) { + protected function standard_attempt_fields(MoodleQuickForm $mform): void { $mform->addElement('hidden', 'attempts', capquiz_attempts_report::ALL_WITH); $mform->setType('attempts', PARAM_ALPHAEXT); @@ -79,10 +75,9 @@ protected function standard_attempt_fields(MoodleQuickForm $mform) { * * @param MoodleQuickForm $mform the form to add preference fields to */ - protected function other_preference_fields(MoodleQuickForm $mform) { - $mform->addGroup(array( - $mform->createElement('advcheckbox', 'qtext', '', - get_string('questiontext', 'quiz_responses')), - ), 'coloptions', get_string('showthe', 'quiz_responses'), array(' '), false); + protected function other_preference_fields(MoodleQuickForm $mform): void { + $mform->addGroup([ + $mform->createElement('advcheckbox', 'qtext', '', get_string('questiontext', 'quiz_responses')), + ], 'coloptions', get_string('showthe', 'quiz_responses'), [' '], false); } } diff --git a/report/questions/questions_options.php b/report/questions/questions_options.php index b770920..bd1754e 100644 --- a/report/questions/questions_options.php +++ b/report/questions/questions_options.php @@ -27,12 +27,12 @@ use mod_capquiz\report\capquiz_attempts_report; use mod_capquiz\report\capquiz_attempts_report_options; +use stdClass; defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/mod/capquiz/report/attemptsreport_options.php'); - /** * Class to store the options for a {@see capquiz_questions_report}. * @@ -43,41 +43,37 @@ class capquizreport_questions_options extends capquiz_attempts_report_options { /** @var bool whether to show the question text columns. */ - public $showqtext = false; + public bool $showqtext = false; /** * @var string quiz_attempts_report::ALL_WITH or quiz_attempts_report::ENROLLED_WITH * quiz_attempts_report::ENROLLED_WITHOUT or quiz_attempts_report::ENROLLED_ALL */ - public $attempts = capquiz_attempts_report::ALL_WITH; + public string $attempts = capquiz_attempts_report::ALL_WITH; /** * Get the current value of the settings to pass to the settings form. */ - public function get_initial_form_data() { + public function get_initial_form_data(): stdClass { $toform = parent::get_initial_form_data(); - $toform->qtext = $this->showqtext; - return $toform; } /** * Set the fields of this object from the form data. - * @param object $fromform The data from $mform->get_data() from the settings form. + * @param stdClass $fromform The data from $mform->get_data() from the settings form. */ - public function setup_from_form_data($fromform) { + public function setup_from_form_data(stdClass $fromform): void { parent::setup_from_form_data($fromform); - $this->showqtext = $fromform->qtext; } /** * Set the fields of this object from the URL parameters. */ - public function setup_from_params() { + public function setup_from_params(): void { parent::setup_from_params(); - $this->showqtext = optional_param('qtext', $this->showqtext, PARAM_BOOL); } @@ -85,9 +81,8 @@ public function setup_from_params() { * Set the fields of this object from the user's preferences. * (For those settings that are backed by user-preferences). */ - public function setup_from_user_preferences() { + public function setup_from_user_preferences(): void { parent::setup_from_user_preferences(); - $this->showqtext = get_user_preferences('capquizreport_questions_qtext', $this->showqtext); } @@ -95,17 +90,17 @@ public function setup_from_user_preferences() { * Update the user preferences so they match the settings in this object. * (For those settings that are backed by user-preferences). */ - public function update_user_preferences() { + public function update_user_preferences(): void { parent::update_user_preferences(); - set_user_preference('capquizreport_questions_qtext', $this->showqtext); } /** * Get the URL parameters required to show the report with these options. + * * @return array URL parameter name => value. */ - protected function get_url_params() { + protected function get_url_params(): array { $params = parent::get_url_params(); $params['qtext'] = $this->showqtext; return $params; diff --git a/report/questions/questions_table.php b/report/questions/questions_table.php index a11cf31..ec5e339 100644 --- a/report/questions/questions_table.php +++ b/report/questions/questions_table.php @@ -25,12 +25,14 @@ namespace capquizreport_questions; +use core\context; use core\dml\sql_join; use mod_capquiz\report\capquiz_attempts_report; use mod_capquiz\report\capquiz_attempts_report_options; use mod_capquiz\report\capquiz_attempts_report_table; use moodle_url; use quiz_responses_options; +use stdClass; defined('MOODLE_INTERNAL') || die(); @@ -48,7 +50,8 @@ class capquizreport_questions_table extends capquiz_attempts_report_table { /** - * Constructor + * Constructor. + * * @param object $capquiz * @param context $context * @param capquiz_attempts_report_options $options @@ -71,14 +74,11 @@ public function __construct($capquiz, $context, capquiz_attempts_report_options * This overwrites the parent method because full SQL query may fail on Mysql * because of the limit in the number of tables in the join. Therefore we only * join 59 tables in the main query and add the rest here. - * - * @return void */ - public function build_table() { + public function build_table(): void { if (!$this->rawdata) { return; } - $this->strtimeformat = str_replace(',', ' ', get_string('strftimedatetimeseconds', 'capquiz')); parent::build_table(); } @@ -86,70 +86,54 @@ public function build_table() { /** * Format the submission and feedback columns. * - * @param string $colname The column name - * @param stdClass $attempt The attempt - * @return mixed string or NULL + * @param string $colname + * @param stdClass $attempt */ - public function other_cols($colname, $attempt) { - switch ($colname) { - case 'question': - return $this->data_col($attempt->slot, 'questionsummary', $attempt); - default: - return null; - } + public function other_cols(string $colname, stdClass $attempt): ?string { + return match ($colname) { + 'question' => $this->data_col($attempt->slot, 'questionsummary', $attempt), + default => null, + }; } /** * Format a single column, used in other_cols * - * @param integer $slot attempts slot + * @param int $slot attempts slot * @param string $field - * @param object $attempt - * @return string + * @param stdClass $attempt */ - public function data_col($slot, $field, $attempt) { + public function data_col(int $slot, string $field, stdClass $attempt): string { if ($attempt->usageid == 0) { return '-'; } $value = $this->field_from_extra_data($attempt, $slot, $field); - - if (is_null($value)) { - $summary = '-'; - } else { - $summary = trim($value); - } - + $summary = $value !== null ? trim($value) : '-'; if ($this->is_downloading() && $this->is_downloading() != 'html') { return $summary; } $summary = s($summary); - if ($this->is_downloading()) { return $summary; } - if ($field === 'questionsummary') { return $this->make_preview_link($summary, $attempt, $slot); - - } else { - return $summary; } + return $summary; } /** * Column text from the extra data loaded in load_extra_data(), before html formatting etc. * - * @param object $attempt + * @param stdClass $attempt * @param int $slot * @param string $field - * @return string */ - protected function field_from_extra_data($attempt, $slot, $field) { + protected function field_from_extra_data(stdClass $attempt, int $slot, string $field): string { if (!isset($this->lateststeps[$attempt->usageid][$slot])) { return '-'; } $stepdata = $this->lateststeps[$attempt->usageid][$slot]; - if (property_exists($stepdata, $field . 'full')) { $value = $stepdata->{$field . 'full'}; } else { @@ -160,17 +144,13 @@ protected function field_from_extra_data($attempt, $slot, $field) { /** * Generate the display of the answer state column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_answerstate($attempt) { - if (is_null($attempt->attempt)) { - return '-'; - } - if ($attempt->usageid == 0) { + public function col_answerstate(stdClass $attempt): string { + if ($attempt->attempt === null || $attempt->usageid === 0) { return '-'; } - $state = $this->slot_state($attempt, $attempt->slot); if ($this->is_downloading()) { return $state->__toString(); @@ -182,54 +162,41 @@ public function col_answerstate($attempt) { /** * Generate the display of the question rating column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_questionrating($attempt) { - if ($attempt->questionrating) { - return $attempt->questionrating; - } else { - return '-'; - } + public function col_questionrating(stdClass $attempt): string { + return $attempt->questionrating ?: '-'; } /** * Generate the display of the time created (actually time answered) rating column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_timecreated($attempt) { - if ($attempt->attempt) { - return userdate($attempt->timeanswered, $this->strtimeformat); - } else { - return '-'; - } + public function col_timecreated(stdClass $attempt): string { + return $attempt->attempt ? userdate($attempt->timeanswered, $this->strtimeformat) : '-'; } /** * Generate the display of the time created (actually time answered) rating column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_attemptid($attempt) { - if ($attempt->attempt) { - return $attempt->attempt; - } else { - return '-'; - } + public function col_attemptid(stdClass $attempt) { + return $attempt->attempt ?: '-'; } /** * Generate the display of the previous question rating column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_questionprevrating($attempt) { + public function col_questionprevrating(stdClass $attempt): string { global $OUTPUT; if ($attempt->questionprevrating) { - $warningicon = $OUTPUT->pix_icon('i/warning', get_string('rating_manually_updated', 'capquizreport_questions'), - 'moodle', array('class' => 'icon')); - + $warningalt = get_string('rating_manually_updated', 'capquizreport_questions'); + $warningicon = $OUTPUT->pix_icon('i/warning', $warningalt, 'moodle', ['class' => 'icon']); if (!$this->is_downloading() && $attempt->manualprevqrating) { return $warningicon . $attempt->questionprevrating; } else { @@ -242,15 +209,14 @@ public function col_questionprevrating($attempt) { /** * Generate the display of the previous question rating column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_prevquestionrating($attempt) { + public function col_prevquestionrating(stdClass $attempt): string { global $OUTPUT; if ($attempt->questionprevrating) { - $warningicon = $OUTPUT->pix_icon('i/warning', get_string('rating_manually_updated', 'capquizreport_questions'), - 'moodle', array('class' => 'icon')); - + $warningalt = get_string('rating_manually_updated', 'capquizreport_questions'); + $warningicon = $OUTPUT->pix_icon('i/warning', $warningalt, 'moodle', ['class' => 'icon']); if (!$this->is_downloading() && $attempt->manualprevqrating) { return $warningicon . $attempt->questionprevrating; } else { @@ -263,15 +229,14 @@ public function col_prevquestionrating($attempt) { /** * Generate the display of the previous question rating column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_prevquestionprevrating($attempt) { + public function col_prevquestionprevrating(stdClass $attempt): string { global $OUTPUT; if ($attempt->questionprevrating) { - $warningicon = $OUTPUT->pix_icon('i/warning', get_string('rating_manually_updated', 'capquizreport_questions'), - 'moodle', array('class' => 'icon')); - + $warningalt = get_string('rating_manually_updated', 'capquizreport_questions'); + $warningicon = $OUTPUT->pix_icon('i/warning', $warningalt, 'moodle', ['class' => 'icon']); if (!$this->is_downloading() && $attempt->manualprevqrating) { return $warningicon . $attempt->questionprevrating; } else { @@ -284,25 +249,23 @@ public function col_prevquestionprevrating($attempt) { /** * Generate the display of the previous question manual rating column. - * @param object $attempt the table row being output. - * @return string HTML content to go inside the td. + * + * @param stdClass $attempt the table row being output. */ - public function col_questionprevratingmanual($attempt) { - if (is_null($attempt->manualprevqrating)) { + public function col_questionprevratingmanual(stdClass $attempt): string { + if ($attempt->manualprevqrating === null) { return '-'; } - $ismanual = ($attempt->manualprevqrating) ? 'true' : 'false'; - $manualprevqrating = get_string($ismanual, 'capquiz'); - return $manualprevqrating; + return get_string($attempt->manualprevqrating ? 'true' : 'false', 'capquiz'); } /** * Contruct all the parts of the main database query. - * @param \core\dml\sql_join $allowedstudentsjoins (joins, wheres, params) defines allowed users for the report. - * @return array with 4 elements ($fields, $from, $where, $params) that can be used to - * build the actual database query. + * + * @param sql_join $allowedstudentsjoins (joins, wheres, params) defines allowed users for the report. + * @return array 4 elements ($fields, $from, $where, $params) that can be used to build the actual database query. */ - public function base_sql(sql_join $allowedstudentsjoins) { + public function base_sql(sql_join $allowedstudentsjoins): array { global $DB; list($fields, $from, $where, $params) = parent::base_sql($allowedstudentsjoins); $fields1 = ', @@ -349,16 +312,9 @@ public function base_sql(sql_join $allowedstudentsjoins) { } /** - * Does this report require the detailed information for each question from the - * question_attempts_steps table? - * - * @return bool + * Does this report require the detailed information for each question from the question_attempts_steps table? */ - protected function requires_latest_steps_loaded() { - if ($this->options->showqtext) { - return true; - } else { - return false; - } + protected function requires_latest_steps_loaded(): bool { + return (bool)$this->options->showqtext; } } diff --git a/report/questions/report.php b/report/questions/report.php index 314edaf..051580d 100644 --- a/report/questions/report.php +++ b/report/questions/report.php @@ -26,7 +26,10 @@ namespace capquizreport_questions; use context_course; +use mod_capquiz\capquiz; use mod_capquiz\report\capquiz_attempts_report; +use mod_quiz\local\reports\attempts_report_options; +use stdClass; defined('MOODLE_INTERNAL') || die(); @@ -45,14 +48,15 @@ class capquizreport_questions_report extends capquiz_attempts_report { /** - * Displays the full report - * @param capquiz $capquiz capquiz object - * @param stdClass $cm - course_module object - * @param stdClass $course - course object - * @param string $download - type of download being requested + * Displays the full report. + * + * @param capquiz $capquiz + * @param stdClass $cm + * @param stdClass $course + * @param string $download type of download being requested */ - public function display($capquiz, $cm, $course, $download) { - global $OUTPUT, $DB; + public function display($capquiz, $cm, $course, $download): bool { + global $DB; list($studentsjoins) = $this->init( 'questions', 'capquizreport_questions\capquizreport_questions_settings_form', $capquiz, $cm, $course); @@ -72,15 +76,15 @@ public function display($capquiz, $cm, $course, $download) { $questions = capquiz_report_get_questions($capquiz); // Prepare for downloading, if applicable. - $courseshortname = format_string($course->shortname, true, - array('context' => context_course::instance($course->id))); + $courseshortname = format_string($course->shortname, true, ['context' => context_course::instance($course->id)]); $table = new capquizreport_questions_table($capquiz, $this->context, $this->options, $studentsjoins, $questions, $this->options->get_url()); + $filename = capquiz_report_download_filename(get_string('questionsfilename', 'capquizreport_questions'), $courseshortname, $capquiz->name()); - $table->is_downloading($this->options->download, $filename, - $courseshortname . ' ' . format_string($capquiz->name(), true)); + + $table->is_downloading($this->options->download, $filename, $courseshortname . ' ' . format_string($capquiz->name())); if ($table->is_downloading()) { raise_memory_limit(MEMORY_EXTRA); } @@ -98,8 +102,7 @@ public function display($capquiz, $cm, $course, $download) { // Start output. if (!$table->is_downloading()) { // Only print headers if not asked to download data. - $this->print_standard_header_and_messages($cm, $course, $capquiz, - $this->options, $hasquestions, $hasstudents); + $this->print_standard_header_and_messages($cm, $course, $capquiz, $this->options, $hasquestions, $hasstudents); // Print the display options. $this->form->display(); @@ -110,8 +113,8 @@ public function display($capquiz, $cm, $course, $download) { $table->setup_sql_queries($studentsjoins); // Define table columns. - $columns = array(); - $headers = array(); + $columns = []; + $headers = []; if ($table->is_downloading()) { $columns[] = 'attemptid'; @@ -164,19 +167,17 @@ public function display($capquiz, $cm, $course, $download) { * outputs the standard group selector, number of attempts summary, * and messages to cover common cases when the report can't be shown. * - * @param \stdClass $cm the course_module information. - * @param \stdClass $course the course settings. - * @param \stdClass $capquiz the capquiz settings. - * @param mod_quiz_attempts_report_options $options the current report settings. + * @param stdClass $cm the course_module information. + * @param stdClass $course the course settings. + * @param capquiz $capquiz the capquiz settings. + * @param attempts_report_options $options the current report settings. * @param bool $hasquestions whether there are any questions in the capquiz. * @param bool $hasstudents whether there are any relevant students. */ - protected function print_standard_header_and_messages($cm, $course, $capquiz, - $options, $hasquestions, $hasstudents) { + protected function print_standard_header_and_messages($cm, $course, capquiz $capquiz, attempts_report_options $options, + bool $hasquestions, bool $hasstudents): void { global $OUTPUT; - - echo $this->print_header_and_tabs($cm, $course, $capquiz, $this->mode); - + $this->print_header_and_tabs($cm, $course, $capquiz, $this->mode); if (!$hasquestions) { echo capquiz_no_questions_message($capquiz, $cm, $this->context); } else if (!$capquiz->is_published()) { @@ -184,7 +185,6 @@ protected function print_standard_header_and_messages($cm, $course, $capquiz, } else if (!$hasstudents) { echo $OUTPUT->notification(get_string('nostudentsyet')); } - } /** @@ -193,7 +193,7 @@ protected function print_standard_header_and_messages($cm, $course, $capquiz, * @param array $columns columns to be added * @param array $headers column headers */ - protected function add_question_rating_columns(array &$columns, array &$headers) { + protected function add_question_rating_columns(array &$columns, array &$headers): void { $this->add_question_rating_column($columns, $headers); $this->add_question_previous_rating_column($columns, $headers); } @@ -204,7 +204,7 @@ protected function add_question_rating_columns(array &$columns, array &$headers) * @param array $columns columns to be added * @param array $headers column headers */ - protected function add_question_rating_column(array &$columns, array &$headers) { + protected function add_question_rating_column(array &$columns, array &$headers): void { $columns[] = 'questionrating'; $headers[] = get_string('questionrating', 'capquiz'); } @@ -215,7 +215,7 @@ protected function add_question_rating_column(array &$columns, array &$headers) * @param array $columns columns to be added * @param array $headers column headers */ - protected function add_question_previous_rating_column(array &$columns, array &$headers) { + protected function add_question_previous_rating_column(array &$columns, array &$headers): void { $columns[] = 'questionprevrating'; $headers[] = get_string('questionprevrating', 'capquizreport_questions'); } diff --git a/report/report.php b/report/report.php index 6b96330..61ac4fd 100644 --- a/report/report.php +++ b/report/report.php @@ -44,13 +44,14 @@ */ class report { /** - * displays the full report - * @param capquiz $capquiz capquiz object - * @param stdClass $cm - course_module object - * @param stdClass $course - course object - * @param string $download - type of download being requested + * Displays the full report. + * + * @param capquiz $capquiz + * @param stdClass $cm + * @param stdClass $course + * @param string $download type of download being requested */ - public function display($capquiz, $cm, $course, $download) { + public function display(capquiz $capquiz, stdClass $cm, stdClass $course, string $download): bool { // This function renders the html for the report. return true; } @@ -58,29 +59,27 @@ public function display($capquiz, $cm, $course, $download) { /** * Allows the plugin to control who can see this plugin. * - * @param context_module $contextmodule Course mocule context class - * @return boolean + * @param context_module $contextmodule */ - public function canview($contextmodule) { + public function canview(context_module $contextmodule): bool { return true; } /** * Initialise some parts of $PAGE and start output. * - * @param object $cm the course_module information. - * @param object $course the course settings. - * @param object $capquiz the capquiz settings. + * @param stdClass $cm the course_module information. + * @param stdClass $course the course settings. + * @param capquiz $capquiz the capquiz settings. * @param string $reportmode the report name. */ - public function print_header_and_tabs($cm, $course, $capquiz, $reportmode = 'attempts') { + public function print_header_and_tabs(stdClass $cm, stdClass $course, capquiz $capquiz, string $reportmode = 'attempts'): void { global $PAGE, $OUTPUT; - // Print the page header. $PAGE->set_title($capquiz->name()); $PAGE->set_heading($course->fullname); $context = context_module::instance($cm->id); echo $OUTPUT->heading(format_string( get_string('pluginname', 'capquizreport_' . $reportmode) . ' ' . get_string('report', 'capquiz'), - true, array('context' => $context))); + true, ['context' => $context])); } } diff --git a/report/reportfactory.php b/report/reportfactory.php index 1e860ff..8a49ab5 100644 --- a/report/reportfactory.php +++ b/report/reportfactory.php @@ -42,24 +42,21 @@ class capquiz_report_factory { /** - * Create an capquiz report of a given type and return it. + * Create a capquiz report of a given type and return it. * * @param string $type the required type. - * @return capquiz_attempts_report the requested capquiz report. - * @throws capquiz_exception */ - public static function make($type) { + public static function make(string $type): capquiz_attempts_report { $class = self::class_for_type($type); - return new $class(); } /** - * The class name corresponding to an report type. + * The class name corresponding to a report type. + * * @param string $type report type name. - * @return string corresponding class name. */ - protected static function class_for_type($type) { + protected static function class_for_type(string $type): string { global $CFG; $typelc = strtolower($type); $file = $CFG->dirroot . '/mod/capquiz/report/' . $type . '/report.php'; diff --git a/report/reportlib.php b/report/reportlib.php index 1431cfc..f7480e6 100644 --- a/report/reportlib.php +++ b/report/reportlib.php @@ -23,6 +23,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +use core\context\module; use mod_capquiz\capquiz; use mod_capquiz\capquiz_urls; use mod_capquiz\report\capquiz_report_factory; @@ -39,45 +40,42 @@ * @param context_module $context the context level to check caps against * @return array list of valid reports present */ -function capquiz_report_list($context) { +function capquiz_report_list(context_module $context): array { static $reportlist; if (!empty($reportlist)) { return $reportlist; } $pluginmanager = new capquiz_plugin_manager('capquizreport'); - $installedplugins = $pluginmanager->get_sorted_plugins_list(); $enabledplugins = core_plugin_manager::instance()->get_enabled_plugins('capquizreport'); - foreach ($installedplugins as $idx => $reportname) { + foreach ($pluginmanager->get_sorted_plugins_list() as $reportname) { $report = capquiz_report_factory::make($reportname); - if (isset($enabledplugins[$reportname]) && $report->canview($context)) { $reportlist[] = $reportname; } - continue; } return $reportlist; } - - /** * Create a filename for use when downloading data from a capquiz report. It is * expected that this will be passed to flexible_table::is_downloading, which * cleans the filename of bad characters and adds the file extension. + * * @param string $report the type of report. * @param string $courseshortname the course shortname. * @param string $capquizname the capquiz name. * @return string the filename. */ -function capquiz_report_download_filename($report, $courseshortname, $capquizname) { - return $courseshortname . '-' . format_string($capquizname, true) . '-' . $report; +function capquiz_report_download_filename(string $report, string $courseshortname, string $capquizname): string { + return $courseshortname . '-' . format_string($capquizname) . '-' . $report; } /** * Are there any questions in this capquiz? - * @param int $capquizid the capquizid id. + * + * @param int $capquizid */ -function capquiz_has_questions($capquizid) { +function capquiz_has_questions(int $capquizid): bool { global $DB; $sql = 'SELECT cq.id FROM {capquiz_question} cq @@ -89,12 +87,11 @@ function capquiz_has_questions($capquizid) { /** * Get the questions in this capquiz, in order. * - * @param capquiz $capquiz the capquiz. + * @param capquiz $capquiz * @return array of slot => $question object with fields * ->slot, ->id, ->qtype, ->length. - * @throws dml_exception */ -function capquiz_report_get_questions(capquiz $capquiz) { +function capquiz_report_get_questions(capquiz $capquiz): array { global $DB; $sql = 'SELECT DISTINCT ' . $DB->sql_concat('qa.id', "'#'", 'cu.id', 'ca.slot') . ' AS uniqueid, ca.slot, @@ -113,14 +110,13 @@ function capquiz_report_get_questions(capquiz $capquiz) { AND q.length > 0 ORDER BY ca.slot'; - $qsbyslot = $DB->get_records_sql($sql, array($capquiz->id())); + $qsbyslot = $DB->get_records_sql($sql, [$capquiz->id()]); $number = 1; foreach ($qsbyslot as $question) { $question->number = $number; $number += $question->length; $question->type = $question->qtype; } - return $qsbyslot; } @@ -133,7 +129,7 @@ function capquiz_report_get_questions(capquiz $capquiz) { * made '' is returned instead of 'Attempts: 0'. * @return string a string like "Attempts: 123". */ -function capquiz_num_attempt_summary(capquiz $capquiz, $returnzero = false) { +function capquiz_num_attempt_summary(capquiz $capquiz, bool $returnzero = false): string { $numattempts = capquiz_report_num_attempt($capquiz); if ($numattempts || $returnzero) { return get_string('attemptsnum', 'quiz', $numattempts); @@ -146,98 +142,84 @@ function capquiz_num_attempt_summary(capquiz $capquiz, $returnzero = false) { * * @param capquiz $capquiz * @return int number of answered CAPQuiz attempts - * @throws dml_exception */ function capquiz_report_num_attempt(capquiz $capquiz): int { global $DB; - $sql = 'SELECT COUNT( ca.id) + $sql = 'SELECT COUNT(ca.id) FROM {capquiz_attempt} ca JOIN {capquiz_user} cu ON cu.capquiz_id = :capquizid AND cu.id = ca.user_id JOIN {question_usages} qu ON qu.id = cu.question_usage_id JOIN {question_attempts} qa ON qa.questionusageid = qu.id AND qa.slot = ca.slot JOIN {capquiz_question} cq ON cq.id = ca.question_id'; - $attempts = $DB->count_records_sql($sql, ['capquizid' => $capquiz->id()]); - return $attempts; + return $DB->count_records_sql($sql, ['capquizid' => $capquiz->id()]); } - /** * Generate a message saying that this capquiz has no questions, with a button to * go to the edit page, if the user has the right capability. + * * @param object $quiz the quiz settings. * @param object $cm the course_module object. - * @param object $context the quiz context. + * @param module $context the quiz context. * @return string HTML to output. */ -function capquiz_no_questions_message($quiz, $cm, $context) { +function capquiz_no_questions_message($quiz, $cm, module $context): string { global $OUTPUT; - - $output = ''; - $output .= $OUTPUT->notification(get_string('noquestions', 'quiz')); + $output = $OUTPUT->notification(get_string('noquestions', 'quiz')); if (has_capability('mod/capquiz:manage', $context)) { $output .= $OUTPUT->single_button(capquiz_urls::view_question_list_url(), get_string('editquiz', 'quiz'), 'get'); } - return $output; } /** * Generate a message saying that this capquiz has no questions, with a button to * go to the dashboard page (question list settings), if the user has the right capability. + * * @param object $quiz the quiz settings. * @param object $cm the course_module object. - * @param object $context the quiz context. + * @param module $context the quiz context. * @return string HTML to output. */ -function capquiz_not_published_message($quiz, $cm, $context) { +function capquiz_not_published_message($quiz, $cm, module $context): string { global $OUTPUT; - - $output = ''; - $output .= $OUTPUT->notification(get_string('question_list_not_published', 'capquiz')); + $output = $OUTPUT->notification(get_string('question_list_not_published', 'capquiz')); if (has_capability('mod/capquiz:manage', $context)) { $output .= $OUTPUT->single_button(capquiz_urls::view_url(), get_string('question_list_settings', 'capquiz'), 'get'); } - return $output; } /** - * Make all named SQL parameters unique and - * generate a new parameter array with the unique parameters. + * Make all named SQL parameters unique and generate a new parameter array with the unique parameters. + * * @param string $sql The SQL with patameters to uniquify * @param array $params The patameters to uniquify - * @return array */ -function uniquify_sql_params($sql, $params): array { +function uniquify_sql_params(string $sql, array $params): array { $pattern = "/:([a-zA-Z0-9_]+)/"; $paramsres = []; $processed = []; - $sqlres = preg_replace_callback($pattern, - function ($matches) use (&$params, &$paramsres, &$processed) { - $index = 1; - $key = substr($matches[0], 1); - if (!array_key_exists($key, $params)) { - return $matches[0]; - } - - if (array_key_exists($key, $processed)) { - $processed[$key] += 1; - $index = $processed[$key]; - } else { - $processed[$key] = 1; - } - - $newkey = $key . $index; - $paramsres[$newkey] = $params[$key]; - - return $matches[0] . $index; - }, $sql); - + $sqlres = preg_replace_callback($pattern, function ($matches) use (&$params, &$paramsres, &$processed) { + $index = 1; + $key = substr($matches[0], 1); + if (!array_key_exists($key, $params)) { + return $matches[0]; + } + if (array_key_exists($key, $processed)) { + $processed[$key] += 1; + $index = $processed[$key]; + } else { + $processed[$key] = 1; + } + $newkey = $key . $index; + $paramsres[$newkey] = $params[$key]; + return $matches[0] . $index; + }, $sql); foreach ($params as $param => $value) { if (!array_key_exists($param, $paramsres) && !array_key_exists($param, $processed)) { $paramsres[$param] = $value; } } - return [$sqlres, $paramsres]; } diff --git a/settings.php b/settings.php index 7637e43..6a91d24 100644 --- a/settings.php +++ b/settings.php @@ -27,20 +27,23 @@ require_once($CFG->dirroot . '/mod/capquiz/adminlib.php'); $modcapquizfolder = new admin_category('modcapquizfolder', - new lang_string('pluginname', 'capquiz'), - $module->is_enabled() === false); + new lang_string('pluginname', 'capquiz'), $module->is_enabled() === false); + $ADMIN->add('modsettings', $modcapquizfolder); -$settings = new admin_settingpage($section, get_string('settings', 'capquiz'), 'moodle/site:config', !$module->is_enabled()); +$settings = new admin_settingpage($section, + get_string('settings', 'capquiz'), 'moodle/site:config', !$module->is_enabled()); + $ADMIN->add('modcapquizfolder', $settings); + // Tell core we already added the settings structure. $settings = null; // Folder 'capquiz report'. $ADMIN->add('modcapquizfolder', new admin_category('capquizreportplugins', new lang_string('reportplugin', 'capquiz'), !$module->is_enabled())); -$ADMIN->add('capquizreportplugins', new capquiz_admin_page_manage_capquiz_plugins('capquizreport')); +$ADMIN->add('capquizreportplugins', new capquiz_admin_page_manage_capquiz_plugins('capquizreport')); foreach (core_plugin_manager::instance()->get_plugins_of_type('capquizreport') as $plugin) { $plugin->load_settings($ADMIN, 'capquizreportplugins', $hassiteconfig); diff --git a/styles.css b/styles.css index 8794665..f78332d 100755 --- a/styles.css +++ b/styles.css @@ -219,3 +219,7 @@ .capquiz-regrade-all { margin-top: 16px; } + +#page-mod-capquiz-edit table.question-bank-table { + width: 100%; +} diff --git a/view.php b/view.php index ffaa70a..6755019 100755 --- a/view.php +++ b/view.php @@ -33,27 +33,22 @@ $cm = get_coursemodule_from_id('capquiz', $cmid, 0, false, MUST_EXIST); require_login($cm->course, false, $cm); -$cmid = capquiz_urls::require_course_module_id_param(); $capquiz = new capquiz($cmid); -if (!$capquiz) { - capquiz_urls::redirect_to_front_page(); -} +$renderer = $capquiz->renderer(); capquiz_urls::set_page_url($capquiz, capquiz_urls::$urlview); if (has_capability('mod/capquiz:instructor', $capquiz->context())) { if ($capquiz->has_question_list()) { - $capquiz->renderer()->display_instructor_dashboard($capquiz); + $renderer->display_instructor_dashboard($capquiz); } else { - $capquiz->renderer()->display_choose_question_list_view($capquiz); + $renderer->display_choose_question_list_view(); } } else { require_capability('mod/capquiz:student', $capquiz->context()); // Question engine is null if the quiz is not published. $qengine = $capquiz->question_engine($capquiz->user()); - if ($qengine) { - $qengine->delete_invalid_attempt($capquiz->user()); - } + $qengine?->delete_invalid_attempt($capquiz->user()); $capquiz->update_grades(); - $capquiz->renderer()->display_question_attempt_view($capquiz); + $renderer->display_question_attempt_view($capquiz); } diff --git a/view_classlist.php b/view_classlist.php index 61acee4..e28c451 100755 --- a/view_classlist.php +++ b/view_classlist.php @@ -35,12 +35,6 @@ $context = \context_module::instance($cmid); require_capability('mod/capquiz:instructor', $context); -$cmid = capquiz_urls::require_course_module_id_param(); $capquiz = new capquiz($cmid); -if (!$capquiz) { - capquiz_urls::redirect_to_front_page(); -} - capquiz_urls::set_page_url($capquiz, capquiz_urls::$urledit); -$renderer = $capquiz->renderer(); -$renderer->display_leaderboard($capquiz); +$capquiz->renderer()->display_leaderboard($capquiz); diff --git a/view_create_question_list.php b/view_create_question_list.php index a4b7269..e7d9cd8 100755 --- a/view_create_question_list.php +++ b/view_create_question_list.php @@ -37,13 +37,9 @@ $cmid = capquiz_urls::require_course_module_id_param(); $capquiz = new capquiz($cmid); -if (!$capquiz) { - capquiz_urls::redirect_to_front_page(); -} - capquiz_urls::set_page_url($capquiz, capquiz_urls::$urlviewcreateqlist); -$renderer = $capquiz->renderer(); +$renderer = $capquiz->renderer(); if ($capquiz->has_question_list()) { $renderer->display_instructor_dashboard($capquiz); } else { diff --git a/view_grading.php b/view_grading.php index ae53776..8863fc6 100644 --- a/view_grading.php +++ b/view_grading.php @@ -35,12 +35,6 @@ $context = \context_module::instance($cmid); require_capability('mod/capquiz:instructor', $context); -$cmid = capquiz_urls::require_course_module_id_param(); $capquiz = new capquiz($cmid); -if (!$capquiz) { - capquiz_urls::redirect_to_front_page(); -} - capquiz_urls::set_page_url($capquiz, capquiz_urls::$urlviewgrading); -$renderer = $capquiz->renderer(); -$renderer->display_grading_configuration($capquiz); +$capquiz->renderer()->display_grading_configuration($capquiz); diff --git a/view_import.php b/view_import.php index 4a40b02..922cf25 100644 --- a/view_import.php +++ b/view_import.php @@ -35,12 +35,6 @@ $context = \context_module::instance($cmid); require_capability('mod/capquiz:instructor', $context); -$cmid = capquiz_urls::require_course_module_id_param(); $capquiz = new capquiz($cmid); -if (!$capquiz) { - capquiz_urls::redirect_to_front_page(); -} - capquiz_urls::set_page_url($capquiz, capquiz_urls::$urledit); -$renderer = $capquiz->renderer(); -$renderer->display_import($capquiz); +$capquiz->renderer()->display_import($capquiz); diff --git a/view_rating_system.php b/view_rating_system.php index 9db7b77..7d005ad 100644 --- a/view_rating_system.php +++ b/view_rating_system.php @@ -35,12 +35,6 @@ $context = \context_module::instance($cmid); require_capability('mod/capquiz:instructor', $context); -$cmid = capquiz_urls::require_course_module_id_param(); $capquiz = new capquiz($cmid); -if (!$capquiz) { - capquiz_urls::redirect_to_front_page(); -} - capquiz_urls::set_page_url($capquiz, capquiz_urls::$urlviewratingsystemconfig); -$renderer = $capquiz->renderer(); -$renderer->display_rating_system_configuration($capquiz); +$capquiz->renderer()->display_rating_system_configuration($capquiz); diff --git a/view_report.php b/view_report.php index 2045aef..e20aca5 100644 --- a/view_report.php +++ b/view_report.php @@ -37,10 +37,5 @@ $cmid = capquiz_urls::require_course_module_id_param(); $capquiz = new capquiz($cmid); -if (!$capquiz) { - capquiz_urls::redirect_to_front_page(); -} - capquiz_urls::set_page_url($capquiz, capquiz_urls::$urledit); -$renderer = $capquiz->renderer(); -$renderer->display_report($capquiz); +$capquiz->renderer()->display_report($capquiz);