���ѧۧݧ�ӧ�� �ާ֧ߧ֧էا֧� - ���֧էѧܧ�ڧ��ӧѧ�� - /home3/cpr76684/public_html/participation.tar
���ѧ٧ѧ�
styles.css 0000644 00000000652 15152312765 0006613 0 ustar 00 #page-report-participation-index .participationselectform { margin: 10px auto; } #page-report-participation-index .participationselectform label { margin-left: 15px; margin-right: 5px; } /* Die to css conflicts with form-inline, we have to create a specific class to fix submit button alignment on clean */ #page-report-participation-index .participationselectform input[type="submit"] { margin-bottom: 0; } db/install.php 0000644 00000002003 15152312765 0007312 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Post installation and migration code. * * @package report * @subpackage participation * @copyright 2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; function xmldb_report_participation_install() { global $DB; } db/access.php 0000644 00000002506 15152312765 0007115 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Capabilities * * @package report_participation * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $capabilities = array( 'report/participation:view' => array( 'riskbitmask' => RISK_PERSONAL, 'captype' => 'read', 'contextlevel' => CONTEXT_COURSE, 'archetypes' => array( 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW ), 'clonepermissionsfrom' => 'coursereport/participation:view', ) ); locallib.php 0000644 00000017165 15152312765 0007057 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * This file contains functions used by the participation reports * * @package report_participation * @copyright 2014 Rajesh Taneja <rajesh@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * Returns log table name of preferred reader, if leagcy then return empty string. * * @return string table name */ function report_participation_get_log_table_name() { // Get prefered sql_internal_table_reader reader (if enabled). $logmanager = get_log_manager(); $readers = $logmanager->get_readers(); $logtable = ''; // Get preferred reader. if (!empty($readers)) { foreach ($readers as $readerpluginname => $reader) { // If legacy reader is preferred reader. if ($readerpluginname == 'logstore_legacy') { break; } // If sql_internal_table_reader is preferred reader. if ($reader instanceof \core\log\sql_internal_table_reader) { $logtable = $reader->get_internal_log_table_name(); break; } } } return $logtable; } /** * Return time options, which should be shown for record filtering. * * @param int $minlog Time of first log record available. * @return array time options. */ function report_participation_get_time_options($minlog) { $timeoptions = array(); $now = usergetmidnight(time()); // Days. for ($i = 1; $i < 7; $i++) { if (strtotime('-'.$i.' days',$now) >= $minlog) { $timeoptions[strtotime('-'.$i.' days',$now)] = get_string('numdays','moodle',$i); } } // Weeks. for ($i = 1; $i < 10; $i++) { if (strtotime('-'.$i.' weeks',$now) >= $minlog) { $timeoptions[strtotime('-'.$i.' weeks',$now)] = get_string('numweeks','moodle',$i); } } // Months. for ($i = 2; $i < 12; $i++) { if (strtotime('-'.$i.' months',$now) >= $minlog) { $timeoptions[strtotime('-'.$i.' months',$now)] = get_string('nummonths','moodle',$i); } } // Try a year. if (strtotime('-1 year',$now) >= $minlog) { $timeoptions[strtotime('-1 year',$now)] = get_string('lastyear'); } return $timeoptions; } /** * Return action sql and params. * * @param string $action action to be filtered. * @param string $modname module name. * @return array actionsql and actionparams. */ function report_participation_get_action_sql($action, $modname) { global $CFG, $DB; $actionsql = ''; $actionparams = array(); $viewnames = array(); $postnames = array(); include_once($CFG->dirroot.'/mod/' . $modname . '/lib.php'); $viewfun = $modname.'_get_view_actions'; $postfun = $modname.'_get_post_actions'; if (function_exists($viewfun)) { $viewnames = $viewfun(); } if (function_exists($postfun)) { $postnames = $postfun(); } switch ($action) { case 'view': $actions = $viewnames; break; case 'post': $actions = $postnames; break; default: // Some modules have stuff we want to hide, ie mail blocked etc so do actually need to limit here. $actions = array_merge($viewnames, $postnames); } if (!empty($actions)) { list($actionsql, $actionparams) = $DB->get_in_or_equal($actions, SQL_PARAMS_NAMED, 'action'); $actionsql = " AND action $actionsql"; } return array($actionsql, $actionparams); } /** * Return crud sql and params. * * @param string $action action to be filtered. * @return array crudsql and crudparams. */ function report_participation_get_crud_sql($action) { global $DB; switch ($action) { case 'view': $crud = 'r'; break; case 'post': $crud = array('c', 'u', 'd'); break; default: $crud = array('c', 'r', 'u', 'd'); } list($crudsql, $crudparams) = $DB->get_in_or_equal($crud, SQL_PARAMS_NAMED, 'crud'); $crudsql = " AND crud " . $crudsql; return array($crudsql, $crudparams); } /** * List of action filters. * * @return array */ function report_participation_get_action_options() { return array('' => get_string('allactions'), 'view' => get_string('view'), 'post' => get_string('post'),); } /** * Print filter form. * * @param stdClass $course course object. * @param int $timefrom Time from which records should be fetched. * @param int $minlog Time of first record present in log store. * @param string $action action to be filtered. * @param int $roleid Role to be filtered. * @param int $instanceid Instance id of module. */ function report_participation_print_filter_form($course, $timefrom, $minlog, $action, $roleid, $instanceid) { global $DB; $timeoptions = report_participation_get_time_options($minlog); $actionoptions = report_participation_get_action_options(); $context = context_course::instance($course->id); $roles = get_roles_used_in_context($context); $rolesviewable = get_viewable_roles($context); $guestrole = get_guest_role(); $roleoptions = array_intersect_key($rolesviewable, $roles) + [ $guestrole->id => role_get_name($guestrole, $context), ]; $modinfo = get_fast_modinfo($course); $modules = $DB->get_records_select('modules', "visible = 1", null, 'name ASC'); $instanceoptions = array(); foreach ($modules as $module) { if (empty($modinfo->instances[$module->name])) { continue; } $instances = array(); foreach ($modinfo->instances[$module->name] as $cm) { // Skip modules such as label which do not actually have links; // this means there's nothing to participate in. if (!$cm->has_view()) { continue; } $instances[$cm->id] = format_string($cm->name); } if (count($instances) == 0) { continue; } $instanceoptions[] = array(get_string('modulenameplural', $module->name)=>$instances); } echo '<form class="participationselectform form-inline" action="index.php" method="get"><div>'."\n". '<input type="hidden" name="id" value="'.$course->id.'" />'."\n"; echo '<label for="menuinstanceid">'.get_string('activitymodule').'</label>'."\n"; echo html_writer::select($instanceoptions, 'instanceid', $instanceid); echo '<label for="menutimefrom">'.get_string('lookback').'</label>'."\n"; echo html_writer::select($timeoptions,'timefrom',$timefrom); echo '<label for="menuroleid">'.get_string('showonly').'</label>'."\n"; echo html_writer::select($roleoptions,'roleid',$roleid,false); echo '<label for="menuaction">'.get_string('showactions').'</label>'."\n"; echo html_writer::select($actionoptions, 'action', $action, false, ['class' => 'mr-1']); echo '<input type="submit" value="'.get_string('go').'" class="btn btn-primary"/>'."\n</div></form>\n"; } amd/build/participants.min.js.map 0000644 00000010622 15152312765 0013011 0 ustar 00 {"version":3,"file":"participants.min.js","sources":["../src/participants.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Some UI stuff for participants page.\n * This is also used by the report/participants/index.php because it has the same functionality.\n *\n * @module core_user/participants\n * @copyright 2017 Damyon Wiese\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport jQuery from 'jquery';\nimport CustomEvents from 'core/custom_interaction_events';\nimport ModalEvents from 'core/modal_events';\nimport Notification from 'core/notification';\nimport {showSendMessage} from 'core_user/local/participants/bulkactions';\n\nconst Selectors = {\n bulkActionSelect: \"#formactionid\",\n bulkUserSelectedCheckBoxes: \"input[data-togglegroup^='participants-table'][data-toggle='slave']:checked\",\n participantsForm: '#participantsform',\n};\n\nexport const init = () => {\n const root = document.querySelector(Selectors.participantsForm);\n\n /**\n * Private method.\n *\n * @method registerEventListeners\n * @private\n */\n const registerEventListeners = () => {\n CustomEvents.define(Selectors.bulkActionSelect, [CustomEvents.events.accessibleChange]);\n jQuery(Selectors.bulkActionSelect).on(CustomEvents.events.accessibleChange, e => {\n const action = e.target.value;\n const checkboxes = root.querySelectorAll(Selectors.bulkUserSelectedCheckBoxes);\n\n if (action.indexOf('#') !== -1) {\n e.preventDefault();\n\n const ids = [];\n checkboxes.forEach(checkbox => {\n ids.push(checkbox.getAttribute('name').replace('user', ''));\n });\n\n if (action === '#messageselect') {\n showSendMessage(ids)\n .then(modal => {\n modal.getRoot().on(ModalEvents.hidden, () => {\n // Focus on the action select when the dialog is closed.\n const bulkActionSelector = root.querySelector(Selectors.bulkActionSelect);\n resetBulkAction(bulkActionSelector);\n bulkActionSelector.focus();\n });\n\n return modal;\n })\n .catch(Notification.exception);\n }\n } else if (action !== '' && checkboxes.length) {\n e.target.form().submit();\n }\n\n resetBulkAction(e.target);\n });\n };\n\n const resetBulkAction = bulkActionSelect => {\n bulkActionSelect.value = '';\n };\n\n registerEventListeners();\n};\n"],"names":["Selectors","root","document","querySelector","resetBulkAction","bulkActionSelect","value","define","CustomEvents","events","accessibleChange","on","e","action","target","checkboxes","querySelectorAll","indexOf","preventDefault","ids","forEach","checkbox","push","getAttribute","replace","then","modal","getRoot","ModalEvents","hidden","bulkActionSelector","focus","catch","Notification","exception","length","form","submit"],"mappings":";;;;;;;;sTA8BMA,2BACgB,gBADhBA,qCAE0B,6EAF1BA,2BAGgB,kCAGF,WACVC,KAAOC,SAASC,cAAcH,4BA4C9BI,gBAAkBC,mBACpBA,iBAAiBC,MAAQ,uCApCZC,OAAOP,2BAA4B,CAACQ,mCAAaC,OAAOC,uCAC9DV,4BAA4BW,GAAGH,mCAAaC,OAAOC,kBAAkBE,UAClEC,OAASD,EAAEE,OAAOR,MAClBS,WAAad,KAAKe,iBAAiBhB,0CAEZ,IAAzBa,OAAOI,QAAQ,KAAa,CAC5BL,EAAEM,uBAEIC,IAAM,GACZJ,WAAWK,SAAQC,WACfF,IAAIG,KAAKD,SAASE,aAAa,QAAQC,QAAQ,OAAQ,QAG5C,mBAAXX,yCACgBM,KACfM,MAAKC,QACFA,MAAMC,UAAUhB,GAAGiB,sBAAYC,QAAQ,WAE7BC,mBAAqB7B,KAAKE,cAAcH,4BAC9CI,gBAAgB0B,oBAChBA,mBAAmBC,WAGhBL,SAEVM,MAAMC,sBAAaC,eAEN,KAAXrB,QAAiBE,WAAWoB,QACnCvB,EAAEE,OAAOsB,OAAOC,SAGpBjC,gBAAgBQ,EAAEE"} amd/build/participants.min.js 0000644 00000004341 15152312765 0012236 0 ustar 00 define("report_participation/participants",["exports","jquery","core/custom_interaction_events","core/modal_events","core/notification","core_user/local/participants/bulkactions"],(function(_exports,_jquery,_custom_interaction_events,_modal_events,_notification,_bulkactions){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} /** * Some UI stuff for participants page. * This is also used by the report/participants/index.php because it has the same functionality. * * @module core_user/participants * @copyright 2017 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=_interopRequireDefault(_jquery),_custom_interaction_events=_interopRequireDefault(_custom_interaction_events),_modal_events=_interopRequireDefault(_modal_events),_notification=_interopRequireDefault(_notification);const Selectors_bulkActionSelect="#formactionid",Selectors_bulkUserSelectedCheckBoxes="input[data-togglegroup^='participants-table'][data-toggle='slave']:checked",Selectors_participantsForm="#participantsform";_exports.init=()=>{const root=document.querySelector(Selectors_participantsForm),resetBulkAction=bulkActionSelect=>{bulkActionSelect.value=""};_custom_interaction_events.default.define(Selectors_bulkActionSelect,[_custom_interaction_events.default.events.accessibleChange]),(0,_jquery.default)(Selectors_bulkActionSelect).on(_custom_interaction_events.default.events.accessibleChange,(e=>{const action=e.target.value,checkboxes=root.querySelectorAll(Selectors_bulkUserSelectedCheckBoxes);if(-1!==action.indexOf("#")){e.preventDefault();const ids=[];checkboxes.forEach((checkbox=>{ids.push(checkbox.getAttribute("name").replace("user",""))})),"#messageselect"===action&&(0,_bulkactions.showSendMessage)(ids).then((modal=>(modal.getRoot().on(_modal_events.default.hidden,(()=>{const bulkActionSelector=root.querySelector(Selectors_bulkActionSelect);resetBulkAction(bulkActionSelector),bulkActionSelector.focus()})),modal))).catch(_notification.default.exception)}else""!==action&&checkboxes.length&&e.target.form().submit();resetBulkAction(e.target)}))}})); //# sourceMappingURL=participants.min.js.map amd/src/participants.js 0000644 00000006263 15152312765 0011151 0 ustar 00 // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Some UI stuff for participants page. * This is also used by the report/participants/index.php because it has the same functionality. * * @module core_user/participants * @copyright 2017 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ import jQuery from 'jquery'; import CustomEvents from 'core/custom_interaction_events'; import ModalEvents from 'core/modal_events'; import Notification from 'core/notification'; import {showSendMessage} from 'core_user/local/participants/bulkactions'; const Selectors = { bulkActionSelect: "#formactionid", bulkUserSelectedCheckBoxes: "input[data-togglegroup^='participants-table'][data-toggle='slave']:checked", participantsForm: '#participantsform', }; export const init = () => { const root = document.querySelector(Selectors.participantsForm); /** * Private method. * * @method registerEventListeners * @private */ const registerEventListeners = () => { CustomEvents.define(Selectors.bulkActionSelect, [CustomEvents.events.accessibleChange]); jQuery(Selectors.bulkActionSelect).on(CustomEvents.events.accessibleChange, e => { const action = e.target.value; const checkboxes = root.querySelectorAll(Selectors.bulkUserSelectedCheckBoxes); if (action.indexOf('#') !== -1) { e.preventDefault(); const ids = []; checkboxes.forEach(checkbox => { ids.push(checkbox.getAttribute('name').replace('user', '')); }); if (action === '#messageselect') { showSendMessage(ids) .then(modal => { modal.getRoot().on(ModalEvents.hidden, () => { // Focus on the action select when the dialog is closed. const bulkActionSelector = root.querySelector(Selectors.bulkActionSelect); resetBulkAction(bulkActionSelector); bulkActionSelector.focus(); }); return modal; }) .catch(Notification.exception); } } else if (action !== '' && checkboxes.length) { e.target.form().submit(); } resetBulkAction(e.target); }); }; const resetBulkAction = bulkActionSelect => { bulkActionSelect.value = ''; }; registerEventListeners(); }; tests/lib_test.php 0000644 00000004045 15152312765 0010236 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Tests for report library functions. * * @package report_participation * @copyright 2014 onwards Ankit agarwal <ankit.agrr@gmail.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later. */ namespace report_participation; defined('MOODLE_INTERNAL') || die(); /** * Class report_participation_lib_testcase * * @package report_participation * @copyright 2014 onwards Ankit agarwal <ankit.agrr@gmail.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later. */ class lib_test extends \advanced_testcase { /** * Test report_log_supports_logstore. */ public function test_report_participation_supports_logstore() { $logmanager = get_log_manager(); $allstores = \core_component::get_plugin_list_with_class('logstore', 'log\store'); $supportedstores = array( 'logstore_legacy' => '\logstore_legacy\log\store', 'logstore_standard' => '\logstore_standard\log\store' ); // Make sure all supported stores are installed. $expectedstores = array_keys(array_intersect($allstores, $supportedstores)); $stores = $logmanager->get_supported_logstores('report_participation'); $stores = array_keys($stores); foreach ($expectedstores as $expectedstore) { $this->assertContains($expectedstore, $stores); } } } tests/behat/message_participants.feature 0000644 00000006466 15152312765 0014576 0 ustar 00 @report @report_participation @javascript Feature: Use the particiaption report to message groups of students In order to engage with students based on participation As a teacher I need to be able to message students who have not participated in an activity Background: Given the following "courses" exist: | fullname | shortname | category | groupmode | | Course 1 | C1 | 0 | 1 | And the following "users" exist: | username | firstname | lastname | | teacher1 | Teacher | 1 | | student1 | Student | 1 | | student2 | Student | 2 | | student3 | Student | 3 | And the following "course enrolments" exist: | user | course | role | | teacher1 | C1 | editingteacher | | student1 | C1 | student | | student2 | C1 | student | | student3 | C1 | student | And the following "activity" exists: | course | C1 | | activity | book | | name | Test book name | | idnumber | Test book name | | idnumber | book1 | And I am on the "Test book name" "book activity" page logged in as student1 Scenario: Message all students from the participation report Given I am on the "Course 1" course page logged in as teacher1 And I navigate to "Reports" in current page administration And I click on "Course participation" "link" And I set the field "instanceid" to "Test book name" And I set the field "roleid" to "Student" And I press "Go" When I click on "select-all-participants" "checkbox" And I choose "Send a message" from the participants page bulk action menu Then "Send message to 3 people" "dialogue" should exist And I set the field "Message" to "Hi there" And I press "Send message to 3 people" And I should see "Message sent to 3 people" Scenario: Message students who have not participated in book Given I am on the "Course 1" course page logged in as teacher1 And I navigate to "Reports" in current page administration And I click on "Course participation" "link" And I set the field "instanceid" to "Test book name" And I set the field "roleid" to "Student" And I press "Go" And I should see "Yes (1)" in the "Student 1" "table_row" And I should see "No" in the "Student 2" "table_row" And I should see "No" in the "Student 3" "table_row" When I press "Select all 'No'" And I choose "Send a message" from the participants page bulk action menu Then "Send message to 2 people" "dialogue" should exist And I set the field "Message" to "Hi there" And I press "Send message to 2 people" And I should see "Message sent to 2 people" Scenario: Ensure no message options when messaging is disabled Given the following config values are set as admin: | messaging | 0 | And I am on the "Course 1" course page logged in as teacher1 And I navigate to "Reports" in current page administration And I click on "Course participation" "link" When I set the field "instanceid" to "Test book name" And I set the field "roleid" to "Student" And I press "Go" Then I should not see "With selected users..." And "select-all-participants" "checkbox" should not exist tests/behat/course_report_participation.feature 0000644 00000002170 15152312765 0016176 0 ustar 00 @report @report_participation Feature: In a course administration page, navigate through report page, test for course participation page In order to navigate through report page As an admin Go to course administration -> Reports -> Course participation Background: Given the following "courses" exist: | fullname | shortname | category | groupmode | | Course 1 | C1 | 0 | 1 | And the following "users" exist: | username | firstname | lastname | email | | student1 | Student | 1 | student1@example.com | And the following "course enrolments" exist: | user | course | role | | admin | C1 | editingteacher | | student1 | C1 | student | @javascript Scenario: Selector should be available in the course participation page Given I log in as "admin" And I am on "Course 1" course homepage When I navigate to "Reports" in current page administration And I click on "Course participation" "link" Then "Report" "field" should exist And the "Report" select box should contain "Course participation" And the field "Report" matches value "Course participation" tests/behat/filter_participation.feature 0000644 00000010705 15152312765 0014573 0 ustar 00 @report @report_participation Feature: In a participation report, admin can filter student actions In order to filter participation data As a student I need to log action and then log in as admin to view participation report Background: Given the following "courses" exist: | fullname | shortname | category | groupmode | | Course 1 | C1 | 0 | 1 | And the following "users" exist: | username | firstname | lastname | email | | manager1 | Manager | 1 | manager1@example.com | | teacher1 | Teacher | 1 | teacher1@example.com | | student1 | Student | 1 | student1@example.com | And the following "course enrolments" exist: | user | course | role | | manager1 | C1 | manager | | teacher1 | C1 | editingteacher | | student1 | C1 | student | And the following "activity" exists: | course | C1 | | activity | book | | name | Test book name | | idnumber | book1 | And the following "mod_book > chapter" exists: | book | Test book name | | title | Test chapter | | content | Test chapter content | @javascript Scenario: Filter participation report when only legacy log reader is enabled Given I log in as "admin" And I navigate to "Plugins > Logging > Manage log stores" in site administration And I click on "Disable" "link" in the "Standard log" "table_row" And I click on "Enable" "link" in the "Legacy log" "table_row" And the following config values are set as admin: | loglegacy | 1 | logstore_legacy | And I am on the "Test book name" "book activity" page logged in as student1 When I am on the "Course 1" course page logged in as admin When I navigate to "Reports" in current page administration And I click on "Course participation" "link" And I set the field "instanceid" to "Test book name" And I set the field "roleid" to "Student" And I press "Go" Then I should see "Yes (1)" @javascript Scenario: Filter participation report when standard log reader is enabled later Given I log in as "admin" And I navigate to "Plugins > Logging > Manage log stores" in site administration And I click on "Disable" "link" in the "Standard log" "table_row" And I click on "Enable" "link" in the "Legacy log" "table_row" And the following config values are set as admin: | loglegacy | 1 | logstore_legacy | And I am on the "Test book name" "book activity" page logged in as student1 And I log out And I log in as "admin" And I navigate to "Plugins > Logging > Manage log stores" in site administration And I click on "Enable" "link" in the "Standard log" "table_row" And I am on the "Test book name" "book activity" page logged in as student1 And I am on the "Course 1" course page logged in as admin When I navigate to "Reports" in current page administration And I click on "Course participation" "link" And I set the field "instanceid" to "Test book name" And I set the field "roleid" to "Student" And I press "Go" Then I should see "Yes (2)" @javascript Scenario: Filter participation report when only standard log reader is enabled by default Given I am on the "Test book name" "book activity" page logged in as student1 And I am on the "Course 1" course page logged in as admin And I navigate to "Reports" in current page administration And I click on "Course participation" "link" And I set the field "instanceid" to "Test book name" And I set the field "roleid" to "Student" And I press "Go" Then I should see "Yes (1)" @javascript Scenario Outline: Filter participation report by viewable roles Given I am on the "Course 1" course page logged in as "teacher1" When I navigate to "Reports" in current page administration And I click on "Course participation" "link" # Teacher role cannot see Manager by default. Then "Manager" "option" should not exist in the "Show only" "select" And I set the following fields to these values: | Activity module | Test book name | | Show only | <role> | And I press "Go" And I should see "<uservisible>" in the "reporttable" "table" And I should not see "<usernonvisible>" in the "reporttable" "table" Examples: | role | uservisible | usernonvisible | | Student | Student 1 | Teacher 1 | | Teacher | Teacher 1 | Student 1 | index.php 0000644 00000037641 15152312765 0006406 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Participation report * * @package report * @subpackage participation * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ use core\report_helper; require('../../config.php'); require_once($CFG->dirroot.'/lib/tablelib.php'); require_once($CFG->dirroot.'/notes/lib.php'); require_once($CFG->dirroot.'/report/participation/locallib.php'); $participantsperpage = intval(get_config('moodlecourse', 'participantsperpage')); define('DEFAULT_PAGE_SIZE', (!empty($participantsperpage) ? $participantsperpage : 20)); define('SHOW_ALL_PAGE_SIZE', 5000); $id = required_param('id', PARAM_INT); // course id. $roleid = optional_param('roleid', 0, PARAM_INT); // which role to show $instanceid = optional_param('instanceid', 0, PARAM_INT); // instance we're looking at. $timefrom = optional_param('timefrom', 0, PARAM_INT); // how far back to look... $action = optional_param('action', '', PARAM_ALPHA); $page = optional_param('page', 0, PARAM_INT); // which page to show $perpage = optional_param('perpage', DEFAULT_PAGE_SIZE, PARAM_INT); // how many per page $currentgroup = optional_param('group', null, PARAM_INT); // Get the active group. $url = new moodle_url('/report/participation/index.php', array('id'=>$id)); if ($roleid !== 0) $url->param('roleid'); if ($instanceid !== 0) $url->param('instanceid'); if ($timefrom !== 0) $url->param('timefrom'); if ($action !== '') $url->param('action'); if ($page !== 0) $url->param('page'); if ($perpage !== DEFAULT_PAGE_SIZE) $url->param('perpage'); $PAGE->set_url($url); $PAGE->set_pagelayout('admin'); if ($action != 'view' and $action != 'post') { $action = ''; // default to all (don't restrict) } if (!$course = $DB->get_record('course', array('id'=>$id))) { throw new \moodle_exception('invalidcourse'); } if ($roleid != 0 and !$role = $DB->get_record('role', array('id'=>$roleid))) { throw new \moodle_exception('invalidrole'); } require_login($course); $context = context_course::instance($course->id); require_capability('report/participation:view', $context); $strparticipation = get_string('participationreport'); $strviews = get_string('views'); $strposts = get_string('posts'); $strreports = get_string('reports'); $actionoptions = report_participation_get_action_options(); if (!array_key_exists($action, $actionoptions)) { $action = ''; } $PAGE->set_title(format_string($course->shortname, true, array('context' => $context)) .': '. $strparticipation); $PAGE->set_heading(format_string($course->fullname, true, array('context' => $context))); echo $OUTPUT->header(); // Print the selector dropdown. $pluginname = get_string('pluginname', 'report_participation'); report_helper::print_report_selector($pluginname); // Release session lock. \core\session\manager::write_close(); // Logs will not have been recorded before the course timecreated time. $minlog = $course->timecreated; $onlyuselegacyreader = false; // Use only legacy log table to aggregate records. $logtable = report_participation_get_log_table_name(); // Log table to use for fetaching records. // If no log table, then use legacy records. if (empty($logtable)) { $onlyuselegacyreader = true; } $modinfo = get_fast_modinfo($course); // Print first controls. report_participation_print_filter_form($course, $timefrom, $minlog, $action, $roleid, $instanceid); $baseurl = new moodle_url('/report/participation/index.php', array( 'id' => $course->id, 'roleid' => $roleid, 'instanceid' => $instanceid, 'timefrom' => $timefrom, 'action' => $action, 'perpage' => $perpage, 'group' => $currentgroup )); $select = groups_allgroups_course_menu($course, $baseurl, true, $currentgroup); // User cannot see any group. if (empty($select)) { echo $OUTPUT->heading(get_string("notingroup")); echo $OUTPUT->footer(); exit; } else { echo $select; } // Fetch current active group. $groupmode = groups_get_course_groupmode($course); $currentgroup = $SESSION->activegroup[$course->id][$groupmode][$course->defaultgroupingid]; if (!empty($instanceid) && !empty($roleid)) { $uselegacyreader = $DB->record_exists('log', ['course' => $course->id]); // Trigger a report viewed event. $event = \report_participation\event\report_viewed::create(array('context' => $context, 'other' => array('instanceid' => $instanceid, 'groupid' => $currentgroup, 'roleid' => $roleid, 'timefrom' => $timefrom, 'action' => $action))); $event->trigger(); // from here assume we have at least the module we're using. $cm = $modinfo->cms[$instanceid]; // Group security checks. if (!groups_group_visible($currentgroup, $course, $cm)) { echo $OUTPUT->heading(get_string("notingroup")); echo $OUTPUT->footer(); exit; } $table = new flexible_table('course-participation-'.$course->id.'-'.$cm->id.'-'.$roleid); $table->course = $course; $actionheader = !empty($action) ? get_string($action) : get_string('allactions'); if (empty($CFG->messaging)) { $table->define_columns(array('fullname', 'count')); $table->define_headers(array(get_string('user'), $actionheader)); } else { $table->define_columns(array('fullname', 'count', 'select')); $mastercheckbox = new \core\output\checkbox_toggleall('participants-table', true, [ 'id' => 'select-all-participants', 'name' => 'select-all-participants', 'label' => get_string('select'), // Consistent labels to prevent select column from resizing. 'selectall' => get_string('select'), 'deselectall' => get_string('select'), ]); $table->define_headers(array(get_string('user'), $actionheader, $OUTPUT->render($mastercheckbox))); } $table->define_baseurl($baseurl); $table->set_attribute('class', 'generaltable generalbox reporttable'); $table->sortable(true,'lastname','ASC'); $table->no_sorting('select'); $table->set_control_variables(array( TABLE_VAR_SORT => 'ssort', TABLE_VAR_HIDE => 'shide', TABLE_VAR_SHOW => 'sshow', TABLE_VAR_IFIRST => 'sifirst', TABLE_VAR_ILAST => 'silast', TABLE_VAR_PAGE => 'spage' )); $table->setup(); // We want to query both the current context and parent contexts. list($relatedctxsql, $params) = $DB->get_in_or_equal($context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'relatedctx'); $params['roleid'] = $roleid; $params['instanceid'] = $instanceid; $params['timefrom'] = $timefrom; $groupsql = ""; if (!empty($currentgroup)) { $groupsql = "JOIN {groups_members} gm ON (gm.userid = u.id AND gm.groupid = :groupid)"; $params['groupid'] = $currentgroup; } $countsql = "SELECT COUNT(DISTINCT(ra.userid)) FROM {role_assignments} ra JOIN {user} u ON u.id = ra.userid $groupsql WHERE ra.contextid $relatedctxsql AND ra.roleid = :roleid"; $totalcount = $DB->count_records_sql($countsql, $params); list($twhere, $tparams) = $table->get_sql_where(); if ($twhere) { $params = array_merge($params, $tparams); $matchcount = $DB->count_records_sql($countsql.' AND '.$twhere, $params); } else { $matchcount = $totalcount; } $modulename = get_string('modulename', $cm->modname); echo '<div id="participationreport">' . "\n"; echo '<p class="modulename">' . $modulename . ' ' . $strviews . '<br />'."\n" . $modulename . ' ' . $strposts . '</p>'."\n"; $table->initialbars($totalcount > $perpage); $table->pagesize($perpage, $matchcount); if ($uselegacyreader || $onlyuselegacyreader) { list($actionsql, $actionparams) = report_participation_get_action_sql($action, $cm->modname); $params = array_merge($params, $actionparams); } if (!$onlyuselegacyreader) { list($crudsql, $crudparams) = report_participation_get_crud_sql($action); $params = array_merge($params, $crudparams); } $userfieldsapi = \core_user\fields::for_name(); $usernamefields = $userfieldsapi->get_sql('u', false, '', '', false)->selects; $users = array(); // If using legacy log then get users from old table. if ($uselegacyreader || $onlyuselegacyreader) { $sql = "SELECT ra.userid, $usernamefields, u.idnumber, l.actioncount AS count FROM (SELECT DISTINCT userid FROM {role_assignments} WHERE contextid $relatedctxsql AND roleid = :roleid ) ra JOIN {user} u ON u.id = ra.userid $groupsql LEFT JOIN ( SELECT userid, COUNT(action) AS actioncount FROM {log} WHERE cmid = :instanceid AND time > :timefrom " . $actionsql . " GROUP BY userid) l ON (l.userid = ra.userid)"; if ($twhere) { $sql .= ' WHERE '.$twhere; // Initial bar. } if ($table->get_sql_sort()) { $sql .= ' ORDER BY '.$table->get_sql_sort(); } if (!$users = $DB->get_records_sql($sql, $params, $table->get_page_start(), $table->get_page_size())) { $users = array(); // Tablelib will handle saying 'Nothing to display' for us. } } // Get record from sql_internal_table_reader and merge with records got from legacy log (if needed). if (!$onlyuselegacyreader) { $sql = "SELECT ra.userid, $usernamefields, u.idnumber, COUNT(DISTINCT l.timecreated) AS count FROM {user} u JOIN {role_assignments} ra ON u.id = ra.userid AND ra.contextid $relatedctxsql AND ra.roleid = :roleid $groupsql LEFT JOIN {" . $logtable . "} l ON l.contextinstanceid = :instanceid AND l.timecreated > :timefrom" . $crudsql ." AND l.edulevel = :edulevel AND l.anonymous = 0 AND l.contextlevel = :contextlevel AND (l.origin = 'web' OR l.origin = 'ws') AND l.userid = ra.userid"; // We add this after the WHERE statement that may come below. $groupbysql = " GROUP BY ra.userid, $usernamefields, u.idnumber"; $params['edulevel'] = core\event\base::LEVEL_PARTICIPATING; $params['contextlevel'] = CONTEXT_MODULE; if ($twhere) { $sql .= ' WHERE '.$twhere; // Initial bar. } $sql .= $groupbysql; if ($table->get_sql_sort()) { $sql .= ' ORDER BY '.$table->get_sql_sort(); } if ($u = $DB->get_records_sql($sql, $params, $table->get_page_start(), $table->get_page_size())) { if (empty($users)) { $users = $u; } else { // Merge two users array. foreach ($u as $key => $value) { if (isset($users[$key]) && !empty($users[$key]->count)) { if ($value->count) { $users[$key]->count += $value->count; } } else { $users[$key] = $value; } } } unset($u); $u = null; } } $data = array(); $a = new stdClass(); $a->count = $totalcount; $a->items = format_string($role->name, true, array('context' => $context)); if ($matchcount != $totalcount) { $a->count = $matchcount.'/'.$a->count; } echo '<h2>'.get_string('counteditems', '', $a).'</h2>'."\n"; if (!empty($CFG->messaging)) { echo '<form action="'.$CFG->wwwroot.'/user/action_redir.php" method="post" id="participantsform">'."\n"; echo '<div>'."\n"; echo '<input type="hidden" name="id" value="'.$id.'" />'."\n"; echo '<input type="hidden" name="returnto" value="'. s($PAGE->url) .'" />'."\n"; echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />'."\n"; } foreach ($users as $u) { $data = array(); $data[] = html_writer::link(new moodle_url('/user/view.php', array('id' => $u->userid, 'course' => $course->id)), fullname($u, true)); $data[] = !empty($u->count) ? get_string('yes').' ('.$u->count.') ' : get_string('no'); if (!empty($CFG->messaging)) { $togglegroup = 'participants-table'; if (empty($u->count)) { $togglegroup .= ' no'; } $checkbox = new \core\output\checkbox_toggleall($togglegroup, false, [ 'classes' => 'usercheckbox', 'name' => 'user' . $u->userid, 'value' => $u->count, ]); $data[] = $OUTPUT->render($checkbox); } $table->add_data($data); } $table->print_html(); if ($perpage == SHOW_ALL_PAGE_SIZE) { $perpageurl = new moodle_url($baseurl, array('perpage' => DEFAULT_PAGE_SIZE)); echo html_writer::start_div('', array('id' => 'showall')); echo html_writer::link($perpageurl, get_string('showperpage', '', DEFAULT_PAGE_SIZE)); echo html_writer::end_div(); } else if ($matchcount > 0 && $perpage < $matchcount) { $perpageurl = new moodle_url($baseurl, array('perpage' => SHOW_ALL_PAGE_SIZE)); echo html_writer::start_div('', array('id' => 'showall')); echo html_writer::link($perpageurl, get_string('showall', '', $matchcount)); echo html_writer::end_div(); } if (!empty($CFG->messaging)) { echo '<div class="selectbuttons btn-group">'; if ($perpage >= $matchcount) { $checknos = new \core\output\checkbox_toggleall('participants-table no', true, [ 'id' => 'select-nos', 'name' => 'select-nos', 'label' => get_string('selectnos'), 'selectall' => get_string('selectnos'), 'deselectall' => get_string('deselectnos'), ], true); echo $OUTPUT->render($checknos); } echo '</div>'; echo '<div class="py-3">'; echo html_writer::label(get_string('withselectedusers'), 'formactionid'); $displaylist['#messageselect'] = get_string('messageselectadd'); $withselectedparams = array( 'id' => 'formactionid', 'data-action' => 'toggle', 'data-togglegroup' => 'participants-table', 'data-toggle' => 'action', 'disabled' => true ); echo html_writer::select($displaylist, 'formaction', '', array('' => 'choosedots'), $withselectedparams); echo '</div>'; echo '</div>'."\n"; echo '</form>'."\n"; $options = new stdClass(); $options->courseid = $course->id; $options->noteStateNames = note_get_state_names(); $options->stateHelpIcon = $OUTPUT->help_icon('publishstate', 'notes'); $PAGE->requires->js_call_amd('report_participation/participants', 'init', [$options]); } echo '</div>'."\n"; } echo $OUTPUT->footer(); lib.php 0000644 00000005436 15152312765 0006042 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * This file contains functions used by the participation report * * @package report * @subpackage participation * @copyright 2009 Sam Hemelryk * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; /** * This function extends the navigation with the report items * * @param navigation_node $navigation The navigation node to extend * @param stdClass $course The course to object for the report * @param stdClass $context The context of the course */ function report_participation_extend_navigation_course($navigation, $course, $context) { global $CFG, $OUTPUT; if (has_capability('report/participation:view', $context)) { $url = new moodle_url('/report/participation/index.php', array('id'=>$course->id)); $navigation->add(get_string('pluginname', 'report_participation'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('i/report', '')); } } /** * Return a list of page types * @param string $pagetype current page type * @param stdClass $parentcontext Block's parent context * @param stdClass $currentcontext Current context of block * @return array */ function report_participation_page_type_list($pagetype, $parentcontext, $currentcontext) { $array = array( '*' => get_string('page-x', 'pagetype'), 'report-*' => get_string('page-report-x', 'pagetype'), 'report-participation-*' => get_string('page-report-participation-x', 'report_participation'), 'report-participation-index' => get_string('page-report-participation-index', 'report_participation'), ); return $array; } /** * Callback to verify if the given instance of store is supported by this report or not. * * @param string $instance store instance. * * @return bool returns true if the store is supported by the report, false otherwise. */ function report_participation_supports_logstore($instance) { if ($instance instanceof \core\log\sql_internal_table_reader || $instance instanceof \logstore_legacy\log\store) { return true; } return false; } version.php 0000644 00000002301 15152312765 0006745 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Version info * * @package report * @subpackage participation * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; $plugin->version = 2022112800; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2022111800; // Requires this Moodle version. $plugin->component = 'report_participation'; // Full name of the plugin (used for diagnostics) classes/privacy/provider.php 0000644 00000003000 15152312765 0012221 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Privacy Subsystem implementation for report_participation. * * @package report_participation * @copyright 2018 Zig Tan <zig@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace report_participation\privacy; defined('MOODLE_INTERNAL') || die(); /** * Privacy Subsystem for report_participation implementing null_provider. * * @copyright 2018 Zig Tan <zig@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class provider implements \core_privacy\local\metadata\null_provider { /** * Get the language string identifier with the component's language * file to explain why this plugin stores no data. * * @return string */ public static function get_reason() : string { return 'privacy:metadata'; } }classes/event/report_viewed.php 0000644 00000010236 15152312765 0012722 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * The report_participation report viewed event. * * @package report_participation * @copyright 2013 Ankit Agarwal * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace report_participation\event; defined('MOODLE_INTERNAL') || die(); /** * The report_participation report viewed event class. * * @property-read array $other { * Extra information about the event. * * - int instanceid: Id of instance. * - int roleid: Role id for whom report is viewed. * - int groupid: (optional) group id. * - int timefrom: (optional) time from which report is viewed. * - string action: (optional) action viewed. * } * * @package report_participation * @since Moodle 2.7 * @copyright 2013 Ankit Agarwal * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class report_viewed extends \core\event\base { /** * Init method. * * @return void */ protected function init() { $this->data['crud'] = 'r'; $this->data['edulevel'] = self::LEVEL_TEACHING; } /** * Return localised event name. * * @return string */ public static function get_name() { return get_string('eventreportviewed', 'report_participation'); } /** * Returns description of what happened. * * @return string */ public function get_description() { return "The user with id '$this->userid' viewed the course participation report for the course with id '$this->courseid'."; } /** * Return the legacy event log data. * * @return array */ protected function get_legacy_logdata() { return array($this->courseid, "course", "report participation", "report/participation/index.php?id=" . $this->courseid, $this->courseid); } /** * Returns relevant URL. * * @return \moodle_url */ public function get_url() { return new \moodle_url('/report/participation/index.php', array('id' => $this->courseid, 'instanceid' => $this->other['instanceid'], 'roleid' => $this->other['roleid'])); } /** * Custom validation. * * @throws \coding_exception * @return void */ protected function validate_data() { parent::validate_data(); if (empty($this->other['instanceid'])) { throw new \coding_exception('The \'instanceid\' value must be set in other.'); } if (empty($this->other['roleid'])) { throw new \coding_exception('The \'roleid\' value must be set in other.'); } if (!isset($this->other['groupid'])) { throw new \coding_exception('The \'groupid\' value must be set in other.'); } if (!isset($this->other['timefrom'])) { throw new \coding_exception('The \'timefrom\' value must be set in other.'); } if (!isset($this->other['action'])) { throw new \coding_exception('The \'action\' value must be set in other.'); } } public static function get_other_mapping() { $othermapped = array(); // This is a badly named variable - it represents "cm->id" not "cm->instance". $othermapped['instanceid'] = array('db' => 'course_modules', 'restore' => 'course_module'); $othermapped['roleid'] = array('db' => 'role', 'restore' => 'role'); $othermapped['groupid'] = array('db' => 'groups', 'restore' => 'group'); return $othermapped; } } lang/en/report_participation.php 0000644 00000002560 15152312765 0013053 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Lang strings * * @package report * @subpackage participation * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ $string['eventreportviewed'] = 'Participation report viewed'; $string['nologreaderenabled'] = 'No log reader enabled'; $string['participation:view'] = 'View course participation report'; $string['page-report-participation-x'] = 'Any participation report'; $string['page-report-participation-index'] = 'Course participation report'; $string['pluginname'] = 'Course participation'; $string['privacy:metadata'] = 'The Course participation plugin does not store any personal data.';
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | ���֧ߧ֧�ѧ�ڧ� ����ѧߧڧ��: 0 |
proxy
|
phpinfo
|
���ѧ����ۧܧ�