diff --git a/.github/workflows/config.json b/.github/workflows/config.json new file mode 100644 index 00000000..c6c32e86 --- /dev/null +++ b/.github/workflows/config.json @@ -0,0 +1,46 @@ +{ + "moodle-plugin-ci": "4.5.9", + "main-moodle": "MOODLE_502_STABLE", + "main-php": "8.3", + "main-db": "pgsql", + "moodle-testmatrix": { + "MOODLE_405_STABLE": { + "php": [ + "8.1", + "8.3" + ], + "db": [ + "pgsql" + ] + }, + "MOODLE_500_STABLE": { + "php": [ + "8.2", + "8.4" + ], + "db": [ + "pgsql" + ] + }, + "MOODLE_501_STABLE": { + "php": [ + "8.2", + "8.4" + ], + "db": [ + "pgsql" + ] + }, + "MOODLE_502_STABLE": { + "php": [ + "8.3", + "8.4" + ], + "db": [ + "pgsql", + "mariadb", + "mysqli" + ] + } + } +} \ No newline at end of file diff --git a/.github/workflows/moodle-plugin-ci.yml b/.github/workflows/moodle-plugin-ci.yml index a44a843b..1f60a633 100644 --- a/.github/workflows/moodle-plugin-ci.yml +++ b/.github/workflows/moodle-plugin-ci.yml @@ -1,119 +1,14 @@ -name: Moodle plugin CI -on: [push, pull_request] +name: Moodle Plugin CI -jobs: - test: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - include: - - php: '8.1' - moodle-branch: 'MOODLE_403_STABLE' - database: 'pgsql' - - php: '8.1' - moodle-branch: 'MOODLE_403_STABLE' - database: 'mariadb' - - services: - postgres: - image: postgres:14 - 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 - - mariadb: - 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 - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - path: plugin - - - name: Setup PHP ${{ matrix.php }} - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - extensions: ${{ matrix.extensions }} - ini-values: max_input_vars=5000 - coverage: none - - - name: Deploy moodle-plugin-ci - run: | - composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^4 - # Add dirs to $PATH - 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 - echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV - - - name: Install Moodle - # Need explicit IP to stop mysql client fail on attempt to use unix socket. - run: moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 - env: - DB: ${{ matrix.database }} - MOODLE_BRANCH: ${{ matrix.moodle-branch }} - IGNORE_PATHS: 'templates/local/mobile' - - - name: PHP Lint - if: ${{ always() }} - run: moodle-plugin-ci phplint - - - name: PHP Copy/Paste Detector - continue-on-error: true # This step will show errors but will not fail - if: ${{ always() }} - run: moodle-plugin-ci phpcpd +on: + push: + branches: + - main + pull_request: + branches: + - main - - name: PHP Mess Detector - continue-on-error: true # This step will show errors but will not fail - if: ${{ always() }} - run: moodle-plugin-ci phpmd - - - name: Moodle Code Checker - if: ${{ always() }} - run: moodle-plugin-ci codechecker - - - name: Moodle PHPDoc Checker - if: ${{ always() }} - run: moodle-plugin-ci phpdoc - - - name: Validating - if: ${{ always() }} - run: moodle-plugin-ci validate - - - name: Check upgrade savepoints - if: ${{ always() }} - run: moodle-plugin-ci savepoints - - - name: Mustache Lint - if: ${{ always() }} - run: moodle-plugin-ci mustache - - - name: Grunt - if: ${{ always() }} - run: moodle-plugin-ci grunt --max-lint-warnings 0 - - - name: PHPUnit tests - if: ${{ always() }} - run: moodle-plugin-ci phpunit - - - name: Behat features - if: ${{ always() }} - run: moodle-plugin-ci behat --profile chrome +jobs: + call-moodle-ci: + name: "Run CI workflow for Learnweb plugins" + uses: learnweb/moodle-workflows-learnweb/.github/workflows/moodle-ci.yml@main diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 00000000..76d2cd4e --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,10 @@ +CHANGELOG +========= + +Changes in v5.2-r1 +---------------------------------- + +- support for Moodle 5.0, 5.1, 5.2 +- add CHANGES.md for user-visible changes +- Migrated CI testing to the shared Learnweb Moodle workflow +- Added a test matrix covering Moodle 4.5, 5.0, 5.1, and 5.2 with multiple supported PHP versions and database systems \ No newline at end of file diff --git a/README.md b/README.md index 3d0cbd95..39f19a1e 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ moodle-mod_scheduler ==================== -[![Latest Release](https://img.shields.io/github/v/release/bostelm/moodle-mod_scheduler?sort=semver&color=orange)](https://github.com/bostelm/moodle-mod_scheduler/releases) -[![Moodle Plugin CI](https://github.com/bostelm/moodle-mod_scheduler/workflows/Moodle%20plugin%20CI/badge.svg?branch=master)](https://github.com/bostelm/moodle-mod_scheduler/actions?query=workflow%3A%22Moodle+plugin+CI%22+branch%3Amaster) +[![Latest Release](https://img.shields.io/github/v/release/learnweb/moodle-mod_scheduler?sort=semver&color=orange)](https://github.com/learnweb/moodle-mod_scheduler/releases) +[![Moodle plugin CI](https://github.com/learnweb/moodle-mod_scheduler/actions/workflows/moodle-plugin-ci.yml/badge.svg)](https://github.com/learnweb/moodle-mod_scheduler/actions/workflows/moodle-plugin-ci.yml) Appointment Scheduler for Moodle diff --git a/ajax.php b/ajax.php index fdbb9ba9..c228239f 100644 --- a/ajax.php +++ b/ajax.php @@ -24,17 +24,17 @@ define('AJAX_SCRIPT', true); -use \mod_scheduler\model\scheduler; -use \mod_scheduler\permission\scheduler_permissions; +use mod_scheduler\model\scheduler; +use mod_scheduler\permission\scheduler_permissions; -require_once(dirname(dirname(dirname(__FILE__))).'/config.php'); +require_once(dirname(dirname(dirname(__FILE__))) . '/config.php'); require_once('locallib.php'); $id = required_param('id', PARAM_INT); $action = required_param('action', PARAM_ALPHA); $cm = get_coursemodule_from_id('scheduler', $id, 0, false, MUST_EXIST); -$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); +$course = $DB->get_record('course', ['id' => $cm->course], '*', MUST_EXIST); $scheduler = scheduler::load_by_coursemodule_id($id); require_login($course, true, $cm); @@ -46,9 +46,8 @@ switch ($action) { case 'saveseen': - $appid = required_param('appointmentid', PARAM_INT); - list($slot, $app) = $scheduler->get_slot_appointment($appid); + [$slot, $app] = $scheduler->get_slot_appointment($appid); $newseen = required_param('seen', PARAM_BOOL); $permissions->ensure($permissions->can_edit_attended($app)); diff --git a/amd/build/delselected.min.js b/amd/build/delselected.min.js index e408b7e7..e1cfe497 100644 --- a/amd/build/delselected.min.js +++ b/amd/build/delselected.min.js @@ -1,4 +1,4 @@ -define("mod_scheduler/delselected",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=_exports.collect_selection=_exports.SELECTORS=void 0; +define("mod_scheduler/delselected",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=_exports.collectSelection=_exports.SELECTORS=void 0; /** * TODO describe module delselected * @@ -6,6 +6,6 @@ define("mod_scheduler/delselected",["exports"],(function(_exports){Object.define * @copyright 2024 ISB Bayern * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -const SELECTORS={DELACTION:"div.commandbar a#delselected",SELECTBOX:"table#slotmanager input.slotselect"};_exports.SELECTORS=SELECTORS;_exports.init=baseurl=>{let link=document.querySelector(SELECTORS.DELACTION);null!==link&&link.addEventListener("click",(function(){collect_selection(link,baseurl)}))};const collect_selection=(link,baseurl)=>{let sellist="";document.querySelectorAll(SELECTORS.SELECTBOX).forEach((function(box){box.checked&&(sellist.length>0&&(sellist+=","),sellist+=box.getAttribute("value"))})),link.setAttribute("href",baseurl+"&items="+sellist)};_exports.collect_selection=collect_selection})); +const SELECTORS={DELACTION:"div.commandbar a#delselected",SELECTBOX:"table#slotmanager input.slotselect"};_exports.SELECTORS=SELECTORS;_exports.init=baseurl=>{let link=document.querySelector(SELECTORS.DELACTION);null!==link&&link.addEventListener("click",(function(){collectSelection(link,baseurl)}))};const collectSelection=(link,baseurl)=>{let sellist="";document.querySelectorAll(SELECTORS.SELECTBOX).forEach((function(box){box.checked&&(sellist.length>0&&(sellist+=","),sellist+=box.getAttribute("value"))})),link.setAttribute("href",baseurl+"&items="+sellist)};_exports.collectSelection=collectSelection})); //# sourceMappingURL=delselected.min.js.map \ No newline at end of file diff --git a/amd/build/delselected.min.js.map b/amd/build/delselected.min.js.map index 4cfa41c3..0b68088b 100644 --- a/amd/build/delselected.min.js.map +++ b/amd/build/delselected.min.js.map @@ -1 +1 @@ -{"version":3,"file":"delselected.min.js","sources":["../src/delselected.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 * TODO describe module delselected\n *\n * @module mod_scheduler/delselected\n * @copyright 2024 ISB Bayern\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Selectors used by the module.\n */\nexport const SELECTORS = {\n DELACTION: 'div.commandbar a#delselected',\n SELECTBOX: 'table#slotmanager input.slotselect',\n};\n\n/**\n * Add event listener to the delete link.\n * @param {*} baseurl\n */\nexport const init = (baseurl) => {\n let link = document.querySelector(SELECTORS.DELACTION);\n if (link !== null) {\n link.addEventListener('click', function() {\n collect_selection(link, baseurl);\n });\n }\n};\n\n/**\n * Copy the selected boxes into an input parameter of the respective form\n *\n * @param {String} link\n * @param {String} baseurl\n */\nexport const collect_selection = (link, baseurl) => {\n let sellist = '';\n document.querySelectorAll(SELECTORS.SELECTBOX).forEach(function(box) {\n if (box.checked) {\n if (sellist.length > 0) {\n sellist += ',';\n }\n sellist += box.getAttribute('value');\n }\n });\n link.setAttribute('href', baseurl + '&items=' + sellist);\n};\n"],"names":["SELECTORS","DELACTION","SELECTBOX","baseurl","link","document","querySelector","addEventListener","collect_selection","sellist","querySelectorAll","forEach","box","checked","length","getAttribute","setAttribute"],"mappings":";;;;;;;;MA0BaA,UAAY,CACrBC,UAAW,+BACXC,UAAW,iFAOMC,cACbC,KAAOC,SAASC,cAAcN,UAAUC,WAC/B,OAATG,MACAA,KAAKG,iBAAiB,SAAS,WAC3BC,kBAAkBJ,KAAMD,mBAWvBK,kBAAoB,CAACJ,KAAMD,eAChCM,QAAU,GACdJ,SAASK,iBAAiBV,UAAUE,WAAWS,SAAQ,SAASC,KACxDA,IAAIC,UACAJ,QAAQK,OAAS,IACjBL,SAAW,KAEfA,SAAWG,IAAIG,aAAa,aAGpCX,KAAKY,aAAa,OAAQb,QAAU,UAAYM"} \ No newline at end of file +{"version":3,"file":"delselected.min.js","sources":["../src/delselected.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 * TODO describe module delselected\n *\n * @module mod_scheduler/delselected\n * @copyright 2024 ISB Bayern\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Selectors used by the module.\n */\nexport const SELECTORS = {\n DELACTION: 'div.commandbar a#delselected',\n SELECTBOX: 'table#slotmanager input.slotselect',\n};\n\n/**\n * Add event listener to the delete link.\n * @param {*} baseurl\n */\nexport const init = (baseurl) => {\n let link = document.querySelector(SELECTORS.DELACTION);\n if (link !== null) {\n link.addEventListener('click', function() {\n collectSelection(link, baseurl);\n });\n }\n};\n\n/**\n * Copy the selected boxes into an input parameter of the respective form\n *\n * @param {String} link\n * @param {String} baseurl\n */\nexport const collectSelection = (link, baseurl) => {\n let sellist = '';\n document.querySelectorAll(SELECTORS.SELECTBOX).forEach(function(box) {\n if (box.checked) {\n if (sellist.length > 0) {\n sellist += ',';\n }\n sellist += box.getAttribute('value');\n }\n });\n link.setAttribute('href', baseurl + '&items=' + sellist);\n};\n"],"names":["SELECTORS","DELACTION","SELECTBOX","baseurl","link","document","querySelector","addEventListener","collectSelection","sellist","querySelectorAll","forEach","box","checked","length","getAttribute","setAttribute"],"mappings":";;;;;;;;MA0BaA,UAAY,CACrBC,UAAW,+BACXC,UAAW,iFAOMC,cACbC,KAAOC,SAASC,cAAcN,UAAUC,WAC/B,OAATG,MACAA,KAAKG,iBAAiB,SAAS,WAC3BC,iBAAiBJ,KAAMD,mBAWtBK,iBAAmB,CAACJ,KAAMD,eAC/BM,QAAU,GACdJ,SAASK,iBAAiBV,UAAUE,WAAWS,SAAQ,SAASC,KACxDA,IAAIC,UACAJ,QAAQK,OAAS,IACjBL,SAAW,KAEfA,SAAWG,IAAIG,aAAa,aAGpCX,KAAKY,aAAa,OAAQb,QAAU,UAAYM"} \ No newline at end of file diff --git a/amd/build/saveseen.min.js b/amd/build/saveseen.min.js index 3ac3f93a..3135ef35 100644 --- a/amd/build/saveseen.min.js +++ b/amd/build/saveseen.min.js @@ -1,3 +1,3 @@ -define("mod_scheduler/saveseen",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.save_status=_exports.init=_exports.SELECTORS=_exports.MOD=void 0;const SELECTORS={CHECKBOXES:"table#slotmanager form.studentselectform input.studentselect"};_exports.SELECTORS=SELECTORS;_exports.MOD={};const save_status=(cmid,appid,newseen,spinner)=>{const url=M.cfg.wwwroot+"/mod/scheduler/ajax.php",params="action=saveseen&id="+cmid+"&appointmentid="+appid+"&seen="+newseen+"&sesskey="+M.cfg.sesskey,xhr=new XMLHttpRequest;xhr.timeout=5e3,xhr.onloadstart=()=>{spinner.style.visibility="visible"},xhr.onload=()=>{if(!(xhr.status>=200&&xhr.status<300)){const msg={name:xhr.status+" "+xhr.statusText,message:xhr.responseText};spinner.style.visibility="hidden";throw spinner.parentNode.removeChild(spinner),new Error(JSON.stringify(msg))}setTimeout((()=>{spinner.style.visibility="hidden";spinner.parentNode.removeChild(spinner)}),250)},xhr.onerror=()=>{spinner.style.visibility="hidden";throw spinner.parentNode.removeChild(spinner),new Error("Network request failed")},xhr.open("POST",url,!0),xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"),xhr.send(params)};_exports.save_status=save_status;_exports.init=cmid=>{document.querySelectorAll(SELECTORS.CHECKBOXES).forEach((function(box){box.addEventListener("change",(function(){var div=document.createElement("div"),span=document.createElement("span");div.classList.add("spinner-border","spinner-border-sm"),span.classList.add("sr-only"),div.appendChild(span),box.closest("div").appendChild(div),save_status(cmid,box.value,box.checked,div)}))}))}})); +define("mod_scheduler/saveseen",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.saveStatus=_exports.init=_exports.SELECTORS=_exports.MOD=void 0;const SELECTORS={CHECKBOXES:"table#slotmanager form.studentselectform input.studentselect"};_exports.SELECTORS=SELECTORS;_exports.MOD={};const saveStatus=(cmid,appid,newseen,spinner)=>{const url=M.cfg.wwwroot+"/mod/scheduler/ajax.php",params="action=saveseen&id="+cmid+"&appointmentid="+appid+"&seen="+newseen+"&sesskey="+M.cfg.sesskey,xhr=new XMLHttpRequest;xhr.timeout=5e3,xhr.onloadstart=()=>{spinner.style.visibility="visible"},xhr.onload=()=>{if(!(xhr.status>=200&&xhr.status<300)){const msg={name:xhr.status+" "+xhr.statusText,message:xhr.responseText};spinner.style.visibility="hidden";throw spinner.parentNode.removeChild(spinner),new Error(JSON.stringify(msg))}setTimeout((()=>{spinner.style.visibility="hidden";spinner.parentNode.removeChild(spinner)}),250)},xhr.onerror=()=>{spinner.style.visibility="hidden";throw spinner.parentNode.removeChild(spinner),new Error("Network request failed")},xhr.open("POST",url,!0),xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"),xhr.send(params)};_exports.saveStatus=saveStatus;_exports.init=cmid=>{document.querySelectorAll(SELECTORS.CHECKBOXES).forEach((function(box){box.addEventListener("change",(function(){var div=document.createElement("div"),span=document.createElement("span");div.classList.add("spinner-border","spinner-border-sm"),span.classList.add("sr-only"),div.appendChild(span),box.closest("div").appendChild(div),saveStatus(cmid,box.value,box.checked,div)}))}))}})); //# sourceMappingURL=saveseen.min.js.map \ No newline at end of file diff --git a/amd/build/saveseen.min.js.map b/amd/build/saveseen.min.js.map index 2d8ddf3c..6747e000 100644 --- a/amd/build/saveseen.min.js.map +++ b/amd/build/saveseen.min.js.map @@ -1 +1 @@ -{"version":3,"file":"saveseen.min.js","sources":["../src/saveseen.js"],"sourcesContent":["\nexport const SELECTORS = {CHECKBOXES: 'table#slotmanager form.studentselectform input.studentselect'};\nexport const MOD = {};\n\n/**\n * Save the \"seen\" status.\n *\n * @param {Number} cmid the coursemodule id\n * @param {Number} appid the id of the relevant appointment\n * @param {Boolean} newseen\n * @param {Object} spinner The spinner icon shown while saving\n */\nexport const save_status = (cmid, appid, newseen, spinner, ) => {\n const url = M.cfg.wwwroot + '/mod/scheduler/ajax.php';\n // The request paramaters.\n const params = 'action=saveseen&id='+cmid+'&appointmentid='+appid+'&seen='+newseen+'&sesskey='+M.cfg.sesskey;\n const xhr = new XMLHttpRequest();\n\n // 5 seconds of timeout.\n xhr.timeout = 5000;\n\n xhr.onloadstart = () => {\n spinner.style.visibility = 'visible';\n };\n\n xhr.onload = () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n setTimeout(() => {\n spinner.style.visibility = 'hidden';\n const parent = spinner.parentNode;\n parent.removeChild(spinner);\n\n }, 250);\n } else {\n const msg = {\n name: xhr.status + ' ' + xhr.statusText,\n message: xhr.responseText\n };\n spinner.style.visibility = 'hidden';\n const parent = spinner.parentNode;\n parent.removeChild(spinner);\n throw new Error(JSON.stringify(msg));\n }\n };\n\n xhr.onerror = () => {\n spinner.style.visibility = 'hidden';\n const parent = spinner.parentNode;\n parent.removeChild(spinner);\n throw new Error('Network request failed');\n };\n\n xhr.open('POST', url, true);\n xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');\n xhr.send(params);\n};\n\nexport const init = (cmid) => {\n document.querySelectorAll(SELECTORS.CHECKBOXES).forEach(function(box) {\n box.addEventListener('change', function() {\n var div = document.createElement('div');\n var span = document.createElement('span');\n div.classList.add('spinner-border', 'spinner-border-sm');\n span.classList.add('sr-only');\n div.appendChild(span);\n box.closest('div').appendChild(div);\n save_status(cmid, box.value, box.checked, div);\n });\n });\n};\n"],"names":["SELECTORS","CHECKBOXES","save_status","cmid","appid","newseen","spinner","url","M","cfg","wwwroot","params","sesskey","xhr","XMLHttpRequest","timeout","onloadstart","style","visibility","onload","status","msg","name","statusText","message","responseText","parentNode","removeChild","Error","JSON","stringify","setTimeout","onerror","open","setRequestHeader","send","document","querySelectorAll","forEach","box","addEventListener","div","createElement","span","classList","add","appendChild","closest","value","checked"],"mappings":"wMACaA,UAAY,CAACC,WAAY,0GACnB,SAUNC,YAAc,CAACC,KAAMC,MAAOC,QAASC,iBACxCC,IAAMC,EAAEC,IAAIC,QAAU,0BAEtBC,OAAS,sBAAsBR,KAAK,kBAAkBC,MAAM,SAASC,QAAQ,YAAYG,EAAEC,IAAIG,QAC/FC,IAAM,IAAIC,eAGhBD,IAAIE,QAAU,IAEdF,IAAIG,YAAc,KACdV,QAAQW,MAAMC,WAAa,WAG/BL,IAAIM,OAAS,UACLN,IAAIO,QAAU,KAAOP,IAAIO,OAAS,KAO/B,OACGC,IAAM,CACRC,KAAMT,IAAIO,OAAS,IAAMP,IAAIU,WAC7BC,QAASX,IAAIY,cAEjBnB,QAAQW,MAAMC,WAAa,eACZZ,QAAQoB,WAChBC,YAAYrB,SACb,IAAIsB,MAAMC,KAAKC,UAAUT,MAd/BU,YAAW,KACPzB,QAAQW,MAAMC,WAAa,SACZZ,QAAQoB,WAChBC,YAAYrB,WAEpB,MAaXO,IAAImB,QAAU,KACV1B,QAAQW,MAAMC,WAAa,eACZZ,QAAQoB,WAChBC,YAAYrB,SACb,IAAIsB,MAAM,2BAGpBf,IAAIoB,KAAK,OAAQ1B,KAAK,GACtBM,IAAIqB,iBAAiB,eAAgB,qCACrCrB,IAAIsB,KAAKxB,wDAGQR,OACjBiC,SAASC,iBAAiBrC,UAAUC,YAAYqC,SAAQ,SAASC,KAC7DA,IAAIC,iBAAiB,UAAU,eACvBC,IAAML,SAASM,cAAc,OAC7BC,KAAOP,SAASM,cAAc,QAClCD,IAAIG,UAAUC,IAAI,iBAAkB,qBACpCF,KAAKC,UAAUC,IAAI,WACnBJ,IAAIK,YAAYH,MAChBJ,IAAIQ,QAAQ,OAAOD,YAAYL,KAC/BvC,YAAYC,KAAMoC,IAAIS,MAAOT,IAAIU,QAASR"} \ No newline at end of file +{"version":3,"file":"saveseen.min.js","sources":["../src/saveseen.js"],"sourcesContent":["\nexport const SELECTORS = {CHECKBOXES: 'table#slotmanager form.studentselectform input.studentselect'};\nexport const MOD = {};\n\n/**\n * Save the \"seen\" status.\n *\n * @param {Number} cmid the coursemodule id\n * @param {Number} appid the id of the relevant appointment\n * @param {Boolean} newseen\n * @param {Object} spinner The spinner icon shown while saving\n */\nexport const saveStatus = (cmid, appid, newseen, spinner,) => {\n const url = M.cfg.wwwroot + '/mod/scheduler/ajax.php';\n // The request paramaters.\n const params = 'action=saveseen&id=' + cmid + '&appointmentid=' + appid + '&seen=' + newseen + '&sesskey=' + M.cfg.sesskey;\n const xhr = new XMLHttpRequest();\n\n // 5 seconds of timeout.\n xhr.timeout = 5000;\n\n xhr.onloadstart = () => {\n spinner.style.visibility = 'visible';\n };\n\n xhr.onload = () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n setTimeout(() => {\n spinner.style.visibility = 'hidden';\n const parent = spinner.parentNode;\n parent.removeChild(spinner);\n\n }, 250);\n } else {\n const msg = {\n name: xhr.status + ' ' + xhr.statusText,\n message: xhr.responseText\n };\n spinner.style.visibility = 'hidden';\n const parent = spinner.parentNode;\n parent.removeChild(spinner);\n throw new Error(JSON.stringify(msg));\n }\n };\n\n xhr.onerror = () => {\n spinner.style.visibility = 'hidden';\n const parent = spinner.parentNode;\n parent.removeChild(spinner);\n throw new Error('Network request failed');\n };\n\n xhr.open('POST', url, true);\n xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');\n xhr.send(params);\n};\n\nexport const init = (cmid) => {\n document.querySelectorAll(SELECTORS.CHECKBOXES).forEach(function(box) {\n box.addEventListener('change', function() {\n var div = document.createElement('div');\n var span = document.createElement('span');\n div.classList.add('spinner-border', 'spinner-border-sm');\n span.classList.add('sr-only');\n div.appendChild(span);\n box.closest('div').appendChild(div);\n saveStatus(cmid, box.value, box.checked, div);\n });\n });\n};\n"],"names":["SELECTORS","CHECKBOXES","saveStatus","cmid","appid","newseen","spinner","url","M","cfg","wwwroot","params","sesskey","xhr","XMLHttpRequest","timeout","onloadstart","style","visibility","onload","status","msg","name","statusText","message","responseText","parentNode","removeChild","Error","JSON","stringify","setTimeout","onerror","open","setRequestHeader","send","document","querySelectorAll","forEach","box","addEventListener","div","createElement","span","classList","add","appendChild","closest","value","checked"],"mappings":"uMACaA,UAAY,CAACC,WAAY,0GACnB,SAUNC,WAAa,CAACC,KAAMC,MAAOC,QAASC,iBACvCC,IAAMC,EAAEC,IAAIC,QAAU,0BAEtBC,OAAS,sBAAwBR,KAAO,kBAAoBC,MAAQ,SAAWC,QAAU,YAAcG,EAAEC,IAAIG,QAC7GC,IAAM,IAAIC,eAGhBD,IAAIE,QAAU,IAEdF,IAAIG,YAAc,KACdV,QAAQW,MAAMC,WAAa,WAG/BL,IAAIM,OAAS,UACLN,IAAIO,QAAU,KAAOP,IAAIO,OAAS,KAO/B,OACGC,IAAM,CACRC,KAAMT,IAAIO,OAAS,IAAMP,IAAIU,WAC7BC,QAASX,IAAIY,cAEjBnB,QAAQW,MAAMC,WAAa,eACZZ,QAAQoB,WAChBC,YAAYrB,SACb,IAAIsB,MAAMC,KAAKC,UAAUT,MAd/BU,YAAW,KACPzB,QAAQW,MAAMC,WAAa,SACZZ,QAAQoB,WAChBC,YAAYrB,WAEpB,MAaXO,IAAImB,QAAU,KACV1B,QAAQW,MAAMC,WAAa,eACZZ,QAAQoB,WAChBC,YAAYrB,SACb,IAAIsB,MAAM,2BAGpBf,IAAIoB,KAAK,OAAQ1B,KAAK,GACtBM,IAAIqB,iBAAiB,eAAgB,qCACrCrB,IAAIsB,KAAKxB,sDAGQR,OACjBiC,SAASC,iBAAiBrC,UAAUC,YAAYqC,SAAQ,SAASC,KAC7DA,IAAIC,iBAAiB,UAAU,eACvBC,IAAML,SAASM,cAAc,OAC7BC,KAAOP,SAASM,cAAc,QAClCD,IAAIG,UAAUC,IAAI,iBAAkB,qBACpCF,KAAKC,UAAUC,IAAI,WACnBJ,IAAIK,YAAYH,MAChBJ,IAAIQ,QAAQ,OAAOD,YAAYL,KAC/BvC,WAAWC,KAAMoC,IAAIS,MAAOT,IAAIU,QAASR"} \ No newline at end of file diff --git a/amd/build/studentid.min.js b/amd/build/studentid.min.js index 2f95f499..5b437d9a 100644 --- a/amd/build/studentid.min.js +++ b/amd/build/studentid.min.js @@ -5,6 +5,6 @@ * @copyright 2022 University of Glasgow * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -define("mod_scheduler/studentid",["jquery","core/ajax","core/templates"],(function($,Ajax,Templates){return{processResults:function(selector,results){var users=[];return $.each(results,(function(index,user){users.push({value:user.id,label:user._label})})),users},transport:function(selector,query,success,failure){let scheduler=$(selector).attr("scheduler")||null,groupids=$(selector).attr("groupids")||null;Ajax.call([{methodname:"mod_scheduler_studentid",args:{query:query,scheduler:scheduler,groupids:groupids}}])[0].then((function(results){var promises=[],i=0;return $.each(results,(function(index,user){promises.push(Templates.render("mod_scheduler/studentid",user))})),$.when.apply($.when,promises).then((function(){var args=arguments;$.each(results,(function(index,user){user._label=args[i],i++})),success(results)}))})).fail(failure)}}})); +define("mod_scheduler/studentid",["jquery","core/ajax","core/templates"],(function($,Ajax,Templates){return{processResults:function(selector,results){var users=[];return $.each(results,(function(index,user){users.push({value:user.id,label:user._label})})),users},transport:function(selector,query,success,failure){var users;let scheduler=$(selector).attr("scheduler")||null,groupids=$(selector).attr("groupids")||null;Ajax.call([{methodname:"mod_scheduler_studentid",args:{query:query,scheduler:scheduler,groupids:groupids}}])[0].then((function(results){var promises=[];return users=results,$.each(results,(function(index,user){promises.push(Templates.render("mod_scheduler/studentid",user))})),$.when.apply($.when,promises)})).then((function(){var i=0,labels=arguments;$.each(users,(function(index,user){user._label=labels[i],i++})),success(users)})).fail(failure)}}})); //# sourceMappingURL=studentid.min.js.map \ No newline at end of file diff --git a/amd/build/studentid.min.js.map b/amd/build/studentid.min.js.map index 515c5dde..b5900e83 100644 --- a/amd/build/studentid.min.js.map +++ b/amd/build/studentid.min.js.map @@ -1 +1 @@ -{"version":3,"file":"studentid.min.js","sources":["../src/studentid.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 * Potential user selector module.\n *\n * @module mod_scheduler/studentid\n * @copyright 2022 University of Glasgow\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/templates'], function($, Ajax, Templates) {\n\n return /** @alias module:mod_scheduler/studentid */ {\n\n processResults: function(selector, results) {\n var users = [];\n $.each(results, function(index, user) {\n users.push({\n value: user.id,\n label: user._label\n });\n });\n return users;\n },\n\n transport: function(selector, query, success, failure) {\n var promise;\n\n let scheduler = $(selector).attr('scheduler') || null;\n let groupids = $(selector).attr('groupids') || null;\n promise = Ajax.call([{\n methodname: 'mod_scheduler_studentid',\n args: {\n query: query,\n scheduler: scheduler,\n groupids: groupids\n }\n }]);\n\n promise[0].then(function(results) {\n var promises = [],\n i = 0;\n\n // Render the label.\n $.each(results, function(index, user) {\n promises.push(Templates.render('mod_scheduler/studentid', user));\n });\n\n // Apply the label to the results.\n return $.when.apply($.when, promises).then(function() {\n var args = arguments;\n $.each(results, function(index, user) {\n user._label = args[i];\n i++;\n });\n success(results);\n return;\n });\n\n }).fail(failure);\n }\n\n };\n\n});"],"names":["define","$","Ajax","Templates","processResults","selector","results","users","each","index","user","push","value","id","label","_label","transport","query","success","failure","scheduler","attr","groupids","call","methodname","args","then","promises","i","render","when","apply","arguments","fail"],"mappings":";;;;;;;AAuBAA,iCAAO,CAAC,SAAU,YAAa,mBAAmB,SAASC,EAAGC,KAAMC,iBAEZ,CAEhDC,eAAgB,SAASC,SAAUC,aAC3BC,MAAQ,UACZN,EAAEO,KAAKF,SAAS,SAASG,MAAOC,MAC5BH,MAAMI,KAAK,CACPC,MAAOF,KAAKG,GACZC,MAAOJ,KAAKK,YAGbR,OAGXS,UAAW,SAASX,SAAUY,MAAOC,QAASC,aAGtCC,UAAYnB,EAAEI,UAAUgB,KAAK,cAAgB,KAC7CC,SAAWrB,EAAEI,UAAUgB,KAAK,aAAe,KACrCnB,KAAKqB,KAAK,CAAC,CACjBC,WAAY,0BACZC,KAAM,CACFR,MAAOA,MACPG,UAAWA,UACXE,SAAUA,aAIV,GAAGI,MAAK,SAASpB,aACjBqB,SAAW,GACXC,EAAI,SAGR3B,EAAEO,KAAKF,SAAS,SAASG,MAAOC,MAC5BiB,SAAShB,KAAKR,UAAU0B,OAAO,0BAA2BnB,UAIvDT,EAAE6B,KAAKC,MAAM9B,EAAE6B,KAAMH,UAAUD,MAAK,eACnCD,KAAOO,UACX/B,EAAEO,KAAKF,SAAS,SAASG,MAAOC,MAC5BA,KAAKK,OAASU,KAAKG,GACnBA,OAEJV,QAAQZ,eAIb2B,KAAKd"} \ No newline at end of file +{"version":3,"file":"studentid.min.js","sources":["../src/studentid.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 * Potential user selector module.\n *\n * @module mod_scheduler/studentid\n * @copyright 2022 University of Glasgow\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/templates'], function($, Ajax, Templates) {\n\n return /** @alias module:mod_scheduler/studentid */ {\n\n processResults: function(selector, results) {\n var users = [];\n $.each(results, function(index, user) {\n users.push({\n value: user.id,\n label: user._label\n });\n });\n return users;\n },\n\n transport: function(selector, query, success, failure) {\n var promise;\n var users;\n\n let scheduler = $(selector).attr('scheduler') || null;\n let groupids = $(selector).attr('groupids') || null;\n promise = Ajax.call([{\n methodname: 'mod_scheduler_studentid',\n args: {\n query: query,\n scheduler: scheduler,\n groupids: groupids\n }\n }]);\n\n promise[0].then(function(results) {\n var promises = [];\n\n // Remember the results so the next step can apply the rendered labels.\n users = results;\n\n // Render the label.\n $.each(results, function(index, user) {\n promises.push(Templates.render('mod_scheduler/studentid', user));\n });\n\n // Wait for all labels to render.\n return $.when.apply($.when, promises);\n }).then(function() {\n var i = 0;\n var labels = arguments;\n\n // Apply the label to the results.\n $.each(users, function(index, user) {\n user._label = labels[i];\n i++;\n });\n success(users);\n return;\n }).fail(failure);\n }\n\n };\n\n});"],"names":["define","$","Ajax","Templates","processResults","selector","results","users","each","index","user","push","value","id","label","_label","transport","query","success","failure","scheduler","attr","groupids","call","methodname","args","then","promises","render","when","apply","i","labels","arguments","fail"],"mappings":";;;;;;;AAuBAA,iCAAO,CAAC,SAAU,YAAa,mBAAmB,SAASC,EAAGC,KAAMC,iBAEZ,CAEhDC,eAAgB,SAASC,SAAUC,aAC3BC,MAAQ,UACZN,EAAEO,KAAKF,SAAS,SAASG,MAAOC,MAC5BH,MAAMI,KAAK,CACPC,MAAOF,KAAKG,GACZC,MAAOJ,KAAKK,YAGbR,OAGXS,UAAW,SAASX,SAAUY,MAAOC,QAASC,aAEtCZ,UAEAa,UAAYnB,EAAEI,UAAUgB,KAAK,cAAgB,KAC7CC,SAAWrB,EAAEI,UAAUgB,KAAK,aAAe,KACrCnB,KAAKqB,KAAK,CAAC,CACjBC,WAAY,0BACZC,KAAM,CACFR,MAAOA,MACPG,UAAWA,UACXE,SAAUA,aAIV,GAAGI,MAAK,SAASpB,aACjBqB,SAAW,UAGfpB,MAAQD,QAGRL,EAAEO,KAAKF,SAAS,SAASG,MAAOC,MAC5BiB,SAAShB,KAAKR,UAAUyB,OAAO,0BAA2BlB,UAIvDT,EAAE4B,KAAKC,MAAM7B,EAAE4B,KAAMF,aAC7BD,MAAK,eACAK,EAAI,EACJC,OAASC,UAGbhC,EAAEO,KAAKD,OAAO,SAASE,MAAOC,MAC1BA,KAAKK,OAASiB,OAAOD,GACrBA,OAEJb,QAAQX,UAET2B,KAAKf"} \ No newline at end of file diff --git a/amd/src/delselected.js b/amd/src/delselected.js index 0a1779cd..462f867d 100644 --- a/amd/src/delselected.js +++ b/amd/src/delselected.js @@ -37,7 +37,7 @@ export const init = (baseurl) => { let link = document.querySelector(SELECTORS.DELACTION); if (link !== null) { link.addEventListener('click', function() { - collect_selection(link, baseurl); + collectSelection(link, baseurl); }); } }; @@ -48,7 +48,7 @@ export const init = (baseurl) => { * @param {String} link * @param {String} baseurl */ -export const collect_selection = (link, baseurl) => { +export const collectSelection = (link, baseurl) => { let sellist = ''; document.querySelectorAll(SELECTORS.SELECTBOX).forEach(function(box) { if (box.checked) { diff --git a/amd/src/saveseen.js b/amd/src/saveseen.js index 361fc42d..18402901 100644 --- a/amd/src/saveseen.js +++ b/amd/src/saveseen.js @@ -10,10 +10,10 @@ export const MOD = {}; * @param {Boolean} newseen * @param {Object} spinner The spinner icon shown while saving */ -export const save_status = (cmid, appid, newseen, spinner, ) => { +export const saveStatus = (cmid, appid, newseen, spinner,) => { const url = M.cfg.wwwroot + '/mod/scheduler/ajax.php'; // The request paramaters. - const params = 'action=saveseen&id='+cmid+'&appointmentid='+appid+'&seen='+newseen+'&sesskey='+M.cfg.sesskey; + const params = 'action=saveseen&id=' + cmid + '&appointmentid=' + appid + '&seen=' + newseen + '&sesskey=' + M.cfg.sesskey; const xhr = new XMLHttpRequest(); // 5 seconds of timeout. @@ -64,7 +64,7 @@ export const init = (cmid) => { span.classList.add('sr-only'); div.appendChild(span); box.closest('div').appendChild(div); - save_status(cmid, box.value, box.checked, div); + saveStatus(cmid, box.value, box.checked, div); }); }); }; diff --git a/amd/src/studentid.js b/amd/src/studentid.js index 76d2dc27..74819081 100644 --- a/amd/src/studentid.js +++ b/amd/src/studentid.js @@ -38,6 +38,7 @@ define(['jquery', 'core/ajax', 'core/templates'], function($, Ajax, Templates) { transport: function(selector, query, success, failure) { var promise; + var users; let scheduler = $(selector).attr('scheduler') || null; let groupids = $(selector).attr('groupids') || null; @@ -51,25 +52,29 @@ define(['jquery', 'core/ajax', 'core/templates'], function($, Ajax, Templates) { }]); promise[0].then(function(results) { - var promises = [], - i = 0; + var promises = []; + + // Remember the results so the next step can apply the rendered labels. + users = results; // Render the label. $.each(results, function(index, user) { promises.push(Templates.render('mod_scheduler/studentid', user)); }); + // Wait for all labels to render. + return $.when.apply($.when, promises); + }).then(function() { + var i = 0; + var labels = arguments; + // Apply the label to the results. - return $.when.apply($.when, promises).then(function() { - var args = arguments; - $.each(results, function(index, user) { - user._label = args[i]; - i++; - }); - success(results); - return; + $.each(users, function(index, user) { + user._label = labels[i]; + i++; }); - + success(users); + return; }).fail(failure); } diff --git a/appointmentforms.php b/appointmentforms.php index 4bebe35a..7118e61e 100644 --- a/appointmentforms.php +++ b/appointmentforms.php @@ -24,10 +24,10 @@ defined('MOODLE_INTERNAL') || die(); -use \mod_scheduler\model\appointment; -use \mod_scheduler\permission\scheduler_permissions; +use mod_scheduler\model\appointment; +use mod_scheduler\permission\scheduler_permissions; -require_once($CFG->libdir.'/formslib.php'); +require_once($CFG->libdir . '/formslib.php'); /** * Form to edit one appointment @@ -36,8 +36,8 @@ * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_editappointment_form extends moodleform { - +class scheduler_editappointment_form extends moodleform +{ /** * @var appointment the appointment being edited */ @@ -70,9 +70,9 @@ public function __construct(appointment $appointment, $action, scheduler_permiss $this->appointment = $appointment; $this->distribute = $distribute; $this->permissions = $permissions; - $this->noteoptions = array('trusttext' => true, 'maxfiles' => -1, 'maxbytes' => 0, + $this->noteoptions = ['trusttext' => true, 'maxfiles' => -1, 'maxbytes' => 0, 'context' => $permissions->get_context(), - 'subdirs' => false, 'collapsed' => true); + 'subdirs' => false, 'collapsed' => true, ]; parent::__construct($action, null); } @@ -105,31 +105,54 @@ protected function definition() { $mform->addElement('static', 'gradedisplay', get_string('grade', 'scheduler'), $gradetext); } } + // Appointment notes (visible to teacher and/or student). if ($scheduler->uses_appointmentnotes()) { if ($this->permissions->can_edit_notes($this->appointment)) { - $mform->addElement('editor', 'appointmentnote_editor', get_string('appointmentnote', 'scheduler'), - array('rows' => 3, 'columns' => 60), $this->noteoptions); + $mform->addElement( + 'editor', + 'appointmentnote_editor', + get_string('appointmentnote', 'scheduler'), + ['rows' => 3, 'columns' => 60], + $this->noteoptions + ); $mform->setType('appointmentnote', PARAM_RAW); // Must be PARAM_RAW for rich text editor content. $candistribute = true; } else { - $note = $output->format_notes($this->appointment->appointmentnote, $this->appointment->appointmentnoteformat, - $scheduler->get_context(), 'appointmentnote', $this->appointment->id); + $note = $output->format_notes( + $this->appointment->appointmentnote, + $this->appointment->appointmentnoteformat, + $scheduler->get_context(), + 'appointmentnote', + $this->appointment->id + ); $mform->addElement('static', 'appointmentnote_display', get_string('appointmentnote', 'scheduler'), $note); } } + if ($scheduler->uses_teachernotes()) { if ($this->permissions->can_edit_notes($this->appointment)) { - $mform->addElement('editor', 'teachernote_editor', get_string('teachernote', 'scheduler'), - array('rows' => 3, 'columns' => 60), $this->noteoptions); + $mform->addElement( + 'editor', + 'teachernote_editor', + get_string('teachernote', 'scheduler'), + ['rows' => 3, 'columns' => 60], + $this->noteoptions + ); $mform->setType('teachernote', PARAM_RAW); // Must be PARAM_RAW for rich text editor content. $candistribute = true; } else { - $note = $output->format_notes($this->appointment->teachernote, $this->appointment->teachernoteformat, - $scheduler->get_context(), 'teachernote', $this->appointment->id); + $note = $output->format_notes( + $this->appointment->teachernote, + $this->appointment->teachernoteformat, + $scheduler->get_context(), + 'teachernote', + $this->appointment->id + ); $mform->addElement('static', 'teachernote_display', get_string('teachernote', 'scheduler'), $note); } } + if ($this->distribute && $candistribute) { $mform->addElement('checkbox', 'distribute', get_string('distributetoslot', 'scheduler')); $mform->setDefault('distribute', false); @@ -162,11 +185,25 @@ public function prepare_appointment_data(appointment $appointment) { $newdata = clone($appointment->get_data()); $context = $this->appointment->get_scheduler()->get_context(); - $newdata = file_prepare_standard_editor($newdata, 'appointmentnote', $this->noteoptions, $context, - 'mod_scheduler', 'appointmentnote', $this->appointment->id); - - $newdata = file_prepare_standard_editor($newdata, 'teachernote', $this->noteoptions, $context, - 'mod_scheduler', 'teachernote', $this->appointment->id); + $newdata = file_prepare_standard_editor( + $newdata, + 'appointmentnote', + $this->noteoptions, + $context, + 'mod_scheduler', + 'appointmentnote', + $this->appointment->id + ); + + $newdata = file_prepare_standard_editor( + $newdata, + 'teachernote', + $this->noteoptions, + $context, + 'mod_scheduler', + 'teachernote', + $this->appointment->id + ); return $newdata; } @@ -183,18 +220,32 @@ public function save_appointment_data(stdClass $formdata, appointment $appointme $appointment->attended = isset($formdata->attended); if ($scheduler->uses_appointmentnotes() && isset($formdata->appointmentnote_editor)) { $editor = $formdata->appointmentnote_editor; - $appointment->appointmentnote = file_save_draft_area_files($editor['itemid'], $cid, - 'mod_scheduler', 'appointmentnote', $appointment->id, - $this->noteoptions, $editor['text']); + $appointment->appointmentnote = file_save_draft_area_files( + $editor['itemid'], + $cid, + 'mod_scheduler', + 'appointmentnote', + $appointment->id, + $this->noteoptions, + $editor['text'] + ); $appointment->appointmentnoteformat = $editor['format']; } + if ($scheduler->uses_teachernotes() && isset($formdata->teachernote_editor)) { $editor = $formdata->teachernote_editor; - $appointment->teachernote = file_save_draft_area_files($editor['itemid'], $cid, - 'mod_scheduler', 'teachernote', $appointment->id, - $this->noteoptions, $editor['text']); + $appointment->teachernote = file_save_draft_area_files( + $editor['itemid'], + $cid, + 'mod_scheduler', + 'teachernote', + $appointment->id, + $this->noteoptions, + $editor['text'] + ); $appointment->teachernoteformat = $editor['format']; } + $appointment->save(); if (isset($formdata->distribute)) { $slot = $appointment->get_slot(); @@ -202,4 +253,3 @@ public function save_appointment_data(stdClass $formdata, appointment $appointme } } } - diff --git a/backup/moodle2/backup_scheduler_activity_task.class.php b/backup/moodle2/backup_scheduler_activity_task.class.php index dc259b48..f1883c57 100644 --- a/backup/moodle2/backup_scheduler_activity_task.class.php +++ b/backup/moodle2/backup_scheduler_activity_task.class.php @@ -34,8 +34,8 @@ * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class backup_scheduler_activity_task extends backup_activity_task { - +class backup_scheduler_activity_task extends backup_activity_task +{ /** * Define (add) particular settings this activity can have */ @@ -63,11 +63,11 @@ public static function encode_content_links($content) { $base = preg_quote($CFG->wwwroot, "/"); // Link to the list of schedulers. - $search = "/(".$base."\/mod\/scheduler\/index.php\?id\=)([0-9]+)/"; + $search = "/(" . $base . "\/mod\/scheduler\/index.php\?id\=)([0-9]+)/"; $content = preg_replace($search, '$@SCHEDULERINDEX*$2@$', $content); // Link to scheduler view by coursemoduleid. - $search = "/(".$base."\/mod\/scheduler\/view.php\?id\=)([0-9]+)/"; + $search = "/(" . $base . "\/mod\/scheduler\/view.php\?id\=)([0-9]+)/"; $content = preg_replace($search, '$@SCHEDULERVIEWBYID*$2@$', $content); return $content; diff --git a/backup/moodle2/backup_scheduler_stepslib.php b/backup/moodle2/backup_scheduler_stepslib.php index 3aaf6f27..6d6f938f 100644 --- a/backup/moodle2/backup_scheduler_stepslib.php +++ b/backup/moodle2/backup_scheduler_stepslib.php @@ -28,8 +28,8 @@ * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class backup_scheduler_activity_structure_step extends backup_activity_structure_step { - +class backup_scheduler_activity_structure_step extends backup_activity_structure_step +{ /** * define_structure * @@ -41,27 +41,27 @@ protected function define_structure() { $userinfo = $this->get_setting_value('userinfo'); // Define each element separated. - $scheduler = new backup_nested_element('scheduler', array('id'), array( + $scheduler = new backup_nested_element('scheduler', ['id'], [ 'name', 'intro', 'introformat', 'schedulermode', 'maxbookings', 'guardtime', 'defaultslotduration', 'allownotifications', 'staffrolename', 'scale', 'gradingstrategy', 'bookingrouping', 'usenotes', 'usebookingform', 'bookinginstructions', 'bookinginstructionsformat', 'usestudentnotes', 'requireupload', 'uploadmaxfiles', 'uploadmaxsize', - 'usecaptcha', 'timemodified')); + 'usecaptcha', 'timemodified', ]); $slots = new backup_nested_element('slots'); - $slot = new backup_nested_element('slot', array('id'), array( + $slot = new backup_nested_element('slot', ['id'], [ 'starttime', 'duration', 'teacherid', 'appointmentlocation', 'timemodified', 'notes', 'notesformat', 'exclusivity', - 'emaildate', 'hideuntil')); + 'emaildate', 'hideuntil', ]); $appointments = new backup_nested_element('appointments'); - $appointment = new backup_nested_element('appointment', array('id'), array( + $appointment = new backup_nested_element('appointment', ['id'], [ 'studentid', 'attended', 'grade', 'appointmentnote', 'appointmentnoteformat', 'teachernote', 'teachernoteformat', - 'studentnote', 'studentnoteformat', 'timecreated', 'timemodified')); + 'studentnote', 'studentnoteformat', 'timecreated', 'timemodified', ]); // Build the tree. @@ -72,13 +72,13 @@ protected function define_structure() { $appointments->add_child($appointment); // Define sources. - $scheduler->set_source_table('scheduler', array('id' => backup::VAR_ACTIVITYID)); + $scheduler->set_source_table('scheduler', ['id' => backup::VAR_ACTIVITYID]); $scheduler->annotate_ids('grouping', 'bookingrouping'); // Include appointments only if we back up user information. if ($userinfo) { - $slot->set_source_table('scheduler_slots', array('schedulerid' => backup::VAR_PARENTID)); - $appointment->set_source_table('scheduler_appointment', array('slotid' => backup::VAR_PARENTID)); + $slot->set_source_table('scheduler_slots', ['schedulerid' => backup::VAR_PARENTID]); + $appointment->set_source_table('scheduler_appointment', ['slotid' => backup::VAR_PARENTID]); } // Define id annotations. diff --git a/backup/moodle2/restore_scheduler_activity_task.class.php b/backup/moodle2/restore_scheduler_activity_task.class.php index b8a8a7ce..4220e879 100644 --- a/backup/moodle2/restore_scheduler_activity_task.class.php +++ b/backup/moodle2/restore_scheduler_activity_task.class.php @@ -34,8 +34,8 @@ * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class restore_scheduler_activity_task extends restore_activity_task { - +class restore_scheduler_activity_task extends restore_activity_task +{ /** * Define (add) particular settings this activity can have */ @@ -56,9 +56,9 @@ protected function define_my_steps() { * processed by the link decoder */ public static function define_decode_contents() { - $contents = array(); + $contents = []; - $contents[] = new restore_decode_content('scheduler', array('intro'), 'scheduler'); + $contents[] = new restore_decode_content('scheduler', ['intro'], 'scheduler'); return $contents; } @@ -68,13 +68,12 @@ public static function define_decode_contents() { * to the activity to be executed by the link decoder */ public static function define_decode_rules() { - $rules = array(); + $rules = []; $rules[] = new restore_decode_rule('SCHEDULERVIEWBYID', '/mod/scheduler/view.php?id=$1', 'course_module'); $rules[] = new restore_decode_rule('SCHEDULERINDEX', '/mod/scheduler/index.php?id=$1', 'course'); return $rules; - } /** @@ -84,7 +83,7 @@ public static function define_decode_rules() { * of {@see restore_log_rule} objects */ public static function define_restore_log_rules() { - $rules = array(); + $rules = []; $rules[] = new restore_log_rule('scheduler', 'add', 'view.php?id={course_module}', '{scheduler}'); $rules[] = new restore_log_rule('scheduler', 'update', 'view.php?id={course_module}', '{scheduler}'); @@ -104,7 +103,7 @@ public static function define_restore_log_rules() { * activity level. All them are rules not linked to any module instance (cmid = 0) */ public static function define_restore_log_rules_for_course() { - $rules = array(); + $rules = []; $rules[] = new restore_log_rule('scheduler', 'view all', 'index.php?id={course}', null); diff --git a/backup/moodle2/restore_scheduler_stepslib.php b/backup/moodle2/restore_scheduler_stepslib.php index 39332709..813a7672 100644 --- a/backup/moodle2/restore_scheduler_stepslib.php +++ b/backup/moodle2/restore_scheduler_stepslib.php @@ -28,8 +28,8 @@ * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class restore_scheduler_activity_structure_step extends restore_activity_structure_step { - +class restore_scheduler_activity_structure_step extends restore_activity_structure_step +{ /** * define_structure * @@ -37,7 +37,7 @@ class restore_scheduler_activity_structure_step extends restore_activity_structu */ protected function define_structure() { - $paths = array(); + $paths = []; $userinfo = $this->get_setting_value('userinfo'); $scheduler = new restore_path_element('scheduler', '/activity/scheduler'); @@ -47,8 +47,10 @@ protected function define_structure() { $slot = new restore_path_element('scheduler_slot', '/activity/scheduler/slots/slot'); $paths[] = $slot; - $appointment = new restore_path_element('scheduler_appointment', - '/activity/scheduler/slots/slot/appointments/appointment'); + $appointment = new restore_path_element( + 'scheduler_appointment', + '/activity/scheduler/slots/slot/appointments/appointment' + ); $paths[] = $appointment; } diff --git a/bookingform.php b/bookingform.php index 4ae84b0e..6b60a354 100644 --- a/bookingform.php +++ b/bookingform.php @@ -24,10 +24,10 @@ defined('MOODLE_INTERNAL') || die(); -use \mod_scheduler\model\slot; -use \mod_scheduler\model\appointment; +use mod_scheduler\model\slot; +use mod_scheduler\model\appointment; -require_once($CFG->libdir.'/formslib.php'); +require_once($CFG->libdir . '/formslib.php'); /** * Student-side form to book or edit an appointment in a selected slot @@ -36,8 +36,8 @@ * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_booking_form extends moodleform { - +class scheduler_booking_form extends moodleform +{ /** @var mixed */ protected $slot; /** @var mixed */ @@ -45,6 +45,8 @@ class scheduler_booking_form extends moodleform { /** @var mixed */ protected $uploadoptions; /** @var mixed */ + protected $noteoptions = []; + /** @var mixed */ protected $existing; /** @@ -70,19 +72,23 @@ protected function definition() { $mform = $this->_form; $scheduler = $this->slot->get_scheduler(); - $this->noteoptions = array('trusttext' => false, 'maxfiles' => 0, 'maxbytes' => 0, + $this->noteoptions = ['trusttext' => false, 'maxfiles' => 0, 'maxbytes' => 0, 'context' => $scheduler->get_context(), - 'collapsed' => true); + 'collapsed' => true, ]; - $this->uploadoptions = array('subdirs' => 0, + $this->uploadoptions = ['subdirs' => 0, 'maxbytes' => $scheduler->uploadmaxsize, - 'maxfiles' => $scheduler->uploadmaxfiles); + 'maxfiles' => $scheduler->uploadmaxfiles, ]; // Text field for student-supplied data. if ($scheduler->uses_studentnotes()) { - - $mform->addElement('editor', 'studentnote_editor', get_string('yourstudentnote', 'scheduler'), - array('rows' => 3, 'columns' => 60), $this->noteoptions); + $mform->addElement( + 'editor', + 'studentnote_editor', + get_string('yourstudentnote', 'scheduler'), + ['rows' => 3, 'columns' => 60], + $this->noteoptions + ); $mform->setType('studentnote', PARAM_RAW); // Must be PARAM_RAW for rich text editor content. if ($scheduler->usestudentnotes == 2) { $mform->addRule('studentnote_editor', get_string('notesrequired', 'scheduler'), 'required'); @@ -91,9 +97,13 @@ protected function definition() { // Student file upload. if ($scheduler->uses_studentfiles()) { - $mform->addElement('filemanager', 'studentfiles', - get_string('uploadstudentfiles', 'scheduler'), - null, $this->uploadoptions ); + $mform->addElement( + 'filemanager', + 'studentfiles', + get_string('uploadstudentfiles', 'scheduler'), + null, + $this->uploadoptions + ); if ($scheduler->requireupload) { $mform->addRule('studentfiles', get_string('uploadrequired', 'scheduler'), 'required'); } @@ -101,7 +111,7 @@ protected function definition() { // Captcha. if ($scheduler->uses_bookingcaptcha() && !$this->existing) { - $mform->addElement('recaptcha', 'bookingcaptcha', get_string('security_question', 'auth'), array('https' => true)); + $mform->addElement('recaptcha', 'bookingcaptcha', get_string('security_question', 'auth'), ['https' => true]); $mform->addHelpButton('bookingcaptcha', 'recaptcha', 'auth'); $mform->closeHeaderBefore('bookingcaptcha'); } @@ -170,11 +180,18 @@ public function save_booking_data(stdClass $formdata, appointment $appointment) $appointment->studentnote = $editor['text']; $appointment->studentnoteformat = $editor['format']; } + if ($scheduler->uses_studentfiles()) { - file_save_draft_area_files($formdata->studentfiles, $scheduler->context->id, - 'mod_scheduler', 'studentfiles', $appointment->id, - $this->uploadoptions); + file_save_draft_area_files( + $formdata->studentfiles, + $scheduler->context->id, + 'mod_scheduler', + 'studentfiles', + $appointment->id, + $this->uploadoptions + ); } + $appointment->save(); } } diff --git a/classes/event/appointment_base.php b/classes/event/appointment_base.php index a5f7e9c5..33317db8 100644 --- a/classes/event/appointment_base.php +++ b/classes/event/appointment_base.php @@ -30,9 +30,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -abstract class appointment_base extends \core\event\base { - - +abstract class appointment_base extends \core\event\base +{ /** * @var \mod_scheduler\model\appointment the appointment associated with this event */ @@ -45,10 +44,10 @@ abstract class appointment_base extends \core\event\base { * @return array */ protected static function base_data(\mod_scheduler\model\appointment $appointment) { - return array( + return [ 'context' => $appointment->get_parent()->get_context(), - 'objectid' => $appointment->id - ); + 'objectid' => $appointment->id, + ]; } /** @@ -76,6 +75,7 @@ public function get_appointment() { if ($this->is_restored()) { throw new \coding_exception('get_appointment() is intended for event observers only'); } + return $this->appointment; } @@ -85,7 +85,7 @@ public function get_appointment() { * @return \moodle_url */ public function get_url() { - return new \moodle_url('/mod/scheduler/view.php', array('id' => $this->contextinstanceid)); + return new \moodle_url('/mod/scheduler/view.php', ['id' => $this->contextinstanceid]); } /** diff --git a/classes/event/appointment_list_viewed.php b/classes/event/appointment_list_viewed.php index df1ff7e3..25f7ddf7 100644 --- a/classes/event/appointment_list_viewed.php +++ b/classes/event/appointment_list_viewed.php @@ -32,8 +32,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class appointment_list_viewed extends scheduler_base { - +class appointment_list_viewed extends scheduler_base +{ /** * Create this event on a given scheduler. * diff --git a/classes/event/booking_added.php b/classes/event/booking_added.php index 3fcd17b0..5283fdbf 100644 --- a/classes/event/booking_added.php +++ b/classes/event/booking_added.php @@ -33,8 +33,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class booking_added extends slot_base { - +class booking_added extends slot_base +{ /** * Create this event on a given scheduler. * @@ -71,6 +71,6 @@ public static function get_name() { */ public function get_description() { return "The user with id '$this->userid' has booked into the slot with id '{$this->objectid}'" - ." in the scheduler with course module id '$this->contextinstanceid'."; + . " in the scheduler with course module id '$this->contextinstanceid'."; } } diff --git a/classes/event/booking_form_viewed.php b/classes/event/booking_form_viewed.php index d63e4ab7..6b32c773 100644 --- a/classes/event/booking_form_viewed.php +++ b/classes/event/booking_form_viewed.php @@ -33,8 +33,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class booking_form_viewed extends scheduler_base { - +class booking_form_viewed extends scheduler_base +{ /** * Create this event on a given scheduler. * diff --git a/classes/event/booking_removed.php b/classes/event/booking_removed.php index c740fc4b..39885346 100644 --- a/classes/event/booking_removed.php +++ b/classes/event/booking_removed.php @@ -33,8 +33,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class booking_removed extends slot_base { - +class booking_removed extends slot_base +{ /** * Create this event on a given slot. * @@ -71,6 +71,6 @@ public static function get_name() { */ public function get_description() { return "The user with id '$this->userid' has removed their booking from the slot with id '{$this->objectid}'" - ." in the scheduler with course module id '$this->contextinstanceid'."; + . " in the scheduler with course module id '$this->contextinstanceid'."; } } diff --git a/classes/event/course_module_instance_list_viewed.php b/classes/event/course_module_instance_list_viewed.php index ee2376ce..0414d25b 100644 --- a/classes/event/course_module_instance_list_viewed.php +++ b/classes/event/course_module_instance_list_viewed.php @@ -31,6 +31,6 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed { +class course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed +{ } - diff --git a/classes/event/scheduler_base.php b/classes/event/scheduler_base.php index 379263f0..619148f4 100644 --- a/classes/event/scheduler_base.php +++ b/classes/event/scheduler_base.php @@ -31,8 +31,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -abstract class scheduler_base extends \core\event\base { - +abstract class scheduler_base extends \core\event\base +{ /** * @var \mod_scheduler\model\scheduler the scheduler associated with this event */ @@ -52,10 +52,10 @@ abstract class scheduler_base extends \core\event\base { * @return array */ protected static function base_data(\mod_scheduler\model\scheduler $scheduler) { - return array( + return [ 'context' => $scheduler->get_context(), - 'objectid' => $scheduler->id - ); + 'objectid' => $scheduler->id, + ]; } /** @@ -81,12 +81,14 @@ public function get_scheduler() { if ($this->is_restored()) { throw new \coding_exception('get_scheduler() is intended for event observers only'); } + if (!isset($this->scheduler)) { debugging('scheduler property should be initialised in each event', DEBUG_DEVELOPER); global $CFG; require_once($CFG->dirroot . '/mod/scheduler/locallib.php'); $this->scheduler = \mod_scheduler\model\scheduler::load_by_coursemodule_id($this->contextinstanceid); } + return $this->scheduler; } @@ -97,7 +99,7 @@ public function get_scheduler() { * @return \moodle_url */ public function get_url() { - return new \moodle_url('/mod/scheduler/view.php', array('id' => $this->contextinstanceid)); + return new \moodle_url('/mod/scheduler/view.php', ['id' => $this->contextinstanceid]); } /** diff --git a/classes/event/slot_added.php b/classes/event/slot_added.php index 6f47eb07..f291dcd7 100644 --- a/classes/event/slot_added.php +++ b/classes/event/slot_added.php @@ -33,8 +33,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class slot_added extends slot_base { - +class slot_added extends slot_base +{ /** * Create this event on a given slot. * @@ -71,6 +71,6 @@ public static function get_name() { */ public function get_description() { return "The user with id '$this->userid' created the slot with id '{$this->objectid}'" - ." in the scheduler with course module id '$this->contextinstanceid'."; + . " in the scheduler with course module id '$this->contextinstanceid'."; } } diff --git a/classes/event/slot_base.php b/classes/event/slot_base.php index 05df4c18..94056249 100644 --- a/classes/event/slot_base.php +++ b/classes/event/slot_base.php @@ -30,8 +30,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -abstract class slot_base extends \core\event\base { - +abstract class slot_base extends \core\event\base +{ /** * @var \mod_scheduler\model\slot the slot associated with this event */ @@ -44,11 +44,11 @@ abstract class slot_base extends \core\event\base { * @return array */ protected static function base_data(\mod_scheduler\model\slot $slot) { - return array( + return [ 'context' => $slot->get_scheduler()->get_context(), 'objectid' => $slot->id, - 'relateduserid' => $slot->teacherid - ); + 'relateduserid' => $slot->teacherid, + ]; } /** @@ -75,6 +75,7 @@ public function get_slot() { if ($this->is_restored()) { throw new \coding_exception('get_slot() is intended for event observers only'); } + return $this->slot; } @@ -84,7 +85,7 @@ public function get_slot() { * @return \moodle_url */ public function get_url() { - return new \moodle_url('/mod/scheduler/view.php', array('id' => $this->contextinstanceid)); + return new \moodle_url('/mod/scheduler/view.php', ['id' => $this->contextinstanceid]); } /** diff --git a/classes/event/slot_deleted.php b/classes/event/slot_deleted.php index 3b25555d..82ac8a00 100644 --- a/classes/event/slot_deleted.php +++ b/classes/event/slot_deleted.php @@ -33,8 +33,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class slot_deleted extends slot_base { - +class slot_deleted extends slot_base +{ /** * Create this event on a given slot. * @@ -44,7 +44,7 @@ class slot_deleted extends slot_base { */ public static function create_from_slot(\mod_scheduler\model\slot $slot, $action) { $data = self::base_data($slot); - $data['other'] = array('action' => $action); + $data['other'] = ['action' => $action]; $event = self::create($data); $event->set_slot($slot); return $event; @@ -74,10 +74,11 @@ public static function get_name() { */ public function get_description() { $desc = "The user with id '$this->userid' deleted the slot with id '{$this->objectid}'" - ." in the scheduler with course module id '$this->contextinstanceid'"; + . " in the scheduler with course module id '$this->contextinstanceid'"; if ($act = $this->other['action']) { $desc .= " during action '$act'"; } + $desc .= '.'; return $desc; } diff --git a/classes/external.php b/classes/external.php index 3c8ab315..7cab262f 100644 --- a/classes/external.php +++ b/classes/external.php @@ -34,7 +34,7 @@ use external_single_structure; use external_multiple_structure; -use \mod_scheduler\model\scheduler; +use mod_scheduler\model\scheduler; /** * This is the external API for this component. @@ -42,8 +42,8 @@ * @copyright 2022 University of Glasgow * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class external extends external_api { - +class external extends external_api +{ /** * studentid parameters * @@ -53,7 +53,7 @@ public static function studentid_parameters() { return new external_function_parameters([ 'query' => new external_value(PARAM_TEXT, 'The search query', VALUE_REQUIRED), 'scheduler' => new external_value(PARAM_INT, 'The scheduler id', VALUE_REQUIRED), - 'groupids' => new external_value(PARAM_INT, 'The group ids', VALUE_DEFAULT) + 'groupids' => new external_value(PARAM_INT, 'The group ids', VALUE_DEFAULT), ]); } @@ -70,12 +70,11 @@ public static function studentid_parameters() { * @throws invalid_parameter_exception * @throws restricted_context_exception */ - public static function studentid($query, $scheduler, $groupids) { $params = external_api::validate_parameters(self::studentid_parameters(), [ 'query' => $query, 'scheduler' => $scheduler, - 'groupids' => $groupids + 'groupids' => $groupids, ]); $query = $params['query']; $scheduler = $params['scheduler']; @@ -96,7 +95,6 @@ public static function studentid($query, $scheduler, $groupids) { } return $students; - } /** @@ -110,9 +108,8 @@ public static function studentid_returns() { return new external_multiple_structure( new external_single_structure([ 'id' => new external_value(PARAM_INT, 'User ID'), - 'fullname' => new external_value(PARAM_NOTAGS, 'User fullname') + 'fullname' => new external_value(PARAM_NOTAGS, 'User fullname'), ]) ); } - } diff --git a/classes/model/appointment.php b/classes/model/appointment.php index 9d61f6dd..8ad2e655 100644 --- a/classes/model/appointment.php +++ b/classes/model/appointment.php @@ -27,7 +27,7 @@ defined('MOODLE_INTERNAL') || die(); // Elements from lib.php needed for grade functionality. -require_once($CFG->dirroot.'/mod/scheduler/lib.php'); +require_once($CFG->dirroot . '/mod/scheduler/lib.php'); /** * A class for representing a scheduler appointment. @@ -35,8 +35,8 @@ * @copyright 2011 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class appointment extends mvc_child_record_model { - +class appointment extends mvc_child_record_model +{ /** * get_table * @@ -86,7 +86,6 @@ public function delete() { $fs->delete_area_files($cid, 'mod_scheduler', 'appointmentnote', $this->get_id()); $fs->delete_area_files($cid, 'mod_scheduler', 'teachernote', $this->get_id()); $fs->delete_area_files($cid, 'mod_scheduler', 'studentnote', $this->get_id()); - } /** @@ -114,7 +113,7 @@ public function get_scheduler() { public function get_student() { global $DB; if ($this->data->studentid) { - return $DB->get_record('user', array('id' => $this->data->studentid), '*', MUST_EXIST); + return $DB->get_record('user', ['id' => $this->data->studentid], '*', MUST_EXIST); } else { return null; } @@ -124,7 +123,7 @@ public function get_student() { * Has this student attended? */ public function is_attended() { - return (boolean) $this->data->attended; + return (bool) $this->data->attended; } /** @@ -145,10 +144,10 @@ public function count_studentfiles() { if (!$this->get_scheduler()->uses_studentnotes()) { return 0; } + $ctx = $this->get_scheduler()->context->id; $fs = get_file_storage(); $files = $fs->get_area_files($ctx, 'mod_scheduler', 'studentfiles', $this->id, "filename", false); return count($files); } - } diff --git a/classes/model/appointment_factory.php b/classes/model/appointment_factory.php index 0c76b2f0..3aaf70c2 100644 --- a/classes/model/appointment_factory.php +++ b/classes/model/appointment_factory.php @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . - /** * A factory class for scheduler appointments. * @@ -31,7 +30,8 @@ * @copyright 2011 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class appointment_factory extends mvc_child_model_factory { +class appointment_factory extends mvc_child_model_factory +{ /** * Create child * diff --git a/classes/model/mvc_child_list.php b/classes/model/mvc_child_list.php index cb3dfe02..c8273fcf 100644 --- a/classes/model/mvc_child_list.php +++ b/classes/model/mvc_child_list.php @@ -30,8 +30,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class mvc_child_list { - +class mvc_child_list +{ /** * @var array list of child records */ @@ -75,15 +75,19 @@ class mvc_child_list { * @param string $childfield name of parent id field in child table * @param mvc_model_factory $factory factory for child records */ - public function __construct(mvc_record_model $parent, $childtable, $childfield, - mvc_model_factory $factory) { + public function __construct( + mvc_record_model $parent, + $childtable, + $childfield, + mvc_model_factory $factory + ) { $this->children = null; $this->childcount = -1; $this->childfield = $childfield; $this->childtable = $childtable; $this->childfactory = $factory; $this->parentmodel = $parent; - $this->childrenfordeletion = array(); + $this->childrenfordeletion = []; } /** @@ -103,16 +107,17 @@ public function load() { return; // Children already loaded. } else if (!$this->get_parent_id()) { // Parent ID is invalid - not yet stored. - $this->children = array(); + $this->children = []; } else { - $this->children = array(); - $childrecs = $DB->get_records($this->childtable, array($this->childfield => $this->get_parent_id())); + $this->children = []; + $childrecs = $DB->get_records($this->childtable, [$this->childfield => $this->get_parent_id()]); $cnt = 0; foreach ($childrecs as $rec) { $app = $this->childfactory->create_child_from_record($rec, $this->parentmodel); $this->children[$rec->id] = $app; $cnt++; } + $this->childcount = $cnt; } } @@ -132,6 +137,7 @@ public function get_child_by_id($id) { break; } } + return $found; } @@ -157,7 +163,7 @@ public function get_child_count() { } else if (!$this->get_parent_id()) { return 0; // No valid parent. } else { - $cnt = $DB->count_records($this->childtable, array($this->childfield => $this->get_parent_id())); + $cnt = $DB->count_records($this->childtable, [$this->childfield => $this->get_parent_id()]); $this->childcount = $cnt; return $cnt; } @@ -172,10 +178,12 @@ public function save_children() { $child->save(); } } + foreach ($this->childrenfordeletion as $delchild) { $delchild->delete(); } - $this->childrenfordeletion = array(); + + $this->childrenfordeletion = []; } /** @@ -196,8 +204,9 @@ public function create_child() { */ public function remove_child(mvc_child_record_model $child) { if (is_null($this->children) || !in_array($child, $this->children)) { - throw new \coding_exception ('Child record to remove not found in list'); + throw new \coding_exception('Child record to remove not found in list'); } + $key = array_search($child, $this->children, true); unset($this->children[$key]); $this->childrenfordeletion[] = $child; diff --git a/classes/model/mvc_child_model_factory.php b/classes/model/mvc_child_model_factory.php index 47694629..121ff94b 100644 --- a/classes/model/mvc_child_model_factory.php +++ b/classes/model/mvc_child_model_factory.php @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . - /** * An abstract factory class for loading child records from the database. * @@ -31,8 +30,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -abstract class mvc_child_model_factory extends mvc_model_factory { - +abstract class mvc_child_model_factory extends mvc_model_factory +{ /** * @var mvc_model the parent record */ @@ -74,4 +73,3 @@ public function create_child_from_record(\stdClass $rec) { return $new; } } - diff --git a/classes/model/mvc_child_record_model.php b/classes/model/mvc_child_record_model.php index 9ffe6d7d..dccf7022 100644 --- a/classes/model/mvc_child_record_model.php +++ b/classes/model/mvc_child_record_model.php @@ -30,8 +30,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -abstract class mvc_child_record_model extends mvc_record_model { - +abstract class mvc_child_record_model extends mvc_record_model +{ /** * @var mvc_record_model the parent record */ @@ -61,6 +61,7 @@ protected function get_parent() { if (is_null($this->parentrec)) { throw new \coding_exception('parent has not been set'); } + return $this->parentrec; } @@ -72,6 +73,4 @@ protected function get_parent() { protected function get_parent_id() { return $this->get_parent()->get_id(); } - } - diff --git a/classes/model/mvc_model.php b/classes/model/mvc_model.php index eb916345..f37aefad 100644 --- a/classes/model/mvc_model.php +++ b/classes/model/mvc_model.php @@ -30,6 +30,6 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -abstract class mvc_model { - +abstract class mvc_model +{ } diff --git a/classes/model/mvc_model_factory.php b/classes/model/mvc_model_factory.php index caa1f93e..b0a6a6ab 100644 --- a/classes/model/mvc_model_factory.php +++ b/classes/model/mvc_model_factory.php @@ -30,8 +30,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -abstract class mvc_model_factory { - +abstract class mvc_model_factory +{ /** * Create a new instance of a record, with no data. * @@ -50,5 +50,4 @@ public function create_from_id($id) { $new->load($id); return $new; } - } diff --git a/classes/model/mvc_record_model.php b/classes/model/mvc_record_model.php index d726332d..a705258a 100644 --- a/classes/model/mvc_record_model.php +++ b/classes/model/mvc_record_model.php @@ -30,8 +30,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -abstract class mvc_record_model extends mvc_model { - +abstract class mvc_record_model extends mvc_model +{ /** * @var \stdClass the underlying data record */ @@ -58,7 +58,7 @@ protected function __construct() { */ public function load($id) { global $DB; - $rec = $DB->get_record($this->get_table(), array('id' => $id), '*', MUST_EXIST); + $rec = $DB->get_record($this->get_table(), ['id' => $id], '*', MUST_EXIST); $this->data = $rec; } @@ -82,12 +82,12 @@ public function load_record(\stdClass $rec) { * @return mixed */ public function __get($key) { - if (method_exists($this, 'get_'.$key)) { - return $this->{'get_'.$key}(); + if (method_exists($this, 'get_' . $key)) { + return $this->{'get_' . $key}(); } else if (property_exists($this->data, $key)) { return $this->data->{$key}; } else { - throw new \coding_exception('unknown property: '.$key); + throw new \coding_exception('unknown property: ' . $key); } } @@ -101,8 +101,8 @@ public function __get($key) { * @param mixed $value */ public function __set($key, $value) { - if (method_exists($this, 'set_'.$key)) { - $this->{'set_'.$key}($value); + if (method_exists($this, 'set_' . $key)) { + $this->{'set_' . $key}($value); } else { $this->data->{$key} = $value; } @@ -161,6 +161,7 @@ public function set_data($data, $propnames = null) { if (is_null($propnames)) { $propnames = array_keys($data); } + foreach ($propnames as $propname) { $this->{$propname} = $data[$propname]; } @@ -174,8 +175,7 @@ public function delete() { $id = $this->get_id(); if ($id != 0) { - $DB->delete_records($this->get_table(), array('id' => $id)); + $DB->delete_records($this->get_table(), ['id' => $id]); } } - } diff --git a/classes/model/scheduler.php b/classes/model/scheduler.php index 3a24cff7..a4f043bc 100644 --- a/classes/model/scheduler.php +++ b/classes/model/scheduler.php @@ -35,8 +35,8 @@ * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler extends mvc_record_model { - +class scheduler extends mvc_record_model +{ /** * @var \stdClass course module record for this scheduler */ @@ -178,8 +178,9 @@ public function get_courseid() { public function get_courserec() { global $DB; if (is_null($this->courserec)) { - $this->courserec = $DB->get_record('course', array('id' => $this->get_courseid()), '*', MUST_EXIST); + $this->courserec = $DB->get_record('course', ['id' => $this->get_courseid()], '*', MUST_EXIST); } + return $this->courserec; } @@ -192,6 +193,7 @@ public function get_context() { if ($this->context == null) { $this->context = \context_module::instance($this->get_cmid()); } + return $this->context; } @@ -215,6 +217,7 @@ public function get_name($applyfilters = false) { if ($applyfilters) { $name = format_text($name); } + return $name; } @@ -229,6 +232,7 @@ public function get_intro($applyfilters = false) { if ($applyfilters) { $intro = format_text($intro); } + return $intro; } @@ -244,6 +248,7 @@ public function get_teacher_name() { if (empty($name)) { $name = get_string('teacher', 'scheduler'); } + return $name; } @@ -293,7 +298,7 @@ public function is_individual_scheduling_enabled() { public function get_last_location($user) { global $DB; - $conds = array('schedulerid' => $this->data->id, 'teacherid' => $user->id); + $conds = ['schedulerid' => $this->data->id, 'teacherid' => $user->id]; $recs = $DB->get_records('scheduler_slots', $conds, 'timemodified DESC', 'id,appointmentlocation', 0, 1); $lastlocation = ''; if ($recs) { @@ -301,6 +306,7 @@ public function get_last_location($user) { $lastlocation = $rec->appointmentlocation; } } + return $lastlocation; } @@ -422,26 +428,28 @@ public function get_user_grades($userid = 0) { } $usersql = ''; - $params = array(); + $params = []; if ($userid) { $usersql = ' AND a.studentid = :userid'; $params['userid'] = $userid; } + $params['sid'] = $this->id; - $sql = 'SELECT a.id, a.studentid, a.grade '. - 'FROM {scheduler_slots} s JOIN {scheduler_appointment} a ON s.id = a.slotid '. - 'WHERE s.schedulerid = :sid AND a.grade IS NOT NULL'.$usersql; + $sql = 'SELECT a.id, a.studentid, a.grade ' . + 'FROM {scheduler_slots} s JOIN {scheduler_appointment} a ON s.id = a.slotid ' . + 'WHERE s.schedulerid = :sid AND a.grade IS NOT NULL' . $usersql; $grades = $DB->get_records_sql($sql, $params); - $finalgrades = array(); - $gradesums = array(); + $finalgrades = []; + $gradesums = []; foreach ($grades as $grade) { $gradesums[$grade->studentid] = new \stdClass(); $finalgrades[$grade->studentid] = new \stdClass(); $finalgrades[$grade->studentid]->userid = $grade->studentid; } + if ($this->scale > 0) { // Grading numerically. foreach ($grades as $grade) { $gradesums[$grade->studentid]->sum = @$gradesums[$grade->studentid]->sum + $grade->grade; @@ -461,11 +469,10 @@ public function get_user_grades($userid = 0) { break; } } - } else { // Grading on scales. $scaleid = - ($this->scale); $maxgrade = ''; - if ($scale = $DB->get_record('scale', array('id' => $scaleid))) { + if ($scale = $DB->get_record('scale', ['id' => $scaleid])) { $scalegrades = make_menu_from_list($scale->scale); foreach ($grades as $grade) { $gradesums[$grade->studentid]->sum = @$gradesums[$grade->studentid]->sum + $grade->grade; @@ -473,6 +480,7 @@ public function get_user_grades($userid = 0) { $gradesums[$grade->studentid]->max = (@$gradesums[$grade->studentid]->max < $grade) ? $grade->grade : @$gradesums[$grade->studentid]->max; } + $maxgrade = $scale->name; } @@ -487,8 +495,8 @@ public function get_user_grades($userid = 0) { break; } } - } + // Include any empty grades. if ($userid > 0) { if (!array_key_exists($userid, $finalgrades)) { @@ -515,8 +523,8 @@ public function get_user_grades($userid = 0) { } } } - return $finalgrades; + return $finalgrades; } /** @@ -535,6 +543,7 @@ public function get_gradebook_info($studentid) { return $item->grades[$studentid]; } } + return null; } @@ -552,19 +561,20 @@ public function get_gradebook_info($studentid) { * @param string $orderby ORDER BY fields * @return slot[] */ - protected function fetch_slots($wherecond, $havingcond, array $params, $limitfrom='', $limitnum='', $orderby='') { + protected function fetch_slots($wherecond, $havingcond, array $params, $limitfrom = '', $limitnum = '', $orderby = '') { global $DB; $select = 'SELECT s.* FROM {scheduler_slots} s'; $where = 'WHERE schedulerid = :schedulerid'; if ($wherecond) { - $where .= ' AND ('.$wherecond.')'; + $where .= ' AND (' . $wherecond . ')'; } + $params['schedulerid'] = $this->data->id; $having = ''; if ($havingcond) { - $having = 'HAVING '.$havingcond; + $having = 'HAVING ' . $havingcond; } if ($orderby) { @@ -576,12 +586,13 @@ protected function fetch_slots($wherecond, $havingcond, array $params, $limitfro $sql = "$select $where $having $order"; $slotdata = $DB->get_records_sql($sql, $params, $limitfrom, $limitnum); - $slots = array(); + $slots = []; foreach ($slotdata as $slotrecord) { $slot = new slot($this); $slot->load_record($slotrecord); $slots[] = $slot; } + return $slots; } @@ -598,8 +609,9 @@ protected function count_slots($wherecond, array $params) { $where = 'WHERE schedulerid = :schedulerid'; if ($wherecond) { - $where .= ' AND ('.$wherecond.')'; + $where .= ' AND (' . $wherecond . ')'; } + $params['schedulerid'] = $this->data->id; $sql = "$select $where"; @@ -633,16 +645,18 @@ protected function appointment_count_query() { * @return string */ protected function student_in_slot_condition(&$params, $studentid, $mustbeattended, $mustbeunattended) { - $cond = 'EXISTS (SELECT 1 FROM {scheduler_appointment} a WHERE a.studentid = :studentid'. - $this->studparno.' and a.slotid=s.id'; + $cond = 'EXISTS (SELECT 1 FROM {scheduler_appointment} a WHERE a.studentid = :studentid' . + $this->studparno . ' and a.slotid=s.id'; if ($mustbeattended) { $cond .= ' AND a.attended = 1'; } + if ($mustbeunattended) { $cond .= ' AND a.attended = 0'; } + $cond .= ')'; - $params['studentid'.$this->studparno] = $studentid; + $params['studentid' . $this->studparno] = $studentid; $this->studparno++; return $cond; } @@ -659,7 +673,7 @@ public function get_slot($id) { global $DB; - $slotdata = $DB->get_record('scheduler_slots', array('id' => $id, 'schedulerid' => $this->id), '*', MUST_EXIST); + $slotdata = $DB->get_record('scheduler_slots', ['id' => $id, 'schedulerid' => $this->id], '*', MUST_EXIST); $slot = new slot($this); $slot->load_record($slotdata); return $slot; @@ -690,8 +704,8 @@ public function get_slot_count() { * @param string $limitnum max number of entries * @return slot[] */ - public function get_all_slots($limitfrom='', $limitnum='') { - return $this->fetch_slots('', '', array(), $limitfrom, $limitnum, 's.starttime ASC'); + public function get_all_slots($limitfrom = '', $limitnum = '') { + return $this->fetch_slots('', '', [], $limitfrom, $limitnum, 's.starttime ASC'); } /** @@ -702,7 +716,7 @@ public function get_all_slots($limitfrom='', $limitnum='') { */ public function get_attended_slots_for_student($studentid) { - $params = array(); + $params = []; $wherecond = $this->student_in_slot_condition($params, $studentid, true, false); $slots = $this->fetch_slots($wherecond, '', $params, '', '', 's.starttime'); @@ -719,7 +733,7 @@ public function get_attended_slots_for_student($studentid) { */ public function get_upcoming_slots_for_student($studentid) { - $params = array(); + $params = []; $wherecond = $this->student_in_slot_condition($params, $studentid, false, true); $slots = $this->fetch_slots($wherecond, '', $params, '', '', 's.starttime'); @@ -740,22 +754,24 @@ public function get_slots_available_to_student($studentid, $includefullybooked = global $DB; - $params = array(); + $params = []; $wherecond = "(s.starttime > :cutofftime) AND (s.hideuntil < :nowhide)"; $params['nowhide'] = time(); $params['cutofftime'] = time() + $this->guardtime; - $subcond = 'NOT ('.$this->student_in_slot_condition($params, $studentid, false, false).')'; + $subcond = 'NOT (' . $this->student_in_slot_condition($params, $studentid, false, false) . ')'; if (!$includefullybooked) { - $subcond .= ' AND (s.exclusivity = 0 OR s.exclusivity > '.$this->appointment_count_query().')'; + $subcond .= ' AND (s.exclusivity = 0 OR s.exclusivity > ' . $this->appointment_count_query() . ')'; } + if ($this->groupmode != NOGROUPS) { $groups = groups_get_all_groups($this->cm->course, $studentid, $this->cm->groupingid); if ($groups) { - $groupids = array(); + $groupids = []; foreach ($groups as $group) { $groupids[] = $group->id; } - list($sqlin, $paramsin) = $DB->get_in_or_equal($groupids, SQL_PARAMS_NAMED); + + [$sqlin, $paramsin] = $DB->get_in_or_equal($groupids, SQL_PARAMS_NAMED); $subquery = "SELECT 1 FROM {groups_members} gm WHERE gm.userid = s.teacherid AND gm.groupid $sqlin"; $subcond .= " AND EXISTS ($subquery)"; $params = array_merge($params, $paramsin); @@ -763,6 +779,7 @@ public function get_slots_available_to_student($studentid, $includefullybooked = $subcond .= " AND FALSE"; } } + $wherecond .= " AND ($subcond)"; $order = 's.starttime ASC, s.duration ASC, s.teacherid'; $slots = $this->fetch_slots($wherecond, '', $params, '', '', $order); @@ -779,7 +796,7 @@ public function get_slots_available_to_student($studentid, $includefullybooked = * @return boolean */ public function has_slots_for_student($studentid, $mustbeattended, $mustbeunattended) { - $params = array(); + $params = []; $where = $this->student_in_slot_condition($params, $studentid, $mustbeattended, $mustbeunattended); $cnt = $this->count_slots($where, $params); return $cnt > 0; @@ -800,9 +817,11 @@ public function has_slots_booked_for_group($groupid, $mustbeattended = false, $m if ($mustbeattended) { $attendcond .= " AND a.attended = 1"; } + if ($mustbeunattended) { $attendcond .= " AND a.attended = 0"; } + $sql = "SELECT COUNT(*) FROM {scheduler_slots} s JOIN {scheduler_appointment} a ON a.slotid = s.id @@ -810,7 +829,7 @@ public function has_slots_booked_for_group($groupid, $mustbeattended = false, $m WHERE s.schedulerid = :schedulerid AND gm.groupid = :groupid $attendcond"; - $params = array('schedulerid' => $this->id, 'groupid' => $groupid); + $params = ['schedulerid' => $this->id, 'groupid' => $groupid]; return $DB->count_records_sql($sql, $params) > 0; } @@ -822,12 +841,13 @@ public function has_slots_booked_for_group($groupid, $mustbeattended = false, $m * @return slot[] list of unused slots */ public function get_slots_without_appointment($teacherid = 0) { - $wherecond = '('.$this->appointment_count_query().' = 0)'; - $params = array(); + $wherecond = '(' . $this->appointment_count_query() . ' = 0)'; + $params = []; if ($teacherid > 0) { - list($twhere, $params) = $this->slots_for_teacher_cond($teacherid, 0, false); + [$twhere, $params] = $this->slots_for_teacher_cond($teacherid, 0, false); $wherecond .= " AND $twhere"; } + $slots = $this->fetch_slots($wherecond, '', $params); return $slots; } @@ -841,23 +861,26 @@ public function get_slots_without_appointment($teacherid = 0) { * @return mixed SQL condition and parameters */ protected function slots_for_teacher_cond($teacherid, $groupid, $timerange) { - $wheres = array(); - $params = array(); + $wheres = []; + $params = []; if ($teacherid > 0) { $wheres[] = "teacherid = :tid"; $params['tid'] = $teacherid; } + if ($groupid > 0) { $wheres[] = "EXISTS (SELECT 1 FROM {groups_members} gm WHERE gm.groupid = :gid AND gm.userid = s.teacherid)"; $params['gid'] = $groupid; } + if ($timerange === true || $timerange == 2) { - $wheres[] = "s.starttime < ".strtotime('now'); + $wheres[] = "s.starttime < " . strtotime('now'); } else if ($timerange == 1) { - $wheres[] = "s.starttime >= ".strtotime('now'); + $wheres[] = "s.starttime >= " . strtotime('now'); } + $where = implode(" AND ", $wheres); - return array($where, $params); + return [$where, $params]; } /** @@ -869,7 +892,7 @@ protected function slots_for_teacher_cond($teacherid, $groupid, $timerange) { * @return int */ public function count_slots_for_teacher($teacherid, $groupid = 0, $inpast = false) { - list($where, $params) = $this->slots_for_teacher_cond($teacherid, $groupid, $inpast); + [$where, $params] = $this->slots_for_teacher_cond($teacherid, $groupid, $inpast); return $this->count_slots($where, $params); } @@ -884,7 +907,7 @@ public function count_slots_for_teacher($teacherid, $groupid = 0, $inpast = fals * @return slot[] */ public function get_slots_for_teacher($teacherid, $groupid = 0, $limitfrom = '', $limitnum = '', $timerange = 0) { - list($where, $params) = $this->slots_for_teacher_cond($teacherid, $groupid, $timerange); + [$where, $params] = $this->slots_for_teacher_cond($teacherid, $groupid, $timerange); return $this->fetch_slots($where, '', $params, $limitfrom, $limitnum, 's.starttime ASC, s.duration ASC, s.teacherid'); } @@ -898,7 +921,7 @@ public function get_slots_for_teacher($teacherid, $groupid = 0, $limitfrom = '', * @return slot[] */ public function get_slots_for_group($groupid, $limitfrom = '', $limitnum = '', $timerange = 0) { - list($where, $params) = $this->slots_for_teacher_cond(0, $groupid, $timerange); + [$where, $params] = $this->slots_for_teacher_cond(0, $groupid, $timerange); return $this->fetch_slots($where, '', $params, $limitfrom, $limitnum, 's.starttime ASC, s.duration ASC, s.teacherid'); } @@ -917,11 +940,17 @@ public function get_slots_for_group($groupid, $limitfrom = '', $limitnum = '', $ * @uses $DB * @return array conflicting slots */ - public function get_conflicts($starttime, $endtime, $teacher = 0, $student = 0, - $others = SCHEDULER_SELF, $excludeslot = 0) { + public function get_conflicts( + $starttime, + $endtime, + $teacher = 0, + $student = 0, + $others = SCHEDULER_SELF, + $excludeslot = 0 + ) { global $DB; - $params = array(); + $params = []; $slotscope = ($excludeslot == 0) ? "" : "sl.id != :excludeslot AND "; $params['excludeslot'] = $excludeslot; @@ -938,6 +967,7 @@ public function get_conflicts($starttime, $endtime, $teacher = 0, $student = 0, default: $schedulerscope = ''; } + if ($teacher != 0) { $teacherscope = "sl.teacherid = :teacherid AND "; $params['teacherid'] = $teacher; @@ -988,11 +1018,11 @@ public function get_conflicts($starttime, $endtime, $teacher = 0, $student = 0, public function get_slot_appointment($appointmentid) { global $DB; - $slotid = $DB->get_field('scheduler_appointment', 'slotid', array('id' => $appointmentid)); + $slotid = $DB->get_field('scheduler_appointment', 'slotid', ['id' => $appointmentid]); $slot = $this->get_slot($slotid); $app = $slot->get_appointment($appointmentid); - return array($slot, $app); + return [$slot, $app]; } /** @@ -1011,15 +1041,15 @@ public function get_appointments_for_student($studentid) { AND s.id = a.slotid AND a.studentid = :studid ORDER BY s.starttime"; - $params = array('schedulerid' => $this->id, 'studid' => $studentid); + $params = ['schedulerid' => $this->id, 'studid' => $studentid]; $slotrecs = $DB->get_records_sql($sql, $params); - $appointments = array(); + $appointments = []; foreach ($slotrecs as $rec) { $slot = new slot($this); $slot->load_record($rec); - $appointrec = $DB->get_record('scheduler_appointment', array('id' => $rec->appointmentid), '*', MUST_EXIST); + $appointrec = $DB->get_record('scheduler_appointment', ['id' => $rec->appointmentid], '*', MUST_EXIST); $appointment = new appointment($slot); $appointment->load_record($appointrec); $appointments[] = $appointment; @@ -1049,17 +1079,19 @@ public function count_bookable_appointments($studentid, $includechangeable = tru // Find how many slots have already been booked. $sql = 'SELECT COUNT(*) FROM {scheduler_slots} s' - .' JOIN {scheduler_appointment} a ON s.id = a.slotid' - .' WHERE s.schedulerid = :schedulerid AND a.studentid=:studentid'; + . ' JOIN {scheduler_appointment} a ON s.id = a.slotid' + . ' WHERE s.schedulerid = :schedulerid AND a.studentid=:studentid'; if ($this->schedulermode == 'onetime') { if ($includechangeable) { $sql .= ' AND s.starttime <= :cutofftime'; } + $sql .= ' AND a.attended = 0'; } else if ($includechangeable) { $sql .= ' AND (s.starttime <= :cutofftime OR a.attended = 1)'; } - $params = array('schedulerid' => $this->id, 'studentid' => $studentid, 'cutofftime' => time() + $this->guardtime); + + $params = ['schedulerid' => $this->id, 'studentid' => $studentid, 'cutofftime' => time() + $this->guardtime]; $booked = $DB->count_records_sql($sql, $params); $allowed = $this->maxbookings; @@ -1071,7 +1103,6 @@ public function count_bookable_appointments($studentid, $includechangeable = tru } else { return $allowed - $booked; } - } /** @@ -1085,7 +1116,7 @@ public function get_teachers() { FROM {scheduler_slots} s, {user} u WHERE s.teacherid = u.id AND schedulerid = ?"; - $teachers = $DB->get_records_sql($sql, array($this->id)); + $teachers = $DB->get_records_sql($sql, [$this->id]); return $teachers; } @@ -1111,14 +1142,21 @@ protected function get_available_users($capability, $groupids = 0) { $groupids = 0; } - $users = array(); + $users = []; if (is_integer($groupids)) { $users = get_enrolled_users($this->get_context(), $capability, $groupids, 'u.*', null, 0, 0, true); - } else if (is_array($groupids)) { foreach ($groupids as $groupid) { - $groupusers = get_enrolled_users($this->get_context(), 'mod/scheduler:appoint', $groupid, - 'u.*', null, 0, 0, true); + $groupusers = get_enrolled_users( + $this->get_context(), + 'mod/scheduler:appoint', + $groupid, + 'u.*', + null, + 0, + 0, + true + ); foreach ($groupusers as $user) { if (!array_key_exists($user->id, $users)) { $users[$user->id] = $user; @@ -1185,7 +1223,8 @@ public function get_students_for_scheduling($groups = '', $cutoff = 0, $onlymand if (($cutoff > 0 && count($studs) > $cutoff) || count($studs) == 0) { return count($studs); } - $schedstuds = array(); + + $schedstuds = []; foreach ($studs as $stud) { $include = false; if ($this->allows_unlimited_bookings()) { @@ -1193,10 +1232,12 @@ public function get_students_for_scheduling($groups = '', $cutoff = 0, $onlymand } else { $include = ($this->count_bookable_appointments($stud->id, false) != 0); } + if ($include) { $schedstuds[$stud->id] = $stud; } } + return $schedstuds; } @@ -1210,7 +1251,7 @@ public function get_students_for_scheduling($groups = '', $cutoff = 0, $onlymand public function delete_appointment($appointmentid) { global $DB; - if (!$oldrecord = $DB->get_record('scheduler_appointment', array('id' => $appointmentid))) { + if (!$oldrecord = $DB->get_record('scheduler_appointment', ['id' => $appointmentid])) { return; } @@ -1238,11 +1279,10 @@ public static function free_late_unused_slots() { WHERE a.studentid IS NULL AND starttime < ?"; $now = time(); - $todelete = $DB->get_records_sql($sql, array($now), 0, 1000); + $todelete = $DB->get_records_sql($sql, [$now], 0, 1000); if ($todelete) { - list($usql, $params) = $DB->get_in_or_equal(array_keys($todelete)); + [$usql, $params] = $DB->get_in_or_equal(array_keys($todelete)); $DB->delete_records_select('scheduler_slots', " id $usql ", $params); } } - } diff --git a/classes/model/slot.php b/classes/model/slot.php index 1c68c069..c8af7473 100644 --- a/classes/model/slot.php +++ b/classes/model/slot.php @@ -30,8 +30,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class slot extends mvc_child_record_model { - +class slot extends mvc_child_record_model +{ /** * @var mvc_child_list list of appointments in this slot */ @@ -57,8 +57,12 @@ public function __construct(scheduler $scheduler) { $this->data->id = 0; $this->set_parent($scheduler); $this->data->schedulerid = $scheduler->get_id(); - $this->appointments = new mvc_child_list($this, 'scheduler_appointment', 'slotid', - new appointment_factory($this)); + $this->appointments = new mvc_child_list( + $this, + 'scheduler_appointment', + 'slotid', + new appointment_factory($this) + ); } /** @@ -95,16 +99,19 @@ public function distribute_appointment_data(appointment $template) { if ($scheduler->uses_grades()) { $appointment->grade = $template->grade; } + if ($scheduler->uses_appointmentnotes()) { $appointment->appointmentnote = $template->appointmentnote; $appointment->appointmentnoteformat = $template->appointmentnoteformat; $this->distribute_file_area('appointmentnote', $template->id, $appointment->id); } + if ($scheduler->uses_teachernotes()) { $appointment->teachernote = $template->teachernote; $appointment->teachernoteformat = $template->teachernoteformat; $this->distribute_file_area('teachernote', $template->id, $appointment->id); } + $appointment->save(); } } @@ -136,7 +143,7 @@ private function distribute_file_area($area, $sourceid, $targetid) { // Copy files from the source to the target. $files = $fs->get_area_files($ctxid, $component, $area, $sourceid); foreach ($files as $f) { - $fs->create_file_from_storedfile(array('itemid' => $targetid), $f); + $fs->create_file_from_storedfile(['itemid' => $targetid], $f); } } @@ -157,7 +164,7 @@ public function get_scheduler() { public function get_teacher() { global $DB; if ($this->data->teacherid) { - return $DB->get_record('user', array('id' => $this->data->teacherid), '*', MUST_EXIST); + return $DB->get_record('user', ['id' => $this->data->teacherid], '*', MUST_EXIST); } else { return new \stdClass(); } @@ -191,7 +198,7 @@ public function is_in_bookable_period() { * @return boolean */ public function is_groupslot() { - return (boolean) !($this->data->exclusivity == 1); + return (bool) !($this->data->exclusivity == 1); } @@ -218,6 +225,7 @@ public function get_student_appointment($studentid) { break; } } + return $studapp; } @@ -232,6 +240,7 @@ public function is_attended() { foreach ($this->appointments->get_children() as $app) { $isattended = $isattended || $app->attended; } + return $isattended; } @@ -246,6 +255,7 @@ public function is_booked_by_student($studentid) { foreach ($this->get_appointments() as $appointment) { $result = $result || $appointment->studentid == $studentid; } + return $result; } @@ -262,6 +272,7 @@ public function count_remaining_appointments() { if ($rem < 0) { $rem = 0; } + return $rem; } } @@ -291,6 +302,7 @@ public function get_appointments($userfilter = null) { } } } + return array_values($apps); } @@ -364,8 +376,8 @@ private function get_student_eventtype() { */ private function clear_calendar() { global $DB; - $DB->delete_records('event', array('eventtype' => $this->get_teacher_eventtype())); - $DB->delete_records('event', array('eventtype' => $this->get_student_eventtype())); + $DB->delete_records('event', ['eventtype' => $this->get_teacher_eventtype()]); + $DB->delete_records('event', ['eventtype' => $this->get_student_eventtype()]); } /** @@ -381,16 +393,16 @@ private function update_calendar() { $myappointments = $this->appointments->get_children(); - $studentids = array(); + $studentids = []; foreach ($myappointments as $appointment) { if (!$appointment->is_attended()) { $studentids[] = $appointment->studentid; } } - $teacher = $DB->get_record('user', array('id' => $this->teacherid)); + $teacher = $DB->get_record('user', ['id' => $this->teacherid]); $students = $DB->get_records_list('user', 'id', $studentids); - $studentnames = array(); + $studentnames = []; foreach ($students as $student) { $studentnames[] = fullname($student); } @@ -403,7 +415,7 @@ private function update_calendar() { $baseevent = new \stdClass(); $baseevent->description = "$schedulername

" - .format_module_intro('scheduler', $scheduler, $scheduler->get_cmid(), false); + . format_module_intro('scheduler', $scheduler, $scheduler->get_cmid(), false); $baseevent->format = FORMAT_HTML; $baseevent->modulename = 'scheduler'; $baseevent->courseid = 0; @@ -415,29 +427,30 @@ private function update_calendar() { // Update student events. $studentevent = clone($baseevent); - $studenteventname = get_string('meetingwith', 'scheduler').' '.$scheduler->get_teacher_name().', '.fullname($teacher); + $studenteventname = get_string('meetingwith', 'scheduler') . ' ' . $scheduler->get_teacher_name() . ', ' . + fullname($teacher); $studentevent->name = shorten_text($studenteventname, 200); - $this->update_calendar_events( $this->get_student_eventtype(), $studentids, $studentevent); + $this->update_calendar_events($this->get_student_eventtype(), $studentids, $studentevent); // Update teacher events. - $teacherids = array(); + $teacherids = []; $teacherevent = clone($baseevent); if (count($studentids) > 0) { $teacherids[] = $teacher->id; if (count($studentids) > 1) { - $teachereventname = get_string('meetingwithplural', 'scheduler').' '. - get_string('students', 'scheduler').', '.implode(', ', $studentnames); + $teachereventname = get_string('meetingwithplural', 'scheduler') . ' ' . + get_string('students', 'scheduler') . ', ' . implode(', ', $studentnames); } else { - $teachereventname = get_string('meetingwith', 'scheduler').' '. - get_string('student', 'scheduler').', '.$studentnames[0]; + $teachereventname = get_string('meetingwith', 'scheduler') . ' ' . + get_string('student', 'scheduler') . ', ' . $studentnames[0]; } + $teacherevent->name = shorten_text($teachereventname, 200); } - $this->update_calendar_events( $this->get_teacher_eventtype(), $teacherids, $teacherevent); - + $this->update_calendar_events($this->get_teacher_eventtype(), $teacherids, $teacherevent); } /** @@ -450,13 +463,13 @@ private function update_calendar() { private function update_calendar_events($eventtype, array $userids, \stdClass $eventdata) { global $CFG, $DB; - require_once($CFG->dirroot.'/calendar/lib.php'); + require_once($CFG->dirroot . '/calendar/lib.php'); $eventdata->eventtype = $eventtype; - $existingevents = $DB->get_records('event', array('modulename' => 'scheduler', 'eventtype' => $eventtype)); - $handledevents = array(); - $handledusers = array(); + $existingevents = $DB->get_records('event', ['modulename' => 'scheduler', 'eventtype' => $eventtype]); + $handledevents = []; + $handledusers = []; // Update existing calendar events. foreach ($existingevents as $eventid => $existingdata) { @@ -485,9 +498,5 @@ private function update_calendar_events($eventtype, array $userids, \stdClass $e $calendarevent->delete(); } } - } - - } - diff --git a/classes/model/slot_factory.php b/classes/model/slot_factory.php index 2c79fbf7..376f0144 100644 --- a/classes/model/slot_factory.php +++ b/classes/model/slot_factory.php @@ -30,7 +30,8 @@ * @copyright 2011 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class slot_factory extends mvc_child_model_factory { +class slot_factory extends mvc_child_model_factory +{ /** * Create child * diff --git a/classes/output/thumbsdown_icon.php b/classes/output/thumbsdown_icon.php new file mode 100644 index 00000000..48c25552 --- /dev/null +++ b/classes/output/thumbsdown_icon.php @@ -0,0 +1,151 @@ +. + +namespace mod_scheduler\output; + +use core\output\renderable; +use core\output\renderer_base; +use core\output\templatable; + +/** + * Class thumbsdown_icon + * + * @package mod_scheduler + * @copyright 2025 Luca Bösch + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class thumbsdown_icon extends \core\output\pix_icon implements renderable, templatable { + /** + * @var string The icon name + */ + public $pix; + + /** + * @var string The component the icon belongs to. + */ + public $component; + + /** + * @var array An array of attributes to use on the icon + */ + public $attributes = []; + + /** + * Constructor + * + * @param string $pix short icon name + * @param string $alt The alt text to use for the icon + * @param string $component component name + * @param null|array $attributes html attributes + */ + public function __construct( + $pix, + $alt, + $component = 'moodle', + ?array $attributes = null, + ) { + global $PAGE; + + $this->pix = $pix; + $this->component = $component; + $this->attributes = (array)$attributes; + + if (empty($this->attributes['class'])) { + $this->attributes['class'] = ''; + } + + // Set an additional class for big icons so that they can be styled properly. + if (substr($pix, 0, 2) === 'b/') { + $this->attributes['class'] .= ' iconsize-big'; + } + + // If the alt is empty, don't place it in the attributes, otherwise it will override parent alt text. + if (!is_null($alt)) { + $this->attributes['alt'] = $alt; + + // If there is no title, set it to the attribute. + if (!isset($this->attributes['title'])) { + $this->attributes['title'] = $this->attributes['alt']; + } + } else { + unset($this->attributes['alt']); + } + + if (empty($this->attributes['title'])) { + // Remove the title attribute if empty, we probably want to use the parent node's title + // and some browsers might overwrite it with an empty title. + unset($this->attributes['title']); + } + + // Hide icons from screen readers that have no alt. + if (empty($this->attributes['alt'])) { + $this->attributes['aria-hidden'] = 'true'; + } + } + + /** + * Export this data so it can be used as the context for a mustache template. + * + * @param renderer_base $output Used to do a final render of any components that need to be rendered for export. + * @return array + */ + public function export_for_template(renderer_base $output) { + $attributes = $this->attributes; + $extraclasses = ''; + + foreach ($attributes as $key => $item) { + if ($key == 'class') { + $extraclasses = $item; + unset($attributes[$key]); + break; + } + } + + $attributes['src'] = $output->image_url($this->pix, $this->component)->out(false); + $templatecontext = []; + foreach ($attributes as $name => $value) { + $templatecontext[] = ['name' => $name, 'value' => $value]; + } + $title = isset($attributes['title']) ? $attributes['title'] : ''; + if (empty($title)) { + $title = isset($attributes['alt']) ? $attributes['alt'] : ''; + } + $data = [ + 'attributes' => $templatecontext, + 'extraclasses' => $extraclasses, + ]; + + return $data; + } + + /** + * Much simpler version of export that will produce the data required to render this pix with the + * pix helper in a mustache tag. + * + * @return array + */ + public function export_for_pix() { + $title = isset($this->attributes['title']) ? $this->attributes['title'] : ''; + if (empty($title)) { + $title = isset($this->attributes['alt']) ? $this->attributes['alt'] : ''; + } + return [ + 'key' => $this->pix, + 'component' => $this->component, + 'title' => (string) $title, + ]; + } +} diff --git a/classes/permission/permissions_manager.php b/classes/permission/permissions_manager.php index ce0be45c..b371f97a 100644 --- a/classes/permission/permissions_manager.php +++ b/classes/permission/permissions_manager.php @@ -30,8 +30,8 @@ * @copyright 2019 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -abstract class permissions_manager { - +abstract class permissions_manager +{ /** @var int */ protected $userid; /** @var \context */ @@ -54,7 +54,7 @@ protected function __construct($pluginname, \context $context, $userid) { $this->context = $context; $this->prefix = str_replace('_', '/', $pluginname) . ':'; - $this->caps = array(); + $this->caps = []; } /** @@ -86,6 +86,7 @@ protected function has_any_capability(array $caps) { return true; } } + return false; } diff --git a/classes/permission/scheduler_permissions.php b/classes/permission/scheduler_permissions.php index b80f1043..63950e53 100644 --- a/classes/permission/scheduler_permissions.php +++ b/classes/permission/scheduler_permissions.php @@ -30,8 +30,8 @@ * @copyright 2019 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_permissions extends permissions_manager { - +class scheduler_permissions extends permissions_manager +{ /** * scheduler_permissions constructor. * @@ -160,5 +160,4 @@ public function can_edit_notes(\mod_scheduler\model\appointment $app) { return $this->userid == $app->get_slot()->teacherid; } } - } diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index 490de14f..7014d709 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -25,31 +25,30 @@ namespace mod_scheduler\privacy; use core_privacy\local\metadata\collection; +use core_privacy\local\metadata\provider as metadata_provider; use core_privacy\local\request\approved_contextlist; use core_privacy\local\request\approved_userlist; +use core_privacy\local\request\content_writer; use core_privacy\local\request\contextlist; -use core_privacy\local\request\userlist; +use core_privacy\local\request\core_userlist_provider; use core_privacy\local\request\helper; -use core_privacy\local\request\content_writer; +use core_privacy\local\request\plugin\provider as plugin_provider; use core_privacy\local\request\transform; +use core_privacy\local\request\userlist; use core_privacy\local\request\writer; /** * Implementation of the privacy subsystem plugin provider for the scheduler activity module. + * This plugin stores personal data and provides the related privacy operations. * * @package mod_scheduler * @copyright 2018 Henning Bostelmann * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class provider implements - // This plugin stores personal data. - \core_privacy\local\metadata\provider, - - // This plugin is a core_user_data_provider. - \core_privacy\local\request\plugin\provider, - - \core_privacy\local\request\core_userlist_provider { - + core_userlist_provider, + metadata_provider, + plugin_provider { /** @var mixed */ private static $renderer; @@ -59,7 +58,7 @@ class provider implements * @param collection $collection a reference to the collection to use to store the metadata. * @return collection the updated collection of metadata items. */ - public static function get_metadata(collection $collection) : collection { + public static function get_metadata(collection $collection): collection { $collection->add_database_table( 'scheduler_slots', [ @@ -69,7 +68,7 @@ public static function get_metadata(collection $collection) : collection { 'appointmentlocation' => 'privacy:metadata:scheduler_slots:appointmentlocation', 'notes' => 'privacy:metadata:scheduler_slots:notes', 'notesformat' => 'privacy:metadata:scheduler_slots:notesformat', - 'exclusivity' => 'privacy:metadata:scheduler_slots:exclusivity' + 'exclusivity' => 'privacy:metadata:scheduler_slots:exclusivity', // The fields "timemodified", "emaildate" and "hideuntil" do not contain personal data. ], 'privacy:metadata:scheduler_slots' @@ -85,7 +84,7 @@ public static function get_metadata(collection $collection) : collection { 'teachernote' => 'privacy:metadata:scheduler_appointment:teachernote', 'teachernoteformat' => 'privacy:metadata:scheduler_appointment:teachernoteformat', 'studentnote' => 'privacy:metadata:scheduler_appointment:studentnote', - 'studentnoteformat' => 'privacy:metadata:scheduler_appointment:studentnoteformat' + 'studentnoteformat' => 'privacy:metadata:scheduler_appointment:studentnoteformat', // The fields "timecreated" and "timemodifed" are technical only, they do not contain personal data. ], 'privacy:metadata:scheduler_appointment' @@ -103,7 +102,7 @@ public static function get_metadata(collection $collection) : collection { * @param int $userid the userid. * @return contextlist the list of contexts containing user info for the user. */ - public static function get_contexts_for_userid(int $userid) : contextlist { + public static function get_contexts_for_userid(int $userid): contextlist { $contextlist = new contextlist(); // Fetch all scheduler records for teachers. @@ -118,7 +117,7 @@ public static function get_contexts_for_userid(int $userid) : contextlist { $params = [ 'modname' => 'scheduler', 'contextlevel' => CONTEXT_MODULE, - 'userid' => $userid + 'userid' => $userid, ]; $contextlist->add_from_sql($sql, $params); @@ -136,7 +135,7 @@ public static function get_contexts_for_userid(int $userid) : contextlist { $params = [ 'modname' => 'scheduler', 'contextlevel' => CONTEXT_MODULE, - 'userid' => $userid + 'userid' => $userid, ]; $contextlist->add_from_sql($sql, $params); @@ -167,7 +166,7 @@ public static function get_users_in_context(userlist $userlist) { $params = [ 'modname' => 'scheduler', - 'cmid' => $context->instanceid + 'cmid' => $context->instanceid, ]; $userlist->add_from_sql('teacherid', $sql, $params); @@ -183,7 +182,7 @@ public static function get_users_in_context(userlist $userlist) { $params = [ 'modname' => 'scheduler', - 'cmid' => $context->instanceid + 'cmid' => $context->instanceid, ]; $userlist->add_from_sql('studentid', $sql, $params); @@ -218,7 +217,6 @@ private static function load_scheduler_for_context(\context $context) { } else { return null; } - } /** @@ -236,7 +234,7 @@ public static function export_user_data(approved_contextlist $contextlist) { $user = $contextlist->get_user(); - list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED); + [$contextsql, $contextparams] = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED); $sql = "SELECT cm.id AS cmid, s.name AS schedulername, s.id as schedulerid, cm.course AS courseid, t.id as slotid, t.teacherid, t.starttime, t.duration, t.appointmentlocation, t.notes, t.notesformat, t.exclusivity, @@ -255,7 +253,7 @@ public static function export_user_data(approved_contextlist $contextlist) { AND t.teacherid = :userid1 OR a.studentid = :userid2 ORDER BY cm.id, t.id, a.id"; $rs = $DB->get_recordset_sql($sql, $contextparams + ['contextlevel' => CONTEXT_MODULE, - 'modname' => 'scheduler', 'userid1' => $user->id, 'userid2' => $user->id]); + 'modname' => 'scheduler', 'userid1' => $user->id, 'userid2' => $user->id, ]); $context = null; $lastrow = null; @@ -274,9 +272,11 @@ public static function export_user_data(approved_contextlist $contextlist) { // Export previous slot record. self::export_slot($context, $user, $row); } + self::export_appointment($context, $scheduler, $user, $row); $lastrow = $row; } + $rs->close(); self::export_slot($context, $user, $lastrow); self::export_scheduler($context, $user); @@ -294,15 +294,23 @@ public static function export_user_data(approved_contextlist $contextlist) { * @param string $exportarea * @return string */ - private static function format_note($notetext, $noteformat, $filearea, $id, - \context $context, content_writer $wrc, $exportarea) { + private static function format_note( + $notetext, + $noteformat, + $filearea, + $id, + \context $context, + content_writer $wrc, + $exportarea + ) { $message = $notetext; if ($filearea) { $message = $wrc->rewrite_pluginfile_urls($exportarea, 'mod_scheduler', $filearea, $id, $notetext); } + $opts = (object) [ 'para' => false, - 'context' => $context + 'context' => $context, ]; $message = format_text($message, $noteformat, $opts); return $message; @@ -319,7 +327,8 @@ protected static function export_slot($context, $user, $record) { if (!$record) { return; } - $slotarea = ['slot '.$record->slotid]; + + $slotarea = ['slot ' . $record->slotid]; $wrc = writer::with_context($context); $data = [ @@ -327,8 +336,15 @@ protected static function export_slot($context, $user, $record) { 'starttime' => transform::datetime($record->starttime), 'duration' => $record->duration, 'appointmentlocation' => format_string($record->appointmentlocation), - 'notes' => self::format_note($record->notes, $record->notesformat, - 'slotnote', $record->slotid, $context, $wrc, $slotarea), + 'notes' => self::format_note( + $record->notes, + $record->notesformat, + 'slotnote', + $record->slotid, + $context, + $wrc, + $slotarea + ), 'exclusivity' => $record->exclusivity, ]; @@ -349,8 +365,9 @@ protected static function export_appointment($context, $scheduler, $user, $recor if (!$record) { return; } + $wrc = writer::with_context($context); - $apparea = ['slot '.$record->slotid, 'appointment '.$record->appointmentid]; + $apparea = ['slot ' . $record->slotid, 'appointment ' . $record->appointmentid]; $revealteachernote = ($user->id == $record->teacherid) || get_config('mod_scheduler', 'revealteachernotes'); @@ -359,14 +376,35 @@ protected static function export_appointment($context, $scheduler, $user, $recor 'studentid' => transform::user($record->studentid), 'attended' => transform::yesno($record->attended), 'grade' => self::$renderer->format_grade($scheduler, $record->grade), - 'appointmentnote' => self::format_note($record->appointmentnote, $record->appointmentnoteformat, - 'appointmentnote', $record->appointmentid, $context, $wrc, $apparea), - 'studentnote' => self::format_note($record->studentnote, $record->studentnoteformat, - '', 0, $context, $wrc, $apparea), + 'appointmentnote' => self::format_note( + $record->appointmentnote, + $record->appointmentnoteformat, + 'appointmentnote', + $record->appointmentid, + $context, + $wrc, + $apparea + ), + 'studentnote' => self::format_note( + $record->studentnote, + $record->studentnoteformat, + '', + 0, + $context, + $wrc, + $apparea + ), ]; if ($revealteachernote) { - $data['teachernote'] = self::format_note($record->teachernote, $record->teachernoteformat, - 'teachernote', $record->appointmentid, $context, $wrc, $apparea); + $data['teachernote'] = self::format_note( + $record->teachernote, + $record->teachernoteformat, + 'teachernote', + $record->appointmentid, + $context, + $wrc, + $apparea + ); } // Data about the appointment. @@ -377,6 +415,7 @@ protected static function export_appointment($context, $scheduler, $user, $recor if ($revealteachernote) { $wrc->export_area_files($apparea, 'mod_scheduler', 'teachernote', $record->appointmentid); } + $wrc->export_area_files($apparea, 'mod_scheduler', 'studentfiles', $record->appointmentid); } @@ -390,6 +429,7 @@ protected static function export_scheduler($context, $user) { if (!$context) { return; } + $contextdata = helper::get_context_data($context, $user); helper::export_context_files($context, $user); writer::with_context($context)->export_data([], $contextdata); @@ -426,7 +466,6 @@ public static function delete_data_for_user(approved_contextlist $contextlist) { $user = $contextlist->get_user(); foreach ($contextlist->get_contexts() as $context) { - if ($scheduler = self::load_scheduler_for_context($context)) { $apps = $scheduler->get_appointments_for_student($user->id); foreach ($apps as $app) { @@ -459,5 +498,4 @@ public static function delete_data_for_users(approved_userlist $userlist) { } } } - } diff --git a/classes/search/activity.php b/classes/search/activity.php index d7e41c82..e5b07cd9 100644 --- a/classes/search/activity.php +++ b/classes/search/activity.php @@ -31,5 +31,6 @@ * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class activity extends \core_search\base_activity { +class activity extends \core_search\base_activity +{ } diff --git a/classes/task/purge_unused_slots.php b/classes/task/purge_unused_slots.php index fe83dee6..167a2cb1 100644 --- a/classes/task/purge_unused_slots.php +++ b/classes/task/purge_unused_slots.php @@ -31,7 +31,8 @@ * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class purge_unused_slots extends \core\task\scheduled_task { +class purge_unused_slots extends \core\task\scheduled_task +{ /** * get_name * diff --git a/classes/task/send_reminders.php b/classes/task/send_reminders.php index 100a1b0e..5e5f9c72 100644 --- a/classes/task/send_reminders.php +++ b/classes/task/send_reminders.php @@ -26,7 +26,7 @@ defined('MOODLE_INTERNAL') || die(); -require_once(dirname(__FILE__).'/../../mailtemplatelib.php'); +require_once(dirname(__FILE__) . '/../../mailtemplatelib.php'); /** * Scheduled background task for sending automated appointment reminders @@ -35,8 +35,8 @@ * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class send_reminders extends \core\task\scheduled_task { - +class send_reminders extends \core\task\scheduled_task +{ /** * get_name * @@ -57,11 +57,11 @@ public function execute() { // Find relevant slots in all schedulers. $select = 'emaildate > 0 AND emaildate <= ? AND starttime > ?'; - $slots = $DB->get_records_select('scheduler_slots', $select, array($date, $date), 'starttime'); + $slots = $DB->get_records_select('scheduler_slots', $select, [$date, $date], 'starttime'); foreach ($slots as $slot) { // Get teacher record. - $teacher = $DB->get_record('user', array('id' => $slot->teacherid)); + $teacher = $DB->get_record('user', ['id' => $slot->teacherid]); // Get scheduler, slot and course. $scheduler = \mod_scheduler\model\scheduler::load_by_id($slot->schedulerid); @@ -76,10 +76,19 @@ public function execute() { foreach ($slotm->get_appointments() as $appointment) { $student = \core_user::get_user($appointment->studentid); \core\cron::setup_user($student, $course); - \scheduler_messenger::send_slot_notification($slotm, - 'reminder', 'reminder', $teacher, $student, $teacher, $student, $course); + \scheduler_messenger::send_slot_notification( + $slotm, + 'reminder', + 'reminder', + $teacher, + $student, + $teacher, + $student, + $course + ); } } + \core\cron::setup_user(); } } diff --git a/customlib.php b/customlib.php index 826cc8e2..3db3826a 100644 --- a/customlib.php +++ b/customlib.php @@ -39,7 +39,7 @@ */ function scheduler_get_user_fields($user, $context) { - $fields = array(); + $fields = []; if (has_capability('moodle/site:viewuseridentity', $context)) { $emailfield = new stdClass(); @@ -54,6 +54,8 @@ function scheduler_get_user_fields($user, $context) { * As an example: Uncomment the following lines in order to display the user's city and country. */ + // phpcs:disable + /* $cityfield = new stdClass(); $cityfield->title = get_string('city'); @@ -73,5 +75,7 @@ function scheduler_get_user_fields($user, $context) { } } */ + + // phpcs:enable return $fields; } diff --git a/datelist.php b/datelist.php index eb2782fd..428be5d1 100644 --- a/datelist.php +++ b/datelist.php @@ -24,14 +24,15 @@ defined('MOODLE_INTERNAL') || die(); -require_once($CFG->libdir.'/tablelib.php'); +require_once($CFG->libdir . '/tablelib.php'); $PAGE->set_docs_path('mod/scheduler/datelist'); $scope = optional_param('scope', 'activity', PARAM_TEXT); -if (!in_array($scope, array('activity', 'course', 'site'))) { +if (!in_array($scope, ['activity', 'course', 'site'])) { $scope = 'activity'; } + $teacherid = optional_param('teacherid', 0, PARAM_INT); if ($scope == 'site') { @@ -45,13 +46,16 @@ if (!has_capability('mod/scheduler:seeoverviewoutsideactivity', $context)) { $scope = 'activity'; } + if (!has_capability('mod/scheduler:canseeotherteachersbooking', $scopecontext)) { $teacherid = 0; } -$taburl = new moodle_url('/mod/scheduler/view.php', - array('id' => $scheduler->cmid, 'what' => 'datelist', 'scope' => $scope, 'teacherid' => $teacherid)); -$returnurl = new moodle_url('/mod/scheduler/view.php', array('id' => $scheduler->cmid)); +$taburl = new moodle_url( + '/mod/scheduler/view.php', + ['id' => $scheduler->cmid, 'what' => 'datelist', 'scope' => $scope, 'teacherid' => $teacherid] +); +$returnurl = new moodle_url('/mod/scheduler/view.php', ['id' => $scheduler->cmid]); $PAGE->set_url($taburl); @@ -76,26 +80,34 @@ $scopemenukey = 'scopemenuself'; if (has_capability('mod/scheduler:canseeotherteachersbooking', $scopecontext)) { $teachers = $scheduler->get_available_teachers($currentgroupid); - $teachermenu = array(); + $teachermenu = []; foreach ($teachers as $teacher) { $teachermenu[$teacher->id] = fullname($teacher); } - $select = $output->single_select($taburl, 'teacherid', $teachermenu, $teacherid, - array(0 => get_string('myself', 'scheduler')), 'teacheridform'); + + $select = $output->single_select( + $taburl, + 'teacherid', + $teachermenu, + $teacherid, + [0 => get_string('myself', 'scheduler')], + 'teacheridform' + ); echo html_writer::div(get_string('teachersmenu', 'scheduler', $select), 'dropdownmenu'); $scopemenukey = 'scopemenu'; } + if (has_capability('mod/scheduler:seeoverviewoutsideactivity', $context)) { - $scopemenu = array('activity' => get_string('thisscheduler', 'scheduler'), + $scopemenu = ['activity' => get_string('thisscheduler', 'scheduler'), 'course' => get_string('thiscourse', 'scheduler'), - 'site' => get_string('thissite', 'scheduler')); + 'site' => get_string('thissite', 'scheduler'), ]; $select = $output->single_select($taburl, 'scope', $scopemenu, $scope, null, 'scopeform'); echo html_writer::div(get_string($scopemenukey, 'scheduler', $select), 'dropdownmenu'); } // Getting date list. -$params = array(); +$params = []; $params['teacherid'] = $teacherid == 0 ? $USER->id : $teacherid; $params['courseid'] = $scheduler->courseid; $params['schedulerid'] = $scheduler->id; @@ -113,7 +125,7 @@ $sql = "SELECT a.id AS id, $studselect," . - $DB->sql_fullname('u1.firstname', 'u1.lastname')." AS studentfullname, + $DB->sql_fullname('u1.firstname', 'u1.lastname') . " AS studentfullname, a.appointmentnote, a.appointmentnoteformat, a.teachernote, @@ -142,7 +154,7 @@ a.slotid = s.id AND u1.id = a.studentid AND u2.id = s.teacherid AND - s.teacherid = :teacherid ". + s.teacherid = :teacherid " . $scopecond; $sqlcount = @@ -154,7 +166,7 @@ WHERE c.id = sc.course AND sc.id = s.schedulerid AND a.slotid = s.id AND - s.teacherid = :teacherid ". + s.teacherid = :teacherid " . $scopecond; $numrecords = $DB->count_records_sql($sqlcount, $params); @@ -163,7 +175,6 @@ $limit = 30; if ($numrecords) { - // Make the table of results. $coursestr = get_string('course', 'scheduler'); @@ -176,10 +187,10 @@ $whatresultedstr = get_string('whatresulted', 'scheduler'); $whathappenedstr = get_string('whathappened', 'scheduler'); - $tablecolumns = array('courseshort', 'schedulerid', 'starttime', 'appointmentlocation', - 'studentfullname', 'studentdepartment', 'notes', 'grade', 'appointmentnote'); - $tableheaders = array($coursestr, $schedulerstr, $whenstr, $wherestr, - $whostr, $wherefromstr, $whatstr, $whatresultedstr, $whathappenedstr); + $tablecolumns = ['courseshort', 'schedulerid', 'starttime', 'appointmentlocation', + 'studentfullname', 'studentdepartment', 'notes', 'grade', 'appointmentnote', ]; + $tableheaders = [$coursestr, $schedulerstr, $whenstr, $wherestr, + $whostr, $wherefromstr, $whatstr, $whatresultedstr, $whathappenedstr, ]; $table = new flexible_table('mod-scheduler-datelist'); $table->define_columns($tablecolumns); @@ -217,19 +228,21 @@ $results = $DB->get_records_sql($sql, $params); foreach ($results as $id => $row) { - $courseurl = new moodle_url('/course/view.php', array('id' => $row->courseid)); + $courseurl = new moodle_url('/course/view.php', ['id' => $row->courseid]); $coursedata = html_writer::link($courseurl, format_string($row->courseshort)); - $schedulerurl = new moodle_url('/mod/scheduler/view.php', array('a' => $row->schedulerid)); + $schedulerurl = new moodle_url('/mod/scheduler/view.php', ['a' => $row->schedulerid]); $schedulerdata = html_writer::link($schedulerurl, format_string($row->name)); $a = mod_scheduler_renderer::slotdatetime($row->starttime, $row->duration); $whendata = get_string('slotdatetime', 'scheduler', $a); - $whourl = new moodle_url('/mod/scheduler/view.php', - array('what' => 'viewstudent', 'a' => $row->schedulerid, 'appointmentid' => $row->id)); + $whourl = new moodle_url( + '/mod/scheduler/view.php', + ['what' => 'viewstudent', 'a' => $row->schedulerid, 'appointmentid' => $row->id] + ); $whodata = html_writer::link($whourl, $row->studentfullname); $whatdata = $output->format_notes($row->notes, $row->notesformat, $context, 'slotnote', $row->sid); $gradedata = $row->scale == 0 ? '' : $output->format_grade($row->scale, $row->grade); - $dataset = array( + $dataset = [ $coursedata, $schedulerdata, $whendata, @@ -238,9 +251,10 @@ $row->studentdepartment, $whatdata, $gradedata, - $output->format_appointment_notes($scheduler, $row) ); + $output->format_appointment_notes($scheduler, $row), ]; $table->add_data($dataset); } + $table->print_html(); echo $output->continue_button($returnurl); } else { diff --git a/db/access.php b/db/access.php index 1547f4d2..bdc72421 100644 --- a/db/access.php +++ b/db/access.php @@ -24,170 +24,168 @@ defined('MOODLE_INTERNAL') || die(); -$capabilities = array( +$capabilities = [ - 'mod/scheduler:addinstance' => array( + 'mod/scheduler:addinstance' => [ 'riskbitmask' => RISK_XSS, 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'archetypes' => array( + 'archetypes' => [ 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ), - 'clonepermissionsfrom' => 'moodle/course:manageactivities' - ), + 'manager' => CAP_ALLOW, + ], + 'clonepermissionsfrom' => 'moodle/course:manageactivities', + ], - 'mod/scheduler:appoint' => array( + 'mod/scheduler:appoint' => [ 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( + 'archetypes' => [ 'student' => CAP_ALLOW, - ) - ), + ], + ], - 'mod/scheduler:attend' => array( + 'mod/scheduler:attend' => [ 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( + 'archetypes' => [ 'teacher' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW - ) - ), + 'editingteacher' => CAP_ALLOW, + ], + ], - 'mod/scheduler:manage' => array( + 'mod/scheduler:manage' => [ 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( + 'archetypes' => [ 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, 'coursecreator' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ), + 'manager' => CAP_ALLOW, + ], + ], - 'mod/scheduler:manageallappointments' => array( + 'mod/scheduler:manageallappointments' => [ 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( + 'archetypes' => [ 'editingteacher' => CAP_ALLOW, 'coursecreator' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ), + 'manager' => CAP_ALLOW, + ], + ], - 'mod/scheduler:canscheduletootherteachers' => array( + 'mod/scheduler:canscheduletootherteachers' => [ 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( + 'archetypes' => [ 'editingteacher' => CAP_ALLOW, 'coursecreator' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ), + 'manager' => CAP_ALLOW, + ], + ], - 'mod/scheduler:canseeotherteachersbooking' => array( + 'mod/scheduler:canseeotherteachersbooking' => [ 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( + 'archetypes' => [ 'editingteacher' => CAP_ALLOW, 'coursecreator' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ), + 'manager' => CAP_ALLOW, + ], + ], - 'mod/scheduler:seeoverviewoutsideactivity' => array( + 'mod/scheduler:seeoverviewoutsideactivity' => [ 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( + 'archetypes' => [ 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, 'coursecreator' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ), + 'manager' => CAP_ALLOW, + ], + ], - 'mod/scheduler:editallattended' => array( + 'mod/scheduler:editallattended' => [ 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( + 'archetypes' => [ 'editingteacher' => CAP_ALLOW, 'coursecreator' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ), + 'manager' => CAP_ALLOW, + ], + ], - 'mod/scheduler:editallgrades' => array( + 'mod/scheduler:editallgrades' => [ 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( + 'archetypes' => [ 'editingteacher' => CAP_ALLOW, 'coursecreator' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ), + 'manager' => CAP_ALLOW, + ], + ], - 'mod/scheduler:editallnotes' => array( + 'mod/scheduler:editallnotes' => [ 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( + 'archetypes' => [ 'editingteacher' => CAP_ALLOW, 'coursecreator' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ), + 'manager' => CAP_ALLOW, + ], + ], - 'mod/scheduler:disengage' => array( + 'mod/scheduler:disengage' => [ 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( + 'archetypes' => [ 'student' => CAP_ALLOW, 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, 'coursecreator' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ), + 'manager' => CAP_ALLOW, + ], + ], - 'mod/scheduler:viewslots' => array( + 'mod/scheduler:viewslots' => [ 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( + 'archetypes' => [ 'student' => CAP_ALLOW, - ), - 'clonepermissionsfrom' => 'mod/scheduler:appoint' - ), + ], + 'clonepermissionsfrom' => 'mod/scheduler:appoint', + ], - 'mod/scheduler:viewfullslots' => array( + 'mod/scheduler:viewfullslots' => [ 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( - ) - ), + 'archetypes' => [ + ], + ], - 'mod/scheduler:seeotherstudentsbooking' => array( + 'mod/scheduler:seeotherstudentsbooking' => [ 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( + 'archetypes' => [ 'student' => CAP_ALLOW, 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, 'coursecreator' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ), + 'manager' => CAP_ALLOW, + ], + ], - 'mod/scheduler:seeotherstudentsresults' => array( + 'mod/scheduler:seeotherstudentsresults' => [ 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( + 'archetypes' => [ 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, 'coursecreator' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ) - -); - + 'manager' => CAP_ALLOW, + ], + ], +]; diff --git a/db/messages.php b/db/messages.php index 702fcf2a..a9f04b3c 100644 --- a/db/messages.php +++ b/db/messages.php @@ -24,18 +24,18 @@ defined('MOODLE_INTERNAL') || die(); -$messageproviders = array ( +$messageproviders = [ // Invitations to make a booking. - 'invitation' => array( - ), + 'invitation' => [ + ], // Notifications about bookings (to teachers or students). - 'bookingnotification' => array( - ), + 'bookingnotification' => [ + ], // Automated reminders about upcoming appointments. - 'reminder' => array( - ), + 'reminder' => [ + ], -); +]; diff --git a/db/services.php b/db/services.php index 6faa22da..0736f6e0 100644 --- a/db/services.php +++ b/db/services.php @@ -24,14 +24,14 @@ defined('MOODLE_INTERNAL') || die(); -$functions = array( +$functions = [ - 'mod_scheduler_studentid' => array( + 'mod_scheduler_studentid' => [ 'classname' => 'mod_scheduler\external', 'methodname' => 'studentid', 'description' => 'Retrieve the list of potential studentids.', 'type' => 'read', 'ajax' => true, - 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) - ), -); + 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE], + ], +]; diff --git a/db/tasks.php b/db/tasks.php index 6a7709df..6b0f092f 100644 --- a/db/tasks.php +++ b/db/tasks.php @@ -24,21 +24,21 @@ defined('MOODLE_INTERNAL') || die(); -$tasks = array( - array( +$tasks = [ + [ 'classname' => 'mod_scheduler\task\send_reminders', 'minute' => 'R', 'hour' => '*', 'day' => '*', 'dayofweek' => '*', - 'month' => '*' - ), - array( + 'month' => '*', + ], + [ 'classname' => 'mod_scheduler\task\purge_unused_slots', 'minute' => '*/5', 'hour' => '*', 'day' => '*', 'dayofweek' => '*', - 'month' => '*' - ) -); + 'month' => '*', + ], +]; diff --git a/db/upgrade.php b/db/upgrade.php index 8dbee09d..fc82aeca 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -28,9 +28,9 @@ * @param string $name name of configuration setting */ function scheduler_migrate_config_setting($name) { - $oldval = get_config('core', 'scheduler_'.$name); + $oldval = get_config('core', 'scheduler_' . $name); set_config($name, $oldval, 'mod_scheduler'); - unset_config('scheduler_'.$name); + unset_config('scheduler_' . $name); } /** @@ -48,9 +48,10 @@ function scheduler_migrate_groupmode($sid) { } else { $g = -1; } - $DB->set_field('scheduler', 'bookingrouping', $g, array('id' => $sid)); - $DB->set_field('course_modules', 'groupmode', 0, array('id' => $cm->id)); - $DB->set_field('course_modules', 'groupingid', 0, array('id' => $cm->id)); + + $DB->set_field('scheduler', 'bookingrouping', $g, ['id' => $sid]); + $DB->set_field('course_modules', 'groupmode', 0, ['id' => $cm->id]); + $DB->set_field('course_modules', 'groupingid', 0, ['id' => $cm->id]); } } @@ -66,10 +67,11 @@ function scheduler_migrate_eventtype($prefix) { foreach ($rs as $record) { $parts = explode(':', $record->eventtype, 3); if (count($parts) > 2) { - $record->eventtype = $parts[0].":".$parts[1]; + $record->eventtype = $parts[0] . ":" . $parts[1]; $DB->update_record('event', $record); } } + $rs->close(); } @@ -80,7 +82,7 @@ function scheduler_migrate_eventtype($prefix) { * @param int $oldversion version number to be migrated from * @return bool true if upgrade is successful */ -function xmldb_scheduler_upgrade($oldversion=0) { +function xmldb_scheduler_upgrade($oldversion = 0) { global $CFG, $DB; @@ -91,14 +93,21 @@ function xmldb_scheduler_upgrade($oldversion=0) { /* ******************* 2.0 upgrade line ********************** */ if ($oldversion < 2011081302) { - // Rename description field to intro, and define field introformat to be added to scheduler. $table = new xmldb_table('scheduler'); $introfield = new xmldb_field('description', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL, null, null, 'name'); $dbman->rename_field($table, $introfield, 'intro', false); - $formatfield = new xmldb_field('introformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, - XMLDB_NOTNULL, null, '0', 'intro'); + $formatfield = new xmldb_field( + 'introformat', + XMLDB_TYPE_INTEGER, + '4', + XMLDB_UNSIGNED, + XMLDB_NOTNULL, + null, + '0', + 'intro' + ); if (!$dbman->field_exists($table, $formatfield)) { $dbman->add_field($table, $formatfield); @@ -106,14 +115,19 @@ function xmldb_scheduler_upgrade($oldversion=0) { // Conditionally migrate to html format in intro. if ($CFG->texteditors !== 'textarea') { - $rs = $DB->get_recordset('scheduler', array('introformat' => FORMAT_MOODLE), - '', 'id, intro, introformat'); + $rs = $DB->get_recordset( + 'scheduler', + ['introformat' => FORMAT_MOODLE], + '', + 'id, intro, introformat' + ); foreach ($rs as $q) { $q->intro = text_to_html($q->intro, false, false, true); $q->introformat = FORMAT_HTML; $DB->update_record('scheduler', $q); upgrade_set_timeout(); } + $rs->close(); } @@ -124,18 +138,33 @@ function xmldb_scheduler_upgrade($oldversion=0) { /* ******************* 2.5 upgrade line ********************** */ if ($oldversion < 2012102903) { - // Define fields notesformat and appointmentnote in respective tables. $table = new xmldb_table('scheduler_slots'); - $formatfield = new xmldb_field('notesformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, - XMLDB_NOTNULL, null, '0', 'notes'); + $formatfield = new xmldb_field( + 'notesformat', + XMLDB_TYPE_INTEGER, + '4', + XMLDB_UNSIGNED, + XMLDB_NOTNULL, + null, + '0', + 'notes' + ); if (!$dbman->field_exists($table, $formatfield)) { $dbman->add_field($table, $formatfield); } $table = new xmldb_table('scheduler_appointment'); - $formatfield = new xmldb_field('appointmentnoteformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, - XMLDB_NOTNULL, null, '0', 'appointmentnote'); + $formatfield = new xmldb_field( + 'appointmentnoteformat', + XMLDB_TYPE_INTEGER, + '4', + XMLDB_UNSIGNED, + XMLDB_NOTNULL, + null, + '0', + 'appointmentnote' + ); if (!$dbman->field_exists($table, $formatfield)) { $dbman->add_field($table, $formatfield); } @@ -154,7 +183,6 @@ function xmldb_scheduler_upgrade($oldversion=0) { /* ******************* 2.7 upgrade line ********************** */ if ($oldversion < 2014071300) { - // Define field teacher to be dropped from scheduler. $table = new xmldb_table('scheduler'); $field = new xmldb_field('teacher'); @@ -198,7 +226,7 @@ function xmldb_scheduler_upgrade($oldversion=0) { // Define index schedulerid-teacherid (not unique) to be added to scheduler_slots. $table = new xmldb_table('scheduler_slots'); - $index = new xmldb_index('schedulerid-teacherid', XMLDB_INDEX_NOTUNIQUE, array('schedulerid', 'teacherid')); + $index = new xmldb_index('schedulerid-teacherid', XMLDB_INDEX_NOTUNIQUE, ['schedulerid', 'teacherid']); // Conditionally launch add index schedulerid-teacherid. if (!$dbman->index_exists($table, $index)) { @@ -207,7 +235,7 @@ function xmldb_scheduler_upgrade($oldversion=0) { // Define index slotid (not unique) to be added to scheduler_appointment. $table = new xmldb_table('scheduler_appointment'); - $index = new xmldb_index('slotid', XMLDB_INDEX_NOTUNIQUE, array('slotid')); + $index = new xmldb_index('slotid', XMLDB_INDEX_NOTUNIQUE, ['slotid']); // Conditionally add index slotid. if (!$dbman->index_exists($table, $index)) { @@ -216,7 +244,7 @@ function xmldb_scheduler_upgrade($oldversion=0) { // Define index studentid (not unique) to be added to scheduler_appointment. $table = new xmldb_table('scheduler_appointment'); - $index = new xmldb_index('studentid', XMLDB_INDEX_NOTUNIQUE, array('studentid')); + $index = new xmldb_index('studentid', XMLDB_INDEX_NOTUNIQUE, ['studentid']); // Conditionally add index studentid. if (!$dbman->index_exists($table, $index)) { @@ -225,7 +253,7 @@ function xmldb_scheduler_upgrade($oldversion=0) { // Convert old calendar events. $sql = 'UPDATE {event} SET modulename = ? WHERE eventtype LIKE ? OR eventtype LIKE ?'; - $DB->execute($sql, array('scheduler', 'SSsup:%', 'SSstu:%')); + $DB->execute($sql, ['scheduler', 'SSsup:%', 'SSstu:%']); // Savepoint reached. upgrade_mod_savepoint(true, 2014071300, 'scheduler'); @@ -234,7 +262,6 @@ function xmldb_scheduler_upgrade($oldversion=0) { /* ******************* 2.9 upgrade line ********************** */ if ($oldversion < 2015050400) { - // Migrate config settings to config_plugins table. scheduler_migrate_config_setting('allteachersgrading'); scheduler_migrate_config_setting('showemailplain'); @@ -246,7 +273,6 @@ function xmldb_scheduler_upgrade($oldversion=0) { } if ($oldversion < 2015062601) { - // Define field bookingrouping to be added to scheduler. $table = new xmldb_table('scheduler'); $field = new xmldb_field('bookingrouping', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '-1', 'gradingstrategy'); @@ -269,7 +295,6 @@ function xmldb_scheduler_upgrade($oldversion=0) { /* ******************* 3.1 upgrade line ********************** */ if ($oldversion < 2016051700) { - // Add configuration field "usenotes" to scheduler table. $table = new xmldb_table('scheduler'); $field = new xmldb_field('usenotes', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '1', 'bookingrouping'); @@ -283,6 +308,7 @@ function xmldb_scheduler_upgrade($oldversion=0) { if (!$dbman->field_exists($table, $field1)) { $dbman->add_field($table, $field1); } + $field2 = new xmldb_field('teachernoteformat', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0', 'teachernote'); if (!$dbman->field_exists($table, $field2)) { $dbman->add_field($table, $field2); @@ -302,7 +328,6 @@ function xmldb_scheduler_upgrade($oldversion=0) { /* ******************* 3.3 upgrade line ********************** */ if ($oldversion < 2017040100) { - // Add new configuration fields (relating to booking form) to scheduler. $table = new xmldb_table('scheduler'); @@ -310,32 +335,55 @@ function xmldb_scheduler_upgrade($oldversion=0) { if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } + $field = new xmldb_field('bookinginstructions', XMLDB_TYPE_TEXT, null, null, null, null, null, 'usebookingform'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } - $field = new xmldb_field('bookinginstructionsformat', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, - null, '1', 'bookinginstructions'); + + $field = new xmldb_field( + 'bookinginstructionsformat', + XMLDB_TYPE_INTEGER, + '4', + null, + XMLDB_NOTNULL, + null, + '1', + 'bookinginstructions' + ); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } - $field = new xmldb_field('usestudentnotes', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, - null, '0', 'bookinginstructionsformat'); + + $field = new xmldb_field( + 'usestudentnotes', + XMLDB_TYPE_INTEGER, + '2', + null, + XMLDB_NOTNULL, + null, + '0', + 'bookinginstructionsformat' + ); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } + $field = new xmldb_field('requireupload', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'usestudentnotes'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } + $field = new xmldb_field('uploadmaxfiles', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'requireupload'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } + $field = new xmldb_field('uploadmaxsize', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'uploadmaxfiles'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } + $field = new xmldb_field('usecaptcha', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'uploadmaxsize'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); @@ -347,6 +395,7 @@ function xmldb_scheduler_upgrade($oldversion=0) { if (!$dbman->field_exists($table, $field1)) { $dbman->add_field($table, $field1); } + $field2 = new xmldb_field('studentnoteformat', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0', 'studentnote'); if (!$dbman->field_exists($table, $field2)) { $dbman->add_field($table, $field2); diff --git a/export.php b/export.php index c3dea461..1fc263a2 100644 --- a/export.php +++ b/export.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -require_once(dirname(__FILE__).'/exportform.php'); +require_once(dirname(__FILE__) . '/exportform.php'); $PAGE->set_docs_path('mod/scheduler/export'); @@ -35,8 +35,8 @@ $currentgroupid = groups_get_activity_group($scheduler->cm, true); } -$actionurl = new moodle_url('/mod/scheduler/view.php', array('what' => 'export', 'id' => $scheduler->cmid)); -$returnurl = new moodle_url('/mod/scheduler/view.php', array('what' => 'view', 'id' => $scheduler->cmid)); +$actionurl = new moodle_url('/mod/scheduler/view.php', ['what' => 'export', 'id' => $scheduler->cmid]); +$returnurl = new moodle_url('/mod/scheduler/view.php', ['what' => 'view', 'id' => $scheduler->cmid]); $PAGE->set_url($actionurl); $mform = new scheduler_export_form($actionurl, $scheduler); @@ -47,19 +47,21 @@ $data = $mform->get_data(); if ($data) { $availablefields = scheduler_get_export_fields($scheduler); - $selectedfields = array(); + $selectedfields = []; foreach ($availablefields as $field) { - $inputid = 'field-'.$field->get_id(); + $inputid = 'field-' . $field->get_id(); if (isset($data->{$inputid}) && $data->{$inputid} == 1) { $selectedfields[] = $field; $field->set_renderer($output); } } + $userid = $USER->id; if (isset($data->includewhom) && $data->includewhom == 'all') { $permissions->ensure($permissions->can_see_all_slots()); $userid = 0; } + $pageperteacher = isset($data->paging) && $data->paging == 'perteacher'; $preview = isset($data->preview); } else { @@ -70,7 +72,7 @@ echo $OUTPUT->header(); // Print top tabs. - $taburl = new moodle_url('/mod/scheduler/view.php', array('id' => $scheduler->cmid, 'what' => 'export')); + $taburl = new moodle_url('/mod/scheduler/view.php', ['id' => $scheduler->cmid, 'what' => 'export']); echo $output->teacherview_tabs($scheduler, $permissions, $taburl, 'export'); if ($groupmode) { @@ -85,14 +87,16 @@ $canvas = new scheduler_html_canvas(); $export = new scheduler_export($canvas); - $export->build($scheduler, - $selectedfields, - $data->content, - $userid, - $currentgroupid, - $data->timerange, - $data->includeemptyslots, - $pageperteacher); + $export->build( + $scheduler, + $selectedfields, + $data->content, + $userid, + $currentgroupid, + $data->timerange, + $data->includeemptyslots, + $pageperteacher + ); $limit = 20; echo $canvas->as_html($limit, false); @@ -124,15 +128,16 @@ $export = new scheduler_export($canvas); -$export->build($scheduler, - $selectedfields, - $data->content, - $userid, - $currentgroupid, - $data->timerange, - $data->includeemptyslots, - $pageperteacher); - -$filename = clean_filename(format_string($course->shortname).'_'.format_string($scheduler->name)); +$export->build( + $scheduler, + $selectedfields, + $data->content, + $userid, + $currentgroupid, + $data->timerange, + $data->includeemptyslots, + $pageperteacher +); + +$filename = clean_filename(format_string($course->shortname) . '_' . format_string($scheduler->name)); $canvas->send($filename); - diff --git a/exportform.php b/exportform.php index e092eec0..b063984b 100644 --- a/exportform.php +++ b/exportform.php @@ -24,10 +24,10 @@ defined('MOODLE_INTERNAL') || die(); -use \mod_scheduler\model\scheduler; +use mod_scheduler\model\scheduler; -require_once($CFG->libdir.'/formslib.php'); -require_once($CFG->dirroot.'/mod/scheduler/exportlib.php'); +require_once($CFG->libdir . '/formslib.php'); +require_once($CFG->dirroot . '/mod/scheduler/exportlib.php'); /** * Export settings form (using Moodle formslib) @@ -36,8 +36,8 @@ * @copyright 2015 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_export_form extends moodleform { - +class scheduler_export_form extends moodleform +{ /** * @var scheduler the scheduler to be exported */ @@ -50,7 +50,7 @@ class scheduler_export_form extends moodleform { * @param scheduler $scheduler the scheduler to export * @param object $customdata */ - public function __construct($action, scheduler $scheduler, $customdata=null) { + public function __construct($action, scheduler $scheduler, $customdata = null) { $this->scheduler = $scheduler; parent::__construct($action, $customdata); } @@ -65,35 +65,54 @@ protected function definition() { // General introduction. $mform->addElement('header', 'general', get_string('general', 'form')); - $radios = array(); - $radios[] = $mform->createElement('radio', 'content', '', - get_string('onelineperslot', 'scheduler'), 'onelineperslot'); - $radios[] = $mform->createElement('radio', 'content', '', - get_string('onelineperappointment', 'scheduler'), 'onelineperappointment'); - $radios[] = $mform->createElement('radio', 'content', '', - get_string('appointmentsgrouped', 'scheduler'), 'appointmentsgrouped'); - $mform->addGroup($radios, 'contentgroup', - get_string('contentformat', 'scheduler'), null, false); + $radios = []; + $radios[] = $mform->createElement( + 'radio', + 'content', + '', + get_string('onelineperslot', 'scheduler'), + 'onelineperslot' + ); + $radios[] = $mform->createElement( + 'radio', + 'content', + '', + get_string('onelineperappointment', 'scheduler'), + 'onelineperappointment' + ); + $radios[] = $mform->createElement( + 'radio', + 'content', + '', + get_string('appointmentsgrouped', 'scheduler'), + 'appointmentsgrouped' + ); + $mform->addGroup( + $radios, + 'contentgroup', + get_string('contentformat', 'scheduler'), + null, + false + ); $mform->setDefault('content', 'onelineperappointment'); $mform->addHelpButton('contentgroup', 'contentformat', 'scheduler'); if (has_capability('mod/scheduler:canseeotherteachersbooking', $this->scheduler->get_context())) { - $selopt = array('me' => get_string('myself', 'scheduler'), - 'all' => get_string ('everyone', 'scheduler')); + $selopt = ['me' => get_string('myself', 'scheduler'), + 'all' => get_string('everyone', 'scheduler'), ]; $mform->addElement('select', 'includewhom', get_string('includeslotsfor', 'scheduler'), $selopt); $mform->setDefault('includewhom', 'all'); - $selopt = array('all' => get_string('allononepage', 'scheduler'), - 'perteacher' => get_string('pageperteacher', 'scheduler', $this->scheduler->get_teacher_name()) ); - $mform->addElement('select', 'paging', get_string('pagination', 'scheduler'), $selopt); + $selopt = ['all' => get_string('allononepage', 'scheduler'), + 'perteacher' => get_string('pageperteacher', 'scheduler', $this->scheduler->get_teacher_name()), ]; + $mform->addElement('select', 'paging', get_string('pagination', 'scheduler'), $selopt); $mform->addHelpButton('paging', 'pagination', 'scheduler'); - } $timeoptions = [ 0 => get_string('exporttimerangeall', 'scheduler'), 1 => get_string('exporttimerangefuture', 'scheduler'), - 2 => get_string('exporttimerangepast', 'scheduler') + 2 => get_string('exporttimerangepast', 'scheduler'), ]; $mform->addElement('select', 'timerange', get_string('exporttimerange', 'scheduler'), $timeoptions); $mform->setDefault('timerange', 0); @@ -120,35 +139,34 @@ protected function definition() { $mform->addElement('header', 'fileformathdr', get_string('fileformat', 'scheduler')); $mform->addHelpButton('fileformathdr', 'fileformat', 'scheduler'); - $radios = array(); + $radios = []; $radios[] = $mform->createElement('radio', 'outputformat', '', get_string('csvformat', 'scheduler'), 'csv'); - $radios[] = $mform->createElement('radio', 'outputformat', '', get_string('excelformat', 'scheduler'), 'xls'); + $radios[] = $mform->createElement('radio', 'outputformat', '', get_string('excelformat', 'scheduler'), 'xls'); $radios[] = $mform->createElement('radio', 'outputformat', '', get_string('odsformat', 'scheduler'), 'ods'); $radios[] = $mform->createElement('radio', 'outputformat', '', get_string('htmlformat', 'scheduler'), 'html'); $radios[] = $mform->createElement('radio', 'outputformat', '', get_string('pdfformat', 'scheduler'), 'pdf'); $mform->addGroup($radios, 'outputformatgroup', get_string('fileformat', 'scheduler'), null, false); $mform->setDefault('outputformat', 'csv'); - $selopt = array('comma' => get_string('sepcomma', 'scheduler'), + $selopt = ['comma' => get_string('sepcomma', 'scheduler'), 'colon' => get_string('sepcolon', 'scheduler'), 'semicolon' => get_string('sepsemicolon', 'scheduler'), - 'tab' => get_string('septab', 'scheduler')); - $mform->addElement('select', 'csvseparator', get_string('csvfieldseparator', 'scheduler'), $selopt); + 'tab' => get_string('septab', 'scheduler'), ]; + $mform->addElement('select', 'csvseparator', get_string('csvfieldseparator', 'scheduler'), $selopt); $mform->setDefault('csvseparator', 'comma'); $mform->disabledIf('csvseparator', 'outputformat', 'neq', 'csv'); - $selopt = array('P' => get_string('portrait', 'scheduler'), - 'L' => get_string('landscape', 'scheduler')); - $mform->addElement('select', 'pdforientation', get_string('pdforientation', 'scheduler'), $selopt); + $selopt = ['P' => get_string('portrait', 'scheduler'), + 'L' => get_string('landscape', 'scheduler'), ]; + $mform->addElement('select', 'pdforientation', get_string('pdforientation', 'scheduler'), $selopt); $mform->disabledIf('pdforientation', 'outputformat', 'neq', 'pdf'); - $buttonarray = array(); + $buttonarray = []; $buttonarray[] = $mform->createElement('submit', 'preview', get_string('preview', 'scheduler')); $buttonarray[] = $mform->createElement('submit', 'submitbutton', get_string('createexport', 'scheduler')); $buttonarray[] = $mform->createElement('cancel'); - $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false); + $mform->addGroup($buttonarray, 'buttonar', '', [' '], false); $mform->closeHeaderBefore('buttonar'); - } /** @@ -161,17 +179,18 @@ private function add_exportfield_group($groupid, $labelid) { $mform = $this->_form; $fields = scheduler_get_export_fields($this->scheduler); - $checkboxes = array(); + $checkboxes = []; foreach ($fields as $field) { if ($field->get_group() == $groupid && $field->is_available($this->scheduler)) { - $inputid = 'field-'.$field->get_id(); + $inputid = 'field-' . $field->get_id(); $label = $field->get_formlabel($this->scheduler); $checkboxes[] = $mform->createElement('checkbox', $inputid, '', $label); } } + $grouplabel = get_string($labelid, 'scheduler'); - $mform->addGroup($checkboxes, 'fields-'.$groupid, $grouplabel, null, false); + $mform->addGroup($checkboxes, 'fields-' . $groupid, $grouplabel, null, false); } /** @@ -187,5 +206,4 @@ public function validation($data, $files) { return $errors; } - } diff --git a/exportlib.php b/exportlib.php index 0a2b3341..12d014fa 100644 --- a/exportlib.php +++ b/exportlib.php @@ -24,16 +24,17 @@ defined('MOODLE_INTERNAL') || die(); -use \mod_scheduler\model\scheduler; -use \mod_scheduler\model\slot; -use \mod_scheduler\model\appointment; +use mod_scheduler\model\scheduler; +use mod_scheduler\model\slot; +use mod_scheduler\model\appointment; -require_once($CFG->dirroot.'/lib/excellib.class.php'); -require_once($CFG->dirroot.'/lib/odslib.class.php'); -require_once($CFG->dirroot.'/lib/csvlib.class.php'); -require_once($CFG->dirroot.'/lib/pdflib.php'); -require_once($CFG->dirroot.'/user/profile/lib.php'); +require_once($CFG->dirroot . '/lib/excellib.class.php'); +require_once($CFG->dirroot . '/lib/odslib.class.php'); +require_once($CFG->dirroot . '/lib/csvlib.class.php'); +require_once($CFG->dirroot . '/lib/pdflib.php'); +require_once($CFG->dirroot . '/user/profile/lib.php'); +// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses /** * A data field included in an export from Scheduler. @@ -42,8 +43,8 @@ * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -abstract class scheduler_export_field { - +abstract class scheduler_export_field +{ /** @var mixed */ protected $renderer; @@ -87,7 +88,7 @@ abstract public function get_group(); * @return string the header for this field */ public function get_header(scheduler $scheduler) { - return get_string('field-'.$this->get_id(), 'scheduler'); + return get_string('field-' . $this->get_id(), 'scheduler'); } /** @@ -98,7 +99,7 @@ public function get_header(scheduler $scheduler) { * @return array the header for this field */ public function get_headers(scheduler $scheduler) { - return array($this->get_header($scheduler)); + return [$this->get_header($scheduler)]; } /** @@ -160,9 +161,8 @@ abstract public function get_value(slot $slot, $appointment); * @return array an array of strings containing the column values */ public function get_values(slot $slot, $appointment) { - return array($this->get_value($slot, $appointment)); + return [$this->get_value($slot, $appointment)]; } - } /** @@ -172,7 +172,7 @@ public function get_values(slot $slot, $appointment) { * @return array the fields as an array of scheduler_export_field objects. */ function scheduler_get_export_fields(scheduler $scheduler) { - $result = array(); + $result = []; $result[] = new slotdate_field(); $result[] = new scheduler_starttime_field(); $result[] = new scheduler_endtime_field(); @@ -191,7 +191,7 @@ function scheduler_get_export_fields(scheduler $scheduler) { $pfields = profile_get_custom_fields(); foreach ($pfields as $id => $field) { $type = $field->datatype; - $result[] = new scheduler_profile_field('profile_'.$type, $id, $type); + $result[] = new scheduler_profile_field('profile_' . $type, $id, $type); } $result[] = new scheduler_groups_single_field(); @@ -215,8 +215,8 @@ function scheduler_get_export_fields(scheduler $scheduler) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class slotdate_field extends scheduler_export_field { - +class slotdate_field extends scheduler_export_field +{ /** * Retrieve the unique id (a string) for this field */ @@ -264,8 +264,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_starttime_field extends scheduler_export_field { - +class scheduler_starttime_field extends scheduler_export_field +{ /** * Retrieve the unique id (a string) for this field */ @@ -293,7 +293,6 @@ public function get_group() { public function get_value(slot $slot, $appointment) { return mod_scheduler_renderer::usertime($slot->starttime); } - } @@ -304,8 +303,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_endtime_field extends scheduler_export_field { - +class scheduler_endtime_field extends scheduler_export_field +{ /** * Retrieve the unique id (a string) for this field */ @@ -333,7 +332,6 @@ public function get_group() { public function get_value(slot $slot, $appointment) { return mod_scheduler_renderer::usertime($slot->endtime); } - } /** @@ -343,8 +341,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_teachername_field extends scheduler_export_field { - +class scheduler_teachername_field extends scheduler_export_field +{ /** * Retrieve the unique id (a string) for this field */ @@ -394,7 +392,6 @@ public function get_typical_width(scheduler $scheduler) { public function get_value(slot $slot, $appointment) { return fullname($slot->teacher); } - } /** @@ -404,8 +401,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_location_field extends scheduler_export_field { - +class scheduler_location_field extends scheduler_export_field +{ /** * Retrieve the unique id (a string) for this field */ @@ -433,7 +430,6 @@ public function get_group() { public function get_value(slot $slot, $appointment) { return format_string($slot->appointmentlocation); } - } /** @@ -443,8 +439,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_maxstudents_field extends scheduler_export_field { - +class scheduler_maxstudents_field extends scheduler_export_field +{ /** * Retrieve the unique id (a string) for this field */ @@ -476,7 +472,6 @@ public function get_value(slot $slot, $appointment) { return $slot->exclusivity; } } - } /** @@ -486,8 +481,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_student_field extends scheduler_export_field { - +class scheduler_student_field extends scheduler_export_field +{ /** @var mixed */ protected $id; /** @var mixed */ @@ -539,6 +534,7 @@ public function is_available(scheduler $scheduler) { if (!$this->idfield) { return true; } + $ctx = $scheduler->get_context(); return has_capability('moodle/site:viewuseridentity', $ctx); } @@ -569,17 +565,18 @@ public function get_value(slot $slot, $appointment) { if (! $appointment instanceof appointment) { return ''; } + $student = $appointment->get_student(); if (is_null($student)) { return ''; } + if ($this->studfield == 'fullname') { return fullname($student); } else { return $student->{$this->studfield}; } } - } /** @@ -589,8 +586,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2017 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_profile_field extends scheduler_export_field { - +class scheduler_profile_field extends scheduler_export_field +{ /** @var mixed */ protected $id; /** @var mixed */ @@ -607,8 +604,8 @@ public function __construct($id, $fieldid, $type) { global $CFG; $this->id = $id; - require_once($CFG->dirroot.'/user/profile/field/'.$type.'/field.class.php'); - $fieldclass = 'profile_field_'.$type; + require_once($CFG->dirroot . '/user/profile/field/' . $type . '/field.class.php'); + $fieldclass = 'profile_field_' . $type; $fieldobj = new $fieldclass($fieldid, 0); $this->field = $fieldobj; } @@ -659,19 +656,22 @@ public function get_header(scheduler $scheduler) { * @return string the value of this field for the given data */ public function get_value(slot $slot, $appointment) { - if (!$appointment instanceof appointment || $appointment->studentid == 0 - || !context_user::instance($appointment->studentid, IGNORE_MISSING)) { + if ( + !$appointment instanceof appointment || $appointment->studentid == 0 + || !context_user::instance($appointment->studentid, IGNORE_MISSING) + ) { return ''; } + $this->field->set_userid($appointment->studentid); $this->field->load_data(); if ($this->field->is_visible()) { $content = $this->field->display_data(); return strip_tags($content); } + return ''; } - } @@ -682,8 +682,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_attended_field extends scheduler_export_field { - +class scheduler_attended_field extends scheduler_export_field +{ /** * Retrieve the unique id (a string) for this field */ @@ -712,10 +712,10 @@ public function get_value(slot $slot, $appointment) { if (! $appointment instanceof appointment) { return ''; } + $str = $appointment->is_attended() ? get_string('yes') : get_string('no'); return $str; } - } /** @@ -725,8 +725,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class slotnotes_field extends scheduler_export_field { - +class slotnotes_field extends scheduler_export_field +{ /** * Retrieve the unique id (a string) for this field */ @@ -774,7 +774,6 @@ public function is_wrapping() { public function get_value(slot $slot, $appointment) { return strip_tags($slot->notes); } - } /** @@ -784,8 +783,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_appointmentnote_field extends scheduler_export_field { - +class scheduler_appointmentnote_field extends scheduler_export_field +{ /** * Retrieve the unique id (a string) for this field */ @@ -844,9 +843,9 @@ public function get_value(slot $slot, $appointment) { if (! $appointment instanceof appointment) { return ''; } + return strip_tags($appointment->appointmentnote); } - } /** @@ -856,8 +855,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_teachernote_field extends scheduler_export_field { - +class scheduler_teachernote_field extends scheduler_export_field +{ /** * Retrieve the unique id (a string) for this field */ @@ -916,9 +915,9 @@ public function get_value(slot $slot, $appointment) { if (! $appointment instanceof appointment) { return ''; } + return strip_tags($appointment->teachernote); } - } /** @@ -928,8 +927,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_studentnote_field extends scheduler_export_field { - +class scheduler_studentnote_field extends scheduler_export_field +{ /** * Retrieve the unique id (a string) for this field */ @@ -988,9 +987,9 @@ public function get_value(slot $slot, $appointment) { if (! $appointment instanceof appointment) { return ''; } + return strip_tags($appointment->studentnote); } - } /** @@ -1000,8 +999,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_filecount_field extends scheduler_export_field { - +class scheduler_filecount_field extends scheduler_export_field +{ /** * Retrieve the unique id (a string) for this field */ @@ -1060,9 +1059,9 @@ public function get_value(slot $slot, $appointment) { if (! $appointment instanceof appointment) { return ''; } + return $appointment->count_studentfiles(); } - } /** @@ -1072,8 +1071,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_grade_field extends scheduler_export_field { - +class scheduler_grade_field extends scheduler_export_field +{ /** * Retrieve the unique id (a string) for this field */ @@ -1112,9 +1111,9 @@ public function get_value(slot $slot, $appointment) { if (! $appointment instanceof appointment) { return ''; } + return $this->renderer->format_grade($slot->get_scheduler(), $appointment->grade); } - } /** @@ -1124,8 +1123,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2018 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_groups_single_field extends scheduler_export_field { - +class scheduler_groups_single_field extends scheduler_export_field +{ /** * Retrieve the unique id (a string) for this field */ @@ -1176,16 +1175,17 @@ public function get_value(slot $slot, $appointment) { if (! $appointment instanceof appointment) { return ''; } + $scheduler = $slot->get_scheduler(); $groups = groups_get_user_groups($scheduler->courseid, $appointment->studentid); $groupingid = $scheduler->get_cm()->groupingid; - $gn = array(); + $gn = []; foreach ($groups[$groupingid] as $groupid) { $gn[] = groups_get_group_name($groupid); } + return implode(',', $gn); } - } /** @@ -1195,8 +1195,8 @@ public function get_value(slot $slot, $appointment) { * @copyright 2018 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_groups_multi_field extends scheduler_export_field { - +class scheduler_groups_multi_field extends scheduler_export_field +{ /** @var mixed */ protected $coursegroups; @@ -1254,10 +1254,11 @@ public function get_num_columns(scheduler $scheduler) { * @return array the header for this field */ public function get_headers(scheduler $scheduler) { - $result = array(); + $result = []; foreach ($this->coursegroups as $group) { $result[] = $group->name; } + return $result; } @@ -1284,15 +1285,16 @@ public function get_values(slot $slot, $appointment) { if (! $appointment instanceof appointment) { return ''; } + $usergroups = groups_get_user_groups($slot->get_scheduler()->courseid, $appointment->studentid)[0]; - $result = array(); + $result = []; foreach ($this->coursegroups as $group) { $key = in_array($group->id, $usergroups) ? 'yes' : 'no'; $result[] = get_string($key); } + return $result; } - } /** @@ -1302,8 +1304,8 @@ public function get_values(slot $slot, $appointment) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -abstract class scheduler_canvas { - +abstract class scheduler_canvas +{ /** * @var object format instructions for header */ @@ -1393,7 +1395,6 @@ public function set_title($title) { * @param string $filename the file name to send */ abstract public function send($filename); - } /** @@ -1403,8 +1404,8 @@ abstract public function send($filename); * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_excel_canvas extends scheduler_canvas { - +class scheduler_excel_canvas extends scheduler_canvas +{ /** @var mixed */ protected $workbook; /** @var mixed */ @@ -1429,7 +1430,6 @@ public function __construct() { $this->formatboldit->set_bold(); $this->formatboldit->set_italic(); $this->formatwrap->set_text_wrap(); - } /** @@ -1458,7 +1458,7 @@ private function ensure_open_page() { * @param mixed $str the string to write * @param mixed $format the format to use (one of the $format... fields of this object), can be null */ - public function write_string($row, $col, $str, $format=null) { + public function write_string($row, $col, $str, $format = null) { $this->ensure_open_page(); $this->worksheet->write_string($row, $col, $str, $format); } @@ -1471,7 +1471,7 @@ public function write_string($row, $col, $str, $format=null) { * @param mixed $num the number to write * @param mixed $format the format to use (one of the $format... fields of this object), can be null */ - public function write_number($row, $col, $num, $format=null) { + public function write_number($row, $col, $num, $format = null) { $this->ensure_open_page(); $this->worksheet->write_number($row, $col, $num, $format); } @@ -1508,7 +1508,6 @@ public function send($filename) { $this->workbook->send($filename); $this->workbook->close(); } - } /** @@ -1518,8 +1517,8 @@ public function send($filename) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_ods_canvas extends scheduler_canvas { - +class scheduler_ods_canvas extends scheduler_canvas +{ /** @var mixed */ protected $workbook; /** @var mixed */ @@ -1543,7 +1542,6 @@ public function __construct() { $this->formatboldit->set_bold(); $this->formatboldit->set_italic(); $this->formatwrap->set_text_wrap(); - } /** @@ -1572,7 +1570,7 @@ private function ensure_open_page() { * @param mixed $str the string to write * @param mixed $format the format to use (one of the $format... fields of this object), can be null */ - public function write_string($row, $col, $str, $format=null) { + public function write_string($row, $col, $str, $format = null) { $this->ensure_open_page(); $this->worksheet->write_string($row, $col, $str, $format); } @@ -1585,7 +1583,7 @@ public function write_string($row, $col, $str, $format=null) { * @param mixed $num the number to write * @param mixed $format the format to use (one of the $format... fields of this object), can be null */ - public function write_number($row, $col, $num, $format=null) { + public function write_number($row, $col, $num, $format = null) { $this->ensure_open_page(); $this->worksheet->write_number($row, $col, $num, $format); } @@ -1622,7 +1620,6 @@ public function send($filename) { $this->workbook->send($filename); $this->workbook->close(); } - } @@ -1633,8 +1630,8 @@ public function send($filename) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -abstract class scheduler_cached_text_canvas extends scheduler_canvas { - +abstract class scheduler_cached_text_canvas extends scheduler_canvas +{ /** @var mixed */ protected $pages; /** @var mixed */ @@ -1651,7 +1648,6 @@ public function __construct() { $this->formatwrap = 'wrap'; $this->start_page(''); - } /** @@ -1669,6 +1665,7 @@ protected function get_col_count($page) { } } } + return $maxcol + 1; } @@ -1685,6 +1682,7 @@ protected function get_row_count($page) { $maxrow = $rownum; } } + return $maxrow + 1; } @@ -1700,7 +1698,8 @@ protected function compute_relative_widths($page) { foreach ($page->columnwidths as $width) { $sum += $width; } - $relwidths = array(); + + $relwidths = []; for ($col = 0; $col < $cols; $col++) { if ($sum > 0 && isset($page->columnwidths[$col])) { $relwidths[$col] = (int) ($page->columnwidths[$col] / $sum * 100); @@ -1708,6 +1707,7 @@ protected function compute_relative_widths($page) { $relwidths[$col] = 0; } } + return $relwidths; } @@ -1721,12 +1721,12 @@ public function start_page($title) { if ($onemptypage) { $this->curpage->title = $title; } else { - $newpage = new stdClass; + $newpage = new stdClass(); $newpage->title = $title; - $newpage->cells = array(); - $newpage->formats = array(); - $newpage->mergers = array(); - $newpage->columnwidths = array(); + $newpage->cells = []; + $newpage->formats = []; + $newpage->mergers = []; + $newpage->columnwidths = []; $this->pages[] = $newpage; $this->curpage = $newpage; } @@ -1740,7 +1740,7 @@ public function start_page($title) { * @param mixed $str the string to write * @param mixed $format the format to use (one of the $format... fields of this object), can be null */ - public function write_string($row, $col, $str, $format=null) { + public function write_string($row, $col, $str, $format = null) { $this->curpage->cells[$row][$col] = $str; $this->curpage->formats[$row][$col] = $format; } @@ -1753,7 +1753,7 @@ public function write_string($row, $col, $str, $format=null) { * @param mixed $num the number to write * @param mixed $format the format to use (one of the $format... fields of this object), can be null */ - public function write_number($row, $col, $num, $format=null) { + public function write_number($row, $col, $num, $format = null) { $this->write_string($row, $col, $num, $format); } @@ -1778,7 +1778,6 @@ public function merge_cells($row, $fromcol, $tocol) { public function set_column_width($col, $width) { $this->curpage->columnwidths[$col] = $width; } - } /** @@ -1788,8 +1787,8 @@ public function set_column_width($col, $width) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_html_canvas extends scheduler_cached_text_canvas { - +class scheduler_html_canvas extends scheduler_cached_text_canvas +{ /** * as_html * @@ -1817,6 +1816,7 @@ public function as_html($rowcutoff, $usetitle = true) { if ($rowcutoff && $rows > $rowcutoff) { $rows = $rowcutoff; } + $relwidths = $this->compute_relative_widths($page); $table = new html_table(); @@ -1832,35 +1832,44 @@ public function as_html($rowcutoff, $usetitle = true) { $span = $mergewidth; } } + $cell = new html_table_cell(''); $text = ''; if (isset($page->cells[$row][$col])) { $text = $page->cells[$row][$col]; } + if (isset($page->formats[$row][$col])) { $cell->header = ($page->formats[$row][$col] == 'header'); if ($page->formats[$row][$col] == 'boldit') { $text = html_writer::tag('i', $text); $text = html_writer::tag('b', $text); } + if ($page->formats[$row][$col] == 'bold') { $text = html_writer::tag('b', $text); } } + if ($span > 1) { $cell->colspan = $span; } + if ($row == 0 & $relwidths[$col] > 0) { - $cell->width = $relwidths[$col].'%'; + $cell->width = $relwidths[$col] . '%'; } + $cell->text = $text; $hrow->cells[] = $cell; $col = $col + $span; } + $table->data[] = $hrow; } + $o .= html_writer::table($table); } + return $o; } @@ -1876,7 +1885,6 @@ public function send($filename) { echo $this->as_html(0, true); echo $OUTPUT->footer(); } - } /** @@ -1886,8 +1894,8 @@ public function send($filename) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_csv_canvas extends scheduler_cached_text_canvas { - +class scheduler_csv_canvas extends scheduler_cached_text_canvas +{ /** @var mixed */ protected $delimiter; @@ -1913,7 +1921,7 @@ public function send($filename) { foreach ($this->pages as $page) { if ($page->title) { - $writer->add_data(array('*** '.$page->title.' ***')); + $writer->add_data(['*** ' . $page->title . ' ***']); } // Find extent of the table. @@ -1921,7 +1929,7 @@ public function send($filename) { $cols = $this->get_col_count($page); for ($row = 0; $row < $rows; $row++) { - $data = array(); + $data = []; $col = 0; while ($col < $cols) { if (isset($page->cells[$row][$col])) { @@ -1937,15 +1945,16 @@ public function send($filename) { $span = $mergewidth; } } + $col += $span; } + $writer->add_data($data); } } $writer->download_file(); } - } /** @@ -1955,8 +1964,8 @@ public function send($filename) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_pdf_canvas extends scheduler_cached_text_canvas { - +class scheduler_pdf_canvas extends scheduler_cached_text_canvas +{ /** @var mixed */ protected $orientation; @@ -1984,12 +1993,13 @@ public function send($filename) { } else { $doc->setPrintHeader(false); } + $doc->setPrintFooter(false); foreach ($this->pages as $page) { $doc->AddPage(); if ($page->title) { - $doc->writeHtml('

'.$page->title.'

'); + $doc->writeHtml('

' . $page->title . '

'); } // Find extent of the table. @@ -1997,7 +2007,7 @@ public function send($filename) { $cols = $this->get_col_count($page); $relwidths = $this->compute_relative_widths($page); - $o = html_writer::start_tag('table', array('border' => 1, 'cellpadding' => 1)); + $o = html_writer::start_tag('table', ['border' => 1, 'cellpadding' => 1]); for ($row = 0; $row < $rows; $row++) { $o .= html_writer::start_tag('tr'); $col = 0; @@ -2009,13 +2019,16 @@ public function send($filename) { $span = $mergewidth; } } - $opts = array(); + + $opts = []; if ($row == 0 && $relwidths[$col] > 0) { - $opts['width'] = $relwidths[$col].'%'; + $opts['width'] = $relwidths[$col] . '%'; } + if ($span > 1) { $opts['colspan'] = $span; } + $o .= html_writer::start_tag('td', $opts); $cell = ''; if (isset($page->cells[$row][$col])) { @@ -2029,21 +2042,23 @@ public function send($filename) { } } } + $o .= $cell; $o .= html_writer::end_tag('td'); $col += $span; } + $o .= html_writer::end_tag('tr'); } + $o .= html_Writer::end_tag('table'); $doc->writeHtml($o); } - $doc->Output($filename.'.pdf'); + $doc->Output($filename . '.pdf'); } - } /** @@ -2053,8 +2068,8 @@ public function send($filename) { * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_export { - +class scheduler_export +{ /** * @var scheduler_canvas the canvas used for output */ @@ -2086,11 +2101,20 @@ public function __construct(scheduler_canvas $canvas) { * @param bool $includeempty whether to include slots without appointments * @param bool $pageperteacher whether one page should be used for each teacher */ - public function build(scheduler $scheduler, array $fields, $mode, $userid, $groupid, $timerange, $includeempty, - $pageperteacher) { + public function build( + scheduler $scheduler, + array $fields, + $mode, + $userid, + $groupid, + $timerange, + $includeempty, + $pageperteacher + ) { if ($groupid) { $this->studfilter = array_keys(groups_get_members($groupid, 'u.id')); } + $this->canvas->set_title(format_string($scheduler->name)); if ($userid) { $slots = $scheduler->get_slots_for_teacher($userid, $groupid, '', '', $timerange); @@ -2132,9 +2156,11 @@ protected function build_page(scheduler $scheduler, array $fields, array $slots, $this->canvas->write_string($row, $col + $i, $headers[$i], $this->canvas->formatheader); $this->canvas->set_column_width($col + $i, $field->get_typical_width($scheduler)); } + $col = $col + $numcols; } } + $row++; // Output the data rows. @@ -2145,6 +2171,7 @@ protected function build_page(scheduler $scheduler, array $fields, array $slots, $this->write_row_summary($row, $slot, $fields); $row++; } + foreach ($appts as $appt) { $this->write_row($row, $slot, $appt, $fields, false); $row++; @@ -2166,7 +2193,6 @@ protected function build_page(scheduler $scheduler, array $fields, array $slots, } } } - } /** @@ -2178,9 +2204,14 @@ protected function build_page(scheduler $scheduler, array $fields, array $slots, * @param bool $includeslotfields whether fields relating to slots, rather than appointments, should be included * @param string $multiple whether the row represents multiple values (appointments) */ - protected function write_row($row, slot $slot, $appointment, array $fields, $includeslotfields = true, - $multiple = false) { - + protected function write_row( + $row, + slot $slot, + $appointment, + array $fields, + $includeslotfields = true, + $multiple = false + ) { $col = 0; foreach ($fields as $field) { if ($includeslotfields || $field->get_group() != 'slot') { @@ -2195,6 +2226,7 @@ protected function write_row($row, slot $slot, $appointment, array $fields, $inc for ($i = 0; $i < $numcols; $i++) { $this->canvas->write_string($row, $col + $i, $values[$i], $format); } + $col = $col + $numcols; } } @@ -2210,7 +2242,7 @@ protected function write_row($row, slot $slot, $appointment, array $fields, $inc */ protected function write_row_summary($row, slot $slot, array $fields) { - $strs = array(); + $strs = []; $cols = 0; foreach ($fields as $field) { if ($field->get_group() == 'slot') { @@ -2219,9 +2251,9 @@ protected function write_row_summary($row, slot $slot, array $fields) { $cols++; } } + $str = implode(' - ', $strs); $this->canvas->write_string($row, 0, $str, $this->canvas->formatboldit); $this->canvas->merge_cells($row, 0, $cols - 1); } - } diff --git a/index.php b/index.php index 4b910fb1..e617de2b 100644 --- a/index.php +++ b/index.php @@ -24,21 +24,21 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once(dirname(dirname(dirname(__FILE__))).'/config.php'); -require_once(dirname(__FILE__).'/lib.php'); +require_once(dirname(dirname(dirname(__FILE__))) . '/config.php'); +require_once(dirname(__FILE__) . '/lib.php'); $id = required_param('id', PARAM_INT); // Course id. -$course = $DB->get_record('course', array('id' => $id), '*', MUST_EXIST); +$course = $DB->get_record('course', ['id' => $id], '*', MUST_EXIST); -$PAGE->set_url('/mod/scheduler/index.php', array('id' => $id)); +$PAGE->set_url('/mod/scheduler/index.php', ['id' => $id]); $PAGE->set_pagelayout('incourse'); $coursecontext = context_course::instance($id); require_login($course->id); -$event = \mod_scheduler\event\course_module_instance_list_viewed::create(array( - 'context' => $coursecontext -)); +$event = \mod_scheduler\event\course_module_instance_list_viewed::create([ + 'context' => $coursecontext, +]); $event->add_record_snapshot('course', $course); $event->trigger(); @@ -72,26 +72,26 @@ $table = new html_table(); if ($course->format == 'weeks') { - $table->head = array ($strweek, $strname); - $table->align = array ('CENTER', 'LEFT'); + $table->head = [$strweek, $strname]; + $table->align = ['CENTER', 'LEFT']; } else if ($course->format == 'topics') { - $table->head = array ($strtopic, $strname); - $table->align = array ('CENTER', 'LEFT', 'LEFT', 'LEFT'); + $table->head = [$strtopic, $strname]; + $table->align = ['CENTER', 'LEFT', 'LEFT', 'LEFT']; } else { - $table->head = array ($strname); - $table->align = array ('LEFT', 'LEFT', 'LEFT'); + $table->head = [$strname]; + $table->align = ['LEFT', 'LEFT', 'LEFT']; } foreach ($schedulers as $scheduler) { - $url = new moodle_url('/mod/scheduler/view.php', array('id' => $scheduler->coursemodule)); + $url = new moodle_url('/mod/scheduler/view.php', ['id' => $scheduler->coursemodule]); // Show dimmed if the mod is hidden. - $attr = $scheduler->visible ? null : array('class' => 'dimmed'); + $attr = $scheduler->visible ? null : ['class' => 'dimmed']; $link = html_writer::link($url, $scheduler->name, $attr); if ($scheduler->visible || has_capability('moodle/course:viewhiddenactivities', $coursecontext)) { if ($course->format == 'weeks' || $course->format == 'topics') { - $table->data[] = array ($scheduler->section, $link); + $table->data[] = [$scheduler->section, $link]; } else { - $table->data[] = array ($link); + $table->data[] = [$link]; } } } @@ -101,4 +101,3 @@ // Finish the page. echo $OUTPUT->footer($course); - diff --git a/lang/en/scheduler.php b/lang/en/scheduler.php index 3b2b19db..3fa13b7e 100644 --- a/lang/en/scheduler.php +++ b/lang/en/scheduler.php @@ -22,6 +22,10 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +// Let codechecker ignore some sniffs for this file as it is perfectly well ordered, just not alphabetically. +// phpcs:disable moodle.Files.LangFilesOrdering.UnexpectedComment +// phpcs:disable moodle.Files.LangFilesOrdering.IncorrectOrder + $string['pluginname'] = 'Scheduler'; $string['pluginadministration'] = 'Scheduler administration'; $string['modulename'] = 'Scheduler'; diff --git a/lib.php b/lib.php index 14119c92..50a9782f 100644 --- a/lib.php +++ b/lib.php @@ -24,22 +24,22 @@ defined('MOODLE_INTERNAL') || die(); -use \mod_scheduler\model\scheduler; +use mod_scheduler\model\scheduler; // Library of functions and constants for module Scheduler. -require_once($CFG->dirroot.'/mod/scheduler/locallib.php'); -require_once($CFG->dirroot.'/mod/scheduler/mailtemplatelib.php'); -require_once($CFG->dirroot.'/mod/scheduler/renderer.php'); -require_once($CFG->dirroot.'/mod/scheduler/renderable.php'); +require_once($CFG->dirroot . '/mod/scheduler/locallib.php'); +require_once($CFG->dirroot . '/mod/scheduler/mailtemplatelib.php'); +require_once($CFG->dirroot . '/mod/scheduler/renderer.php'); +require_once($CFG->dirroot . '/mod/scheduler/renderable.php'); define('SCHEDULER_TIMEUNKNOWN', 0); // This is used for appointments for which no time is entered. define('SCHEDULER_SELF', 0); // Used for setting conflict search scope. define('SCHEDULER_OTHERS', 1); // Used for setting conflict search scope. define('SCHEDULER_ALL', 2); // Used for setting conflict search scope. -define ('SCHEDULER_MEAN_GRADE', 0); // Used for grading strategy. -define ('SCHEDULER_MAX_GRADE', 1); // Used for grading strategy. +define('SCHEDULER_MEAN_GRADE', 0); // Used for grading strategy. +define('SCHEDULER_MAX_GRADE', 1); // Used for grading strategy. /** * Given an object containing all the necessary data, @@ -61,7 +61,7 @@ function scheduler_add_instance($data, $mform = null) { $data->id = $DB->insert_record('scheduler', $data); - $DB->set_field('course_modules', 'instance', $data->id, array('id' => $cmid)); + $DB->set_field('course_modules', 'instance', $data->id, ['id' => $cmid]); $context = context_module::instance($cmid); if ($mform) { @@ -78,13 +78,21 @@ function scheduler_add_instance($data, $mform = null) { return $data->id; } +/** + * Callback function for the student autocomplete. + * + * @param int $value user id + * @return bool|string + * @throws \core\exception\moodle_exception + * @throws dml_exception + */ function scheduler_student_autocomplete_callback($value) { global $OUTPUT; $fields = 'id ' . \core_user\fields::for_name()->get_sql()->selects; $user = \core_user::get_user($value, $fields); $useroptiondata = [ - 'fullname' => fullname($user) + 'fullname' => fullname($user), ]; return $OUTPUT->render_from_template('mod_scheduler/studentid', $useroptiondata); @@ -137,7 +145,7 @@ function scheduler_update_instance($data, $mform) { function scheduler_delete_instance($id) { global $DB; - if (! $DB->record_exists('scheduler', array('id' => $id))) { + if (! $DB->record_exists('scheduler', ['id' => $id])) { return false; } @@ -145,7 +153,7 @@ function scheduler_delete_instance($id) { $scheduler->delete(); // Clean up any possibly remaining event records. - $params = array('modulename' => 'scheduler', 'instance' => $id); + $params = ['modulename' => 'scheduler', 'instance' => $id]; $DB->delete_records('event', $params); return true; @@ -173,7 +181,7 @@ function scheduler_user_outline($course, $user, $mod, $scheduler) { $text = ''; if ($attended + $upcoming > 0) { - $a = array('attended' => $attended, 'upcoming' => $upcoming); + $a = ['attended' => $attended, 'upcoming' => $upcoming]; $text .= get_string('outlineappointments', 'scheduler', $a); } @@ -226,7 +234,6 @@ function scheduler_user_complete($course, $user, $mod, $scheduler) { echo $output->render($info); } } - } /** @@ -259,7 +266,7 @@ function scheduler_scale_used($cmid, $scaleid) { $return = false; // Note: scales are assigned using negative index in the grade field of the appointment (see mod/assignement/lib.php). - $rec = $DB->get_record('scheduler', array('id' => $cmid, 'scale' => -$scaleid)); + $rec = $DB->get_record('scheduler', ['id' => $cmid, 'scale' => -$scaleid]); if (!empty($rec) && !empty($scaleid)) { $return = true; @@ -279,7 +286,7 @@ function scheduler_scale_used($cmid, $scaleid) { function scheduler_scale_used_anywhere($scaleid) { global $DB; - if ($scaleid && $DB->record_exists('scheduler', array('scale' => -$scaleid))) { + if ($scaleid && $DB->record_exists('scheduler', ['scale' => -$scaleid])) { return true; } else { return false; @@ -304,8 +311,7 @@ function scheduler_reset_course_form_definition(&$mform) { $mform->addElement('header', 'schedulerheader', get_string('modulenameplural', 'scheduler')); - if ($DB->record_exists('scheduler', array('course' => $COURSE->id))) { - + if ($DB->record_exists('scheduler', ['course' => $COURSE->id])) { $mform->addElement('checkbox', 'reset_scheduler_slots', get_string('resetslots', 'scheduler')); $mform->addElement('checkbox', 'reset_scheduler_appointments', get_string('resetappointments', 'scheduler')); $mform->disabledIf('reset_scheduler_appointments', 'reset_scheduler_slots', 'checked'); @@ -318,7 +324,7 @@ function scheduler_reset_course_form_definition(&$mform) { * @param stdClass $course the course in which the reset takes place */ function scheduler_reset_course_form_defaults($course) { - return array('reset_scheduler_slots' => 1, 'reset_scheduler_appointments' => 1); + return ['reset_scheduler_slots' => 1, 'reset_scheduler_appointments' => 1]; } @@ -333,33 +339,34 @@ function scheduler_reset_course_form_defaults($course) { function scheduler_reset_userdata($data) { global $CFG, $DB; - $status = array(); + $status = []; $componentstr = get_string('modulenameplural', 'scheduler'); $success = true; if (!empty($data->reset_scheduler_appointments) || !empty($data->reset_scheduler_slots)) { - $schedulers = $DB->get_records('scheduler', ['course' => $data->courseid]); foreach ($schedulers as $srec) { $scheduler = scheduler::load_by_id($srec->id); - if (!empty($data->reset_scheduler_slots) ) { + if (!empty($data->reset_scheduler_slots)) { $scheduler->delete_all_slots(); - $status[] = array('component' => $componentstr, 'item' => get_string('resetslots', 'scheduler'), 'error' => false); - } else if (!empty($data->reset_scheduler_appointments) ) { + $status[] = ['component' => $componentstr, 'item' => get_string('resetslots', 'scheduler'), 'error' => false]; + } else if (!empty($data->reset_scheduler_appointments)) { foreach ($scheduler->get_all_slots() as $slot) { $slot->delete_all_appointments(); } - $status[] = array( + + $status[] = [ 'component' => $componentstr, 'item' => get_string('resetappointments', 'scheduler'), - 'error' => !$success - ); + 'error' => !$success, + ]; } } } + return $status; } @@ -370,13 +377,11 @@ function scheduler_reset_userdata($data) { * @return mixed True if module supports feature, null if doesn't know */ function scheduler_supports($feature) { - switch($feature) { + switch ($feature) { case FEATURE_GROUPS: return true; case FEATURE_GROUPINGS: return true; - case FEATURE_GROUPMEMBERSONLY: - return true; case FEATURE_MOD_INTRO: return true; case FEATURE_COMPLETION_TRACKS_VIEWS: @@ -412,23 +417,22 @@ function scheduler_supports($feature) { * @uses $CFG * @uses $DB */ -function scheduler_update_grades($schedulerrecord, $userid=0, $nullifnone=true) { +function scheduler_update_grades($schedulerrecord, $userid = 0, $nullifnone = true) { global $CFG, $DB; - require_once($CFG->libdir.'/gradelib.php'); + require_once($CFG->libdir . '/gradelib.php'); $scheduler = scheduler::load_by_id($schedulerrecord->id); if ($scheduler->scale == 0) { scheduler_grade_item_update($schedulerrecord); - } else if ($grades = $scheduler->get_user_grades($userid)) { foreach ($grades as $k => $v) { if ($v->rawgrade == -1) { $grades[$k]->rawgrade = null; } } - scheduler_grade_item_update($schedulerrecord, $grades); + scheduler_grade_item_update($schedulerrecord, $grades); } else { scheduler_grade_item_update($schedulerrecord); } @@ -442,32 +446,31 @@ function scheduler_update_grades($schedulerrecord, $userid=0, $nullifnone=true) * @param mixed $grades optional array/object of grade(s); 'reset' means reset grades in gradebook * @return int 0 if ok, error code otherwise */ -function scheduler_grade_item_update($scheduler, $grades=null) { +function scheduler_grade_item_update($scheduler, $grades = null) { global $CFG, $DB; - require_once($CFG->libdir.'/gradelib.php'); + require_once($CFG->libdir . '/gradelib.php'); if (!isset($scheduler->courseid)) { $scheduler->courseid = $scheduler->course; } - $moduleid = $DB->get_field('modules', 'id', array('name' => 'scheduler')); - $cmid = $DB->get_field('course_modules', 'id', array('module' => $moduleid, 'instance' => $scheduler->id)); + + $moduleid = $DB->get_field('modules', 'id', ['name' => 'scheduler']); + $cmid = $DB->get_field('course_modules', 'id', ['module' => $moduleid, 'instance' => $scheduler->id]); if ($scheduler->scale == 0) { // Delete any grade item. scheduler_grade_item_delete($scheduler); return 0; } else { - $params = array('itemname' => $scheduler->name, 'idnumber' => $cmid); + $params = ['itemname' => $scheduler->name, 'idnumber' => $cmid]; if ($scheduler->scale > 0) { $params['gradetype'] = GRADE_TYPE_VALUE; $params['grademax'] = $scheduler->scale; $params['grademin'] = 0; - } else if ($scheduler->scale < 0) { $params['gradetype'] = GRADE_TYPE_SCALE; $params['scaleid'] = -$scheduler->scale; - } else { $params['gradetype'] = GRADE_TYPE_TEXT; // Allow text comments only. } @@ -507,8 +510,10 @@ function scheduler_upgrade_grades() { scheduler_update_grades($scheduler); $pbar->update($i, $count, "Updating scheduler grades ($i/$count)."); } + upgrade_set_timeout(); // Reset to default timeout. } + $rs->close(); } @@ -521,13 +526,13 @@ function scheduler_upgrade_grades() { */ function scheduler_grade_item_delete($scheduler) { global $CFG; - require_once($CFG->libdir.'/gradelib.php'); + require_once($CFG->libdir . '/gradelib.php'); if (!isset($scheduler->courseid)) { $scheduler->courseid = $scheduler->course; } - return grade_update('mod/scheduler', $scheduler->courseid, 'mod', 'scheduler', $scheduler->id, 0, null, array('deleted' => 1)); + return grade_update('mod/scheduler', $scheduler->courseid, 'mod', 'scheduler', $scheduler->id, 0, null, ['deleted' => 1]); } @@ -546,12 +551,12 @@ function scheduler_grade_item_delete($scheduler) { * @return array */ function scheduler_get_file_areas($course, $cm, $context) { - return array( + return [ 'bookinginstructions' => get_string('bookinginstructions', 'scheduler'), 'slotnote' => get_string('areaslotnote', 'scheduler'), 'appointmentnote' => get_string('areaappointmentnote', 'scheduler'), - 'teachernote' => get_string('areateachernote', 'scheduler') - ); + 'teachernote' => get_string('areateachernote', 'scheduler'), + ]; } /** @@ -573,12 +578,21 @@ function scheduler_get_file_info($browser, $areas, $course, $cm, $context, $file // Note: 'intro' area is handled in file_browser automatically. - if (!has_any_capability(array('mod/scheduler:appoint', 'mod/scheduler:attend', - 'mod/scheduler:viewotherteachersbooking', 'mod/scheduler:manageallappointments'), $context)) { + if ( + !has_any_capability( + [ + 'mod/scheduler:appoint', + 'mod/scheduler:attend', + 'mod/scheduler:viewotherteachersbooking', + 'mod/scheduler:manageallappointments', + ], + $context + ) + ) { return null; } - require_once(dirname(__FILE__).'/locallib.php'); + require_once(dirname(__FILE__) . '/locallib.php'); $validareas = array_keys(scheduler_get_file_areas($course, $cm, $context)); if (!in_array($filearea, $validareas)) { @@ -597,31 +611,29 @@ function scheduler_get_file_info($browser, $areas, $course, $cm, $context, $file $cansee = true; $canwrite = has_capability('moodle/course:manageactivities', $context); $name = get_string('bookinginstructions', 'scheduler'); - } else if ($filearea === 'slotnote') { $slot = $scheduler->get_slot($itemid); $cansee = true; $canwrite = $permissions->can_edit_slot($slot); - $name = get_string('slot', 'scheduler'). ' '.$itemid; - + $name = get_string('slot', 'scheduler') . ' ' . $itemid; } else if ($filearea === 'appointmentnote') { if (!$scheduler->uses_appointmentnotes()) { return null; } - list($slot, $app) = $scheduler->get_slot_appointment($itemid); + + [$slot, $app] = $scheduler->get_slot_appointment($itemid); $cansee = $permissions->can_see_appointment($app); $canwrite = $permissions->can_edit_notes($app); - $name = get_string('appointment', 'scheduler'). ' '.$itemid; - + $name = get_string('appointment', 'scheduler') . ' ' . $itemid; } else if ($filearea === 'teachernote') { if (!$scheduler->uses_teachernotes()) { return null; } - list($slot, $app) = $scheduler->get_slot_appointment($itemid); + [$slot, $app] = $scheduler->get_slot_appointment($itemid); $cansee = $permissions->teacher_can_see_slot($slot); $canwrite = $permissions->can_edit_notes($app); - $name = get_string('appointment', 'scheduler'). ' '.$itemid; + $name = get_string('appointment', 'scheduler') . ' ' . $itemid; } $fs = get_file_storage(); @@ -631,7 +643,7 @@ function scheduler_get_file_info($browser, $areas, $course, $cm, $context, $file return null; } - $urlbase = $CFG->wwwroot.'/pluginfile.php'; + $urlbase = $CFG->wwwroot . '/pluginfile.php'; return new file_info_stored($browser, $context, $storedfile, $urlbase, $name, true, true, $canwrite, false); } catch (Exception $e) { return null; @@ -652,7 +664,15 @@ function scheduler_get_file_info($browser, $areas, $course, $cm, $context, $file * @param array $options additional options affecting the file serving * @return bool false if file not found, does not return if found - just send the file */ -function scheduler_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) { +function scheduler_pluginfile( + $course, + $cm, + $context, + $filearea, + $args, + $forcedownload, + array $options = [] +) { global $CFG, $DB, $USER; if ($context->contextlevel != CONTEXT_MODULE) { @@ -660,7 +680,7 @@ function scheduler_pluginfile($course, $cm, $context, $filearea, $args, $forcedo } require_course_login($course, true, $cm); - if (!has_any_capability(array('mod/scheduler:appoint', 'mod/scheduler:attend'), $context)) { + if (!has_any_capability(['mod/scheduler:appoint', 'mod/scheduler:attend'], $context)) { return false; } @@ -675,50 +695,46 @@ function scheduler_pluginfile($course, $cm, $context, $filearea, $args, $forcedo if (!$scheduler->get_slot($entryid)) { return false; } - // No further access control required - everyone can see slots notes. + // No further access control required - everyone can see slots notes. } else if ($filearea === 'appointmentnote') { if (!$scheduler->uses_appointmentnotes()) { return false; } - list($slot, $app) = $scheduler->get_slot_appointment($entryid); + [$slot, $app] = $scheduler->get_slot_appointment($entryid); if (!$app) { return false; } $permissions->ensure($permissions->can_see_appointment($app)); - } else if ($filearea === 'teachernote') { if (!$scheduler->uses_teachernotes()) { return false; } - list($slot, $app) = $scheduler->get_slot_appointment($entryid); + [$slot, $app] = $scheduler->get_slot_appointment($entryid); if (!$app) { return false; } $permissions->ensure($permissions->teacher_can_see_slot($slot)); - } else if ($filearea === 'bookinginstructions') { - $caps = array('moodle/course:manageactivities', 'mod/scheduler:appoint'); + $caps = ['moodle/course:manageactivities', 'mod/scheduler:appoint']; if (!has_any_capability($caps, $context)) { return false; } - } else if ($filearea === 'studentfiles') { if (!$scheduler->uses_studentfiles()) { return false; } - list($slot, $app) = $scheduler->get_slot_appointment($entryid); + [$slot, $app] = $scheduler->get_slot_appointment($entryid); if (!$app) { return false; } $permissions->ensure($permissions->can_see_appointment($app)); - } else { // Unknown file area. return false; @@ -749,8 +765,10 @@ function scheduler_pluginfile($course, $cm, $context, $filearea, $args, $forcedo * @param \core_calendar\action_factory $factory * @return \core_calendar\local\event\entities\action_interface|null */ -function mod_scheduler_core_calendar_provide_event_action(calendar_event $event, - \core_calendar\action_factory $factory) { +function mod_scheduler_core_calendar_provide_event_action( + calendar_event $event, + \core_calendar\action_factory $factory +) { $cm = get_fast_modinfo($event->courseid)->instances['scheduler'][$event->instance]; $completion = new \completion_info($cm->get_course()); @@ -762,10 +780,20 @@ function mod_scheduler_core_calendar_provide_event_action(calendar_event $event, } return $factory->create_instance( - get_string('view'), - new \moodle_url('/mod/scheduler/view.php', ['id' => $cm->id]), - 1, - true + get_string('view'), + new \moodle_url('/mod/scheduler/view.php', ['id' => $cm->id]), + 1, + true ); } +/** + * Get icon mapping for font-awesome. + * + * @return array + */ +function mod_scheduler_get_fontawesome_icon_map() { + return [ + 'mod_scheduler:t/no' => 'fa-thumbs-down', + ]; +} diff --git a/locallib.php b/locallib.php index 60ce8232..4e9a5792 100644 --- a/locallib.php +++ b/locallib.php @@ -24,8 +24,8 @@ defined('MOODLE_INTERNAL') || die(); -require_once($CFG->libdir.'/filelib.php'); -require_once(dirname(__FILE__).'/customlib.php'); +require_once($CFG->libdir . '/filelib.php'); +require_once(dirname(__FILE__) . '/customlib.php'); /* Events related functions */ @@ -43,8 +43,8 @@ function scheduler_delete_calendar_events($slot) { $teachereventtype = "SSsup:{$slot->id}"; $studenteventtype = "SSstu:{$slot->id}"; - $teacherdeletionsuccess = $DB->delete_records('event', array('eventtype' => $teachereventtype)); - $studentdeletionsuccess = $DB->delete_records('event', array('eventtype' => $studenteventtype)); + $teacherdeletionsuccess = $DB->delete_records('event', ['eventtype' => $teachereventtype]); + $studentdeletionsuccess = $DB->delete_records('event', ['eventtype' => $studenteventtype]); return ($teacherdeletionsuccess && $studentdeletionsuccess); // This return may not be meaningful if the delete records functions do not return anything meaningful. @@ -64,7 +64,7 @@ function scheduler_delete_calendar_events($slot) { * @param bool $return whether the HTML fragment is to be returned as a string (otherwise printed) * @return string HTML fragment, if so selected */ -function scheduler_print_user($user, $course, $messageselect=false, $return=false) { +function scheduler_print_user($user, $course, $messageselect = false, $return = false) { global $CFG, $USER, $OUTPUT; @@ -82,7 +82,6 @@ function scheduler_print_user($user, $course, $messageselect=false, $return=fals } if (empty($string)) { // Cache all the strings for the rest of the page. - $string = new stdClass(); $string->email = get_string('email'); $string->lastaccess = get_string('lastaccess'); @@ -104,12 +103,11 @@ function scheduler_print_user($user, $course, $messageselect=false, $return=fals $datestring->secs = get_string('secs'); $datestring->year = get_string('year'); $datestring->years = get_string('years'); - } // Get the hidden field list. if (has_capability('moodle/course:viewhiddenuserfields', $context)) { - $hiddenfields = array(); + $hiddenfields = []; } else { $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields)); } @@ -117,13 +115,13 @@ function scheduler_print_user($user, $course, $messageselect=false, $return=fals $output .= ''; $output .= ''; $output .= ''; $output .= '
'; - $output .= $OUTPUT->user_picture($user, array('size' => 100)); + $output .= $OUTPUT->user_picture($user, ['size' => 100]); $output .= ''; - $output .= '
'.fullname($user, has_capability('moodle/site:viewfullnames', $context)).'
'; + $output .= '
' . fullname($user, has_capability('moodle/site:viewfullnames', $context)) . '
'; $output .= '
'; if (!empty($user->role) && ($user->role <> $course->teacher)) { - $output .= $string->role .': '. $user->role .'
'; + $output .= $string->role . ': ' . $user->role . '
'; } $extrafields = scheduler_get_user_fields($user, $context); @@ -133,33 +131,41 @@ function scheduler_print_user($user, $course, $messageselect=false, $return=fals if (!isset($hiddenfields['lastaccess'])) { if ($user->lastaccess) { - $output .= $string->lastaccess .': '. userdate($user->lastaccess); - $output .= '  ('. format_time(time() - $user->lastaccess, $datestring) .')'; + $output .= $string->lastaccess . ': ' . userdate($user->lastaccess); + $output .= '  (' . format_time(time() - $user->lastaccess, $datestring) . ')'; } else { - $output .= $string->lastaccess .': '. $string->never; + $output .= $string->lastaccess . ': ' . $string->never; } } + $output .= '
'; @@ -178,7 +184,8 @@ function scheduler_print_user($user, $course, $messageselect=false, $return=fals * @copyright 2011 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_file_info extends file_info { +class scheduler_file_info extends file_info +{ /** @var stdClass Course object */ protected $course; /** @var stdClass Course module object */ @@ -216,12 +223,12 @@ public function __construct($browser, $course, $cm, $context, $areas, $filearea) * @return array with keys contextid, filearea, itemid, filepath and filename */ public function get_params() { - return array('contextid' => $this->context->id, + return ['contextid' => $this->context->id, 'component' => 'mod_scheduler', 'filearea' => $this->filearea, 'itemid' => null, 'filepath' => null, - 'filename' => null); + 'filename' => null, ]; } /** @@ -269,9 +276,9 @@ public function get_children() { private function get_filtered_children($extensions = '*', $countonly = false, $returnemptyfolders = false) { global $DB; - $params = array('contextid' => $this->context->id, + $params = ['contextid' => $this->context->id, 'component' => 'mod_scheduler', - 'filearea' => $this->filearea); + 'filearea' => $this->filearea, ]; $sql = "SELECT DISTINCT f.itemid AS id FROM {files} f WHERE f.contextid = :contextid @@ -281,26 +288,30 @@ private function get_filtered_children($extensions = '*', $countonly = false, $r $sql .= ' AND filename <> :emptyfilename'; $params['emptyfilename'] = '.'; } - list($sql2, $params2) = $this->build_search_files_sql($extensions, 'f'); - $sql .= ' '.$sql2; + + [$sql2, $params2] = $this->build_search_files_sql($extensions, 'f'); + $sql .= ' ' . $sql2; $params = array_merge($params, $params2); $rs = $DB->get_recordset_sql($sql, $params); - $children = array(); + $children = []; foreach ($rs as $record) { if ($child = $this->browser->get_file_info($this->context, 'mod_scheduler', $this->filearea, $record->id)) { if ($returnemptyfolders || $child->count_non_empty_children($extensions)) { $children[] = $child; } } + if ($countonly !== false && count($children) >= $countonly) { break; } } + $rs->close(); if ($countonly !== false) { return count($children); } + return $children; } diff --git a/mailtemplatelib.php b/mailtemplatelib.php index 85d6ad3b..3a0353c8 100644 --- a/mailtemplatelib.php +++ b/mailtemplatelib.php @@ -22,8 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -use \mod_scheduler\model\scheduler; -use \mod_scheduler\model\slot; +use mod_scheduler\model\scheduler; +use mod_scheduler\model\slot; /** * Message functionality for scheduler module @@ -32,7 +32,8 @@ * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_messenger { +class scheduler_messenger +{ /** * Returns the language to be used in a message to a user * @@ -43,12 +44,12 @@ class scheduler_messenger { * @return string */ protected static function get_message_language($user, $course) { - if ($course && ! empty ($course->id) && $course->id != SITEID && !empty($course->lang)) { + if ($course && ! empty($course->id) && $course->id != SITEID && !empty($course->lang)) { // Course language overrides user language. $return = $course->lang; } else if (!empty($user->lang)) { $return = $user->lang; - } else if (isset ($CFG->lang)) { + } else if (isset($CFG->lang)) { $return = $CFG->lang; } else { $return = 'en'; @@ -71,10 +72,11 @@ protected static function get_message_language($user, $course) { * */ public static function compile_mail_template($template, $format, $parameters, $module = 'scheduler', $lang = null) { - $params = array (); + $params = []; foreach ($parameters as $key => $value) { $params[strtolower($key)] = $value; } + $mailstr = get_string_manager()->get_string("email_{$template}_{$format}", $module, $params, $lang); return $mailstr; } @@ -101,21 +103,28 @@ public static function compile_mail_template($template, $format, $parameters, $m * a hash containing pairs of parm => data to replace in template * @return bool|int Returns message id if message was sent OK, "false" if there was another sort of error. */ - public static function send_message_from_template($modulename, $messagename, $isnotification, - stdClass $sender, stdClass $recipient, $course, - $template, array $parameters) { + public static function send_message_from_template( + $modulename, + $messagename, + $isnotification, + stdClass $sender, + stdClass $recipient, + $course, + $template, + array $parameters + ) { global $CFG; global $SITE; $lang = self::get_message_language($recipient, $course); - $defaultvars = array ( + $defaultvars = [ 'SITE' => $SITE->fullname, 'SITE_SHORT' => $SITE->shortname, 'SITE_URL' => $CFG->wwwroot, - 'SENDER' => fullname ( $sender ), - 'RECIPIENT' => fullname ( $recipient ) - ); + 'SENDER' => fullname($sender), + 'RECIPIENT' => fullname($recipient), + ]; if ($course) { $defaultvars['COURSE_SHORT'] = format_string($course->shortname); @@ -133,7 +142,7 @@ public static function send_message_from_template($modulename, $messagename, $is $message->subject = self::compile_mail_template($template, 'subject', $vars, $modulename, $lang); $message->fullmessage = self::compile_mail_template($template, 'plain', $vars, $modulename, $lang); $message->fullmessageformat = FORMAT_PLAIN; - $message->fullmessagehtml = self::compile_mail_template ( $template, 'html', $vars, $modulename, $lang ); + $message->fullmessagehtml = self::compile_mail_template($template, 'html', $vars, $modulename, $lang); $message->notification = '1'; $message->courseid = $course->id; $message->contexturl = $defaultvars['COURSE_URL']; @@ -156,9 +165,14 @@ public static function send_message_from_template($modulename, $messagename, $is * (used for determining the message language) * @return array A hash with mail template substitutions */ - public static function get_scheduler_variables(scheduler $scheduler, $slot, - $teacher, $student, $course, $recipient) { - + public static function get_scheduler_variables( + scheduler $scheduler, + $slot, + $teacher, + $student, + $course, + $recipient + ) { global $CFG; $lang = self::get_message_language($recipient, $course); @@ -167,33 +181,35 @@ public static function get_scheduler_variables(scheduler $scheduler, $slot, $tz = core_date::get_user_timezone($recipient); - $vars = array(); + $vars = []; if ($scheduler) { $vars['MODULE'] = format_string($scheduler->name); $vars['STAFFROLE'] = $scheduler->get_teacher_name(); - $vars['SCHEDULER_URL'] = $CFG->wwwroot.'/mod/scheduler/view.php?id='.$scheduler->cmid; + $vars['SCHEDULER_URL'] = $CFG->wwwroot . '/mod/scheduler/view.php?id=' . $scheduler->cmid; } + if ($slot) { $vars['DATE'] = userdate($slot->starttime, get_string('strftimedate'), $tz); $vars['TIME'] = userdate($slot->starttime, get_string('strftimetime'), $tz); $vars['ENDTIME'] = userdate($slot->endtime, get_string('strftimetime'), $tz); $vars['LOCATION'] = format_string($slot->appointmentlocation); } + if ($teacher) { $vars['ATTENDANT'] = fullname($teacher); - $vars['ATTENDANT_URL'] = $CFG->wwwroot.'/user/view.php?id='.$teacher->id.'&course='.$scheduler->course; + $vars['ATTENDANT_URL'] = $CFG->wwwroot . '/user/view.php?id=' . $teacher->id . '&course=' . $scheduler->course; } + if ($student) { $vars['ATTENDEE'] = fullname($student); - $vars['ATTENDEE_URL'] = $CFG->wwwroot.'/user/view.php?id='.$student->id.'&course='.$scheduler->course; + $vars['ATTENDEE_URL'] = $CFG->wwwroot . '/user/view.php?id=' . $student->id . '&course=' . $scheduler->course; } // Reset language settings. force_current_language($oldlang); return $vars; - } @@ -209,11 +225,17 @@ public static function get_scheduler_variables(scheduler $scheduler, $slot, * @param stdClass $student user record for student * @param stdClass $course course record */ - public static function send_slot_notification(slot $slot, $messagename, $template, - stdClass $sender, stdClass $recipient, - stdClass $teacher, stdClass $student, stdClass $course) { + public static function send_slot_notification( + slot $slot, + $messagename, + $template, + stdClass $sender, + stdClass $recipient, + stdClass $teacher, + stdClass $student, + stdClass $course + ) { $vars = self::get_scheduler_variables($slot->get_scheduler(), $slot, $teacher, $student, $course, $recipient); self::send_message_from_template('mod_scheduler', $messagename, 1, $sender, $recipient, $course, $template, $vars); } - } diff --git a/message_form.php b/message_form.php index db55ea83..250353df 100644 --- a/message_form.php +++ b/message_form.php @@ -26,7 +26,7 @@ defined('MOODLE_INTERNAL') || die(); -require_once($CFG->libdir.'/formslib.php'); +require_once($CFG->libdir . '/formslib.php'); /** * Message form for invitations (using Moodle formslib) @@ -35,8 +35,8 @@ * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_message_form extends moodleform { - +class scheduler_message_form extends moodleform +{ /** * @var scheduler scheduler in whose context the messages are sent */ @@ -49,7 +49,7 @@ class scheduler_message_form extends moodleform { * @param scheduler $scheduler scheduler in whose context the messages are sent * @param object $customdata */ - public function __construct($action, scheduler $scheduler, $customdata=null) { + public function __construct($action, scheduler $scheduler, $customdata = null) { $this->scheduler = $scheduler; parent::__construct($action, $customdata); } @@ -62,21 +62,23 @@ protected function definition() { $mform = $this->_form; // Select users to sent the message to. - $checkboxes = array(); + $checkboxes = []; $recipients = $this->_customdata['recipients']; foreach ($recipients as $recipient) { - $inputid = 'recipient['.$recipient->id.']'; + $inputid = 'recipient[' . $recipient->id . ']'; $label = fullname($recipient); $checkboxes[] = $mform->createElement('checkbox', $inputid, '', $label); $mform->setDefault($inputid, true); } + $mform->addGroup($checkboxes, 'recipients', get_string('recipients', 'scheduler'), null, false); if (get_config('mod_scheduler', 'showemailplain')) { - $maillist = array(); + $maillist = []; foreach ($recipients as $recipient) { $maillist[] = trim($recipient->email); } + $maildisplay = html_writer::div(implode(', ', $maillist)); $mform->addElement('html', $maildisplay); } @@ -84,25 +86,29 @@ protected function definition() { $mform->addElement('selectyesno', 'copytomyself', get_string('copytomyself', 'scheduler')); $mform->setDefault('copytomyself', true); - $mform->addElement('text', 'subject', get_string('messagesubject', 'scheduler'), array('size' => '60')); + $mform->addElement('text', 'subject', get_string('messagesubject', 'scheduler'), ['size' => '60']); $mform->setType('subject', PARAM_TEXT); $mform->addRule('subject', null, 'required'); if (isset($this->_customdata['subject'])) { $mform->setDefault('subject', $this->_customdata['subject']); } - $bodyedit = $mform->addElement('editor', 'body', get_string('messagebody', 'scheduler'), - array('rows' => 15, 'columns' => 60), array('collapsed' => true)); + $bodyedit = $mform->addElement( + 'editor', + 'body', + get_string('messagebody', 'scheduler'), + ['rows' => 15, 'columns' => 60], + ['collapsed' => true] + ); $mform->setType('body', PARAM_RAW); // Must be PARAM_RAW for rich text editor content. if (isset($this->_customdata['body'])) { - $bodyedit->setValue(array('text' => $this->_customdata['body'])); + $bodyedit->setValue(['text' => $this->_customdata['body']]); } - $buttonarray = array(); + $buttonarray = []; $buttonarray[] = $mform->createElement('submit', 'submitbutton', get_string('sendmessage', 'scheduler')); $buttonarray[] = $mform->createElement('cancel'); - $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false); - + $mform->addGroup($buttonarray, 'buttonar', '', [' '], false); } /** @@ -118,5 +124,4 @@ public function validation($data, $files) { return $errors; } - } diff --git a/mod_form.php b/mod_form.php index 4dccef8c..d2ac522d 100644 --- a/mod_form.php +++ b/mod_form.php @@ -33,8 +33,8 @@ * @copyright 2011 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class mod_scheduler_mod_form extends moodleform_mod { - +class mod_scheduler_mod_form extends moodleform_mod +{ /** @var array */ protected $editoroptions; @@ -49,12 +49,13 @@ public function definition() { // General introduction. $mform->addElement('header', 'general', get_string('general', 'form')); - $mform->addElement('text', 'name', get_string('name'), array('size' => '64')); + $mform->addElement('text', 'name', get_string('name'), ['size' => '64']); if (!empty($CFG->formatstringstriptags)) { $mform->setType('name', PARAM_TEXT); } else { $mform->setType('name', PARAM_CLEANHTML); } + $mform->addRule('name', null, 'required', null, 'client'); $mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255, 'client'); @@ -64,19 +65,20 @@ public function definition() { $mform->addElement('header', 'optionhdr', get_string('options', 'scheduler')); $mform->setExpanded('optionhdr'); - $mform->addElement('text', 'staffrolename', get_string('staffrolename', 'scheduler'), array('size' => '48')); + $mform->addElement('text', 'staffrolename', get_string('staffrolename', 'scheduler'), ['size' => '48']); $mform->setType('staffrolename', PARAM_TEXT); $mform->addRule('staffrolename', get_string('error'), 'maxlength', 255); $mform->addHelpButton('staffrolename', 'staffrolename', 'scheduler'); - $modegroup = array(); + $modegroup = []; $modegroup[] = $mform->createElement('static', 'modeintro', '', get_string('modeintro', 'scheduler')); - $maxbookoptions = array(); + $maxbookoptions = []; $maxbookoptions['0'] = get_string('unlimited', 'scheduler'); for ($i = 1; $i <= 10; $i++) { $maxbookoptions[(string)$i] = $i; } + $modegroup[] = $mform->createElement('select', 'maxbookings', '', $maxbookoptions); $mform->setDefault('maxbookings', 1); @@ -91,23 +93,24 @@ public function definition() { $mform->addHelpButton('modegrp', 'appointmentmode', 'scheduler'); if (get_config('mod_scheduler', 'groupscheduling')) { - $selopt = array( + $selopt = [ -1 => get_string('no'), - 0 => get_string('yesallgroups', 'scheduler') - ); + 0 => get_string('yesallgroups', 'scheduler'), + ]; $groupings = groups_get_all_groupings($COURSE->id); foreach ($groupings as $grouping) { $selopt[$grouping->id] = get_string('yesingrouping', 'scheduler', $grouping->name); } + $mform->addElement('select', 'bookingrouping', get_string('groupbookings', 'scheduler'), $selopt); $mform->addHelpButton('bookingrouping', 'groupbookings', 'scheduler'); $mform->setDefault('bookingrouping', '-1'); } - $mform->addElement('duration', 'guardtime', get_string('guardtime', 'scheduler'), array('optional' => true)); + $mform->addElement('duration', 'guardtime', get_string('guardtime', 'scheduler'), ['optional' => true]); $mform->addHelpButton('guardtime', 'guardtime', 'scheduler'); - $mform->addElement('text', 'defaultslotduration', get_string('defaultslotduration', 'scheduler'), array('size' => '2')); + $mform->addElement('text', 'defaultslotduration', get_string('defaultslotduration', 'scheduler'), ['size' => '2']); $mform->setType('defaultslotduration', PARAM_INT); $mform->addHelpButton('defaultslotduration', 'defaultslotduration', 'scheduler'); $mform->setDefault('defaultslotduration', 15); @@ -139,10 +142,15 @@ public function definition() { $mform->addElement('selectyesno', 'usebookingform', get_string('usebookingform', 'scheduler')); $mform->addHelpButton('usebookingform', 'usebookingform', 'scheduler'); - $this->editoroptions = array('trusttext' => true, 'maxfiles' => -1, 'maxbytes' => 0, - 'context' => $this->context, 'collapsed' => true); - $mform->addElement('editor', 'bookinginstructions_editor', get_string('bookinginstructions', 'scheduler'), - array('rows' => 3, 'columns' => 60), $this->editoroptions); + $this->editoroptions = ['trusttext' => true, 'maxfiles' => -1, 'maxbytes' => 0, + 'context' => $this->context, 'collapsed' => true, ]; + $mform->addElement( + 'editor', + 'bookinginstructions_editor', + get_string('bookinginstructions', 'scheduler'), + ['rows' => 3, 'columns' => 60], + $this->editoroptions + ); $mform->setType('bookinginstructions', PARAM_RAW); // Must be PARAM_RAW for rich text editor content. $mform->disabledIf('bookinginstructions_editor', 'usebookingform', 'eq', '0'); $mform->addHelpButton('bookinginstructions_editor', 'bookinginstructions', 'scheduler'); @@ -155,12 +163,13 @@ public function definition() { $mform->disabledIf('usestudentnotes', 'usebookingform', 'eq', '0'); $mform->addHelpButton('usestudentnotes', 'usestudentnotes', 'scheduler'); - $uploadgroup = array(); + $uploadgroup = []; - $filechoices = array(); + $filechoices = []; for ($i = 0; $i <= get_config('mod_scheduler', 'uploadmaxfiles'); $i++) { $filechoices[$i] = $i; } + $uploadgroup[] = $mform->createElement('select', 'uploadmaxfiles', get_string('uploadmaxfiles', 'scheduler'), $filechoices); $mform->setDefault('uploadmaxfiles', 0); $mform->disabledIf('uploadmaxfiles', 'usebookingform', 'eq', '0'); @@ -202,11 +211,18 @@ public function definition() { public function data_preprocessing(&$defaultvalues) { parent::data_preprocessing($defaultvalues); if ($this->current->instance) { - $newvalues = file_prepare_standard_editor((object)$defaultvalues, 'bookinginstructions', - $this->editoroptions, $this->context, - 'mod_scheduler', 'bookinginstructions', 0); + $newvalues = file_prepare_standard_editor( + (object)$defaultvalues, + 'bookinginstructions', + $this->editoroptions, + $this->context, + 'mod_scheduler', + 'bookinginstructions', + 0 + ); $defaultvalues['bookinginstructions_editor'] = $newvalues->bookinginstructions_editor; } + if (array_key_exists('scale', $defaultvalues)) { $dgrade = $defaultvalues['scale']; $defaultvalues['grade'] = $dgrade; @@ -216,6 +232,7 @@ public function data_preprocessing(&$defaultvalues) { } else if ($dgrade < 0) { $type = 'scale'; } + $defaultvalues['grade[modgrade_type]'] = $type; } } @@ -231,14 +248,17 @@ public function save_mod_data(stdClass $data, context_module $context) { $editor = $data->bookinginstructions_editor; if ($editor && array_key_exists('text', $editor)) { - $data->bookinginstructions = file_save_draft_area_files($editor['itemid'], $context->id, - 'mod_scheduler', 'bookinginstructions', 0, - $this->editoroptions, $editor['text']); + $data->bookinginstructions = file_save_draft_area_files( + $editor['itemid'], + $context->id, + 'mod_scheduler', + 'bookinginstructions', + 0, + $this->editoroptions, + $editor['text'] + ); $data->bookinginstructionsformat = $editor['format']; $DB->update_record('scheduler', $data); } } - - - } diff --git a/pix/t/no.svg b/pix/t/no.svg new file mode 100644 index 00000000..7408c22a --- /dev/null +++ b/pix/t/no.svg @@ -0,0 +1 @@ + diff --git a/renderable.php b/renderable.php index 38c3bb7f..951f9e2f 100644 --- a/renderable.php +++ b/renderable.php @@ -24,9 +24,11 @@ defined('MOODLE_INTERNAL') || die(); -use \mod_scheduler\model\scheduler; -use \mod_scheduler\model\slot; -use \mod_scheduler\model\appointment; +use mod_scheduler\model\scheduler; +use mod_scheduler\model\slot; +use mod_scheduler\model\appointment; + +// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses /** * This class represents a table of slots associated with one student @@ -34,10 +36,10 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_slot_table implements renderable { - +class scheduler_slot_table implements renderable +{ /** @var array list of slots in this table */ - public $slots = array(); + public $slots = []; /** @var scheduler the scheduler that the slots are in */ public $scheduler; @@ -82,13 +84,20 @@ class scheduler_slot_table implements renderable { * @param bool $canedit whether the user can edit the slot/appointment * @param bool $canview whether the user can view the appointment */ - public function add_slot(slot $slotmodel, appointment $appointmentmodel, - $otherstudents, $cancancel = false, $canedit = false, $canview = false) { + public function add_slot( + slot $slotmodel, + appointment $appointmentmodel, + $otherstudents, + $cancancel = false, + $canedit = false, + $canview = false + ) { $slot = new stdClass(); $slot->slotid = $slotmodel->id; if ($this->showstudent) { $slot->student = $appointmentmodel->student; } + $slot->starttime = $slotmodel->starttime; $slot->endtime = $slotmodel->endtime; $slot->attended = $appointmentmodel->attended; @@ -101,10 +110,12 @@ public function add_slot(slot $slotmodel, appointment $appointmentmodel, $slot->appointmentnote = $appointmentmodel->appointmentnote; $slot->appointmentnoteformat = $appointmentmodel->appointmentnoteformat; } + if ($this->scheduler->uses_teachernotes() && $this->showteachernotes) { $slot->teachernote = $appointmentmodel->teachernote; $slot->teachernoteformat = $appointmentmodel->teachernoteformat; } + $slot->otherstudents = $otherstudents; $slot->cancancel = $cancancel; $slot->canedit = $canedit; @@ -112,6 +123,7 @@ public function add_slot(slot $slotmodel, appointment $appointmentmodel, if ($this->showgrades) { $slot->grade = $appointmentmodel->grade; } + $this->showactions = $this->showactions || $cancancel; $this->hasotherstudents = $this->hasotherstudents || (bool) $otherstudents; @@ -125,12 +137,11 @@ public function add_slot(slot $slotmodel, appointment $appointmentmodel, * @param bool $showgrades whether to show grades * @param moodle_url|null $actionurl action URL for buttons */ - public function __construct(scheduler $scheduler, $showgrades=true, $actionurl = null) { + public function __construct(scheduler $scheduler, $showgrades = true, $actionurl = null) { $this->scheduler = $scheduler; $this->showgrades = $showgrades && $scheduler->uses_grades(); $this->actionurl = $actionurl; } - } @@ -140,10 +151,10 @@ public function __construct(scheduler $scheduler, $showgrades=true, $actionurl = * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_student_list implements renderable { - +class scheduler_student_list implements renderable +{ /** @var array list of students to be displayed */ - public $students = array(); + public $students = []; /** @var scheduler the scheduler in whose context the list is */ public $scheduler; @@ -182,8 +193,14 @@ class scheduler_student_list implements renderable { * @param bool $showstudprovided whether to show an icon for student-provided files * @param bool $editattended whether to make the attended tickbox editable */ - public function add_student(appointment $appointment, $highlight, $checked = false, - $showgrade = true, $showstudprovided = false, $editattended = false) { + public function add_student( + appointment $appointment, + $highlight, + $checked = false, + $showgrade = true, + $showstudprovided = false, + $editattended = false + ) { $student = new stdClass(); $student->user = $appointment->get_student(); if ($this->showgrades && $showgrade) { @@ -191,6 +208,7 @@ public function add_student(appointment $appointment, $highlight, $checked = fal } else { $student->grade = null; } + $student->highlight = $highlight; $student->checked = $checked; $student->editattended = $editattended; @@ -204,6 +222,7 @@ public function add_student(appointment $appointment, $highlight, $checked = fal $student->filesprovided = $appointment->count_studentfiles(); } } + $this->students[] = $student; } @@ -217,7 +236,6 @@ public function __construct(scheduler $scheduler, $showgrades = true) { $this->scheduler = $scheduler; $this->showgrades = $showgrades; } - } @@ -227,12 +245,12 @@ public function __construct(scheduler $scheduler, $showgrades = true) { * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_slot_booker implements renderable { - +class scheduler_slot_booker implements renderable +{ /** * @var array list of slots to be displayed */ - public $slots = array(); + public $slots = []; /** * @var scheduler scheduler in whose context the list is @@ -288,7 +306,6 @@ public function __construct(scheduler $scheduler, $studentid, moodle_url $action $this->studentid = $studentid; $this->actionurl = $actionurl; } - } /** @@ -297,17 +314,17 @@ public function __construct(scheduler $scheduler, $studentid, moodle_url $action * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_command_bar implements renderable { - +class scheduler_command_bar implements renderable +{ /** * @var array list of drop-down menus in the command bar */ - public $menus = array(); + public $menus = []; /** * @var array list of action_link objects used in the menu */ - public $linkactions = array(); + public $linkactions = []; /** * @var string title of the menu @@ -338,15 +355,17 @@ public function add_group($title, array $actions) { */ public function action_link(moodle_url $url, $titlekey, $iconkey, $confirmkey = null, $id = null) { $title = get_string($titlekey, 'scheduler'); - $pix = new pix_icon($iconkey, $title, 'moodle', array('class' => 'iconsmall', 'title' => '')); - $attributes = array(); + $pix = new pix_icon($iconkey, $title, 'moodle', ['class' => 'iconsmall', 'title' => '']); + $attributes = []; if ($id) { $attributes['id'] = $id; } + $confirmaction = null; if ($confirmkey) { $confirmaction = new confirm_action(get_string($confirmkey, 'scheduler')); } + $act = new action_link($url, $title, $confirmaction, $attributes, $pix); return $act; } @@ -363,15 +382,17 @@ public function action_link(moodle_url $url, $titlekey, $iconkey, $confirmkey = */ public function action_menu_link(moodle_url $url, $titlekey, $iconkey, $confirmkey = null, $id = null) { $title = get_string($titlekey, 'scheduler'); - $pix = new pix_icon($iconkey, $title, 'moodle', array('class' => 'iconsmall', 'title' => '')); - $attributes = array(); + $pix = new pix_icon($iconkey, $title, 'moodle', ['class' => 'iconsmall', 'title' => '']); + $attributes = []; if ($id) { $attributes['id'] = $id; } + $act = new action_menu_link($url, $pix, $title, false, $attributes); if ($confirmkey) { $act->add_action(new confirm_action(get_string($confirmkey, 'scheduler'))); } + return $act; } @@ -381,7 +402,6 @@ public function action_menu_link(moodle_url $url, $titlekey, $iconkey, $confirmk public function __construct() { // Nothing to add right now. } - } /** @@ -390,12 +410,12 @@ public function __construct() { * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_slot_manager implements renderable { - +class scheduler_slot_manager implements renderable +{ /** * @var array list of slots */ - public $slots = array(); + public $slots = []; /** * @var scheduler scheduler in whose context the list is @@ -445,7 +465,6 @@ public function __construct(scheduler $scheduler, moodle_url $actionurl) { $this->scheduler = $scheduler; $this->actionurl = $actionurl; } - } @@ -455,12 +474,12 @@ public function __construct(scheduler $scheduler, moodle_url $actionurl) { * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_scheduling_list implements renderable { - +class scheduler_scheduling_list implements renderable +{ /** * @var array lines in the list */ - public $lines = array(); + public $lines = []; /** * @var scheduler the scheduler in whose context the list is @@ -505,7 +524,6 @@ public function __construct(scheduler $scheduler, array $extraheaders) { $this->scheduler = $scheduler; $this->extraheaders = $extraheaders; } - } /** @@ -516,8 +534,8 @@ public function __construct(scheduler $scheduler, array $extraheaders) { * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_totalgrade_info implements renderable { - +class scheduler_totalgrade_info implements renderable +{ /** * @var stdClass|null gradebook grade for the student */ @@ -552,7 +570,6 @@ public function __construct(scheduler $scheduler, $gbgrade, $showtotalgrade = fa $this->showtotalgrade = $showtotalgrade; $this->totalgrade = $totalgrade; } - } /** @@ -561,12 +578,12 @@ public function __construct(scheduler $scheduler, $gbgrade, $showtotalgrade = fa * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_conflict_list implements renderable { - +class scheduler_conflict_list implements renderable +{ /** * @var array list of conflicts */ - public $conflicts = array(); + public $conflicts = []; /** * Add a conflict to the list. @@ -581,6 +598,7 @@ public function add_conflict(stdClass $conflict, $user = null) { } else { $c->userfullname = ''; } + $this->conflicts[] = $c; } @@ -594,7 +612,6 @@ public function add_conflicts(array $conflicts) { $this->add_conflict($c); } } - } /** @@ -603,8 +620,8 @@ public function add_conflicts(array $conflicts) { * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_appointment_info implements renderable { - +class scheduler_appointment_info implements renderable +{ /** * @var scheduler scheduler in whose context the appointment is */ @@ -650,6 +667,11 @@ class scheduler_appointment_info implements renderable { */ public $showresult; + /** + * @var bool whether to show booking info + */ + public $showboookinginfo; + /** * Create appointment information for a new appointment in a slot. * @@ -659,8 +681,12 @@ class scheduler_appointment_info implements renderable { * @param string $groupinfo information about the group that the booking is for * @return scheduler_appointment_info */ - public static function make_from_slot(slot $slot, $showbookinginstr = true, $onstudentside = true, - $groupinfo = null) { + public static function make_from_slot( + slot $slot, + $showbookinginstr = true, + $onstudentside = true, + $groupinfo = null + ) { $info = new scheduler_appointment_info(); $info->slot = $slot; $info->scheduler = $slot->get_scheduler(); @@ -688,7 +714,7 @@ public static function make_from_appointment(slot $slot, appointment $appointmen $info->appointment = $appointment; $info->scheduler = $slot->get_scheduler(); $info->showslotinfo = true; - $info->showboookinginfo = true; + $info->showbookinginfo = true; $info->showstudentdata = $info->scheduler->uses_studentdata(); $info->showresult = true; $info->onstudentside = $onstudentside; @@ -711,7 +737,7 @@ public static function make_for_teacher(slot $slot, appointment $appointment) { $info->appointment = $appointment; $info->scheduler = $slot->get_scheduler(); $info->showslotinfo = true; - $info->showboookinginfo = false; + $info->showbookinginfo = false; $info->showstudentdata = $info->scheduler->uses_studentdata(); $info->showresult = false; $info->onstudentside = false; diff --git a/renderer.php b/renderer.php index e5e53f3e..f53bbc6c 100644 --- a/renderer.php +++ b/renderer.php @@ -24,8 +24,9 @@ defined('MOODLE_INTERNAL') || die(); -use \mod_scheduler\model\scheduler; -use \mod_scheduler\permission\scheduler_permissions; +use mod_scheduler\model\scheduler; +use mod_scheduler\output\thumbsdown_icon; +use mod_scheduler\permission\scheduler_permissions; require_once($CFG->dirroot . '/mod/assign/locallib.php'); @@ -35,8 +36,8 @@ * @copyright 2016 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class mod_scheduler_renderer extends plugin_renderer_base { - +class mod_scheduler_renderer extends plugin_renderer_base +{ /** * Constructor method, calls the parent constructor * @@ -75,9 +76,11 @@ public static function usertime($date) { if (empty($timeformat)) { $timeformat = get_config(null, 'calendar_site_timeformat'); // Get calendar config if above not exist. } + if (empty($timeformat)) { $timeformat = get_string('strftimetime'); // Get locale default format if both of the above do not exist. } + return userdate($date, $timeformat); } } @@ -107,7 +110,7 @@ public static function slotdatetime($slotdate, $duration) { /** * @var array a cached version of scale levels */ - protected $scalecache = array(); + protected $scalecache = []; /** * Get a list of levels in a grading scale. @@ -119,14 +122,15 @@ public function get_scale_levels($scaleid) { global $DB; if (!array_key_exists($scaleid, $this->scalecache)) { - $this->scalecache[$scaleid] = array(); - if ($scale = $DB->get_record('scale', array('id' => $scaleid))) { + $this->scalecache[$scaleid] = []; + if ($scale = $DB->get_record('scale', ['id' => $scaleid])) { $levels = explode(',', $scale->scale); foreach ($levels as $levelid => $value) { $this->scalecache[$scaleid][$levelid + 1] = $value; } } } + return $this->scalecache[$scaleid]; } @@ -148,7 +152,7 @@ public function format_grade($subject, $grade, $short = false, $decimals = 0) { } $result = ''; - if ($scaleid == 0 || is_null($grade) ) { + if ($scaleid == 0 || is_null($grade)) { // Scheduler doesn't allow grading, or no grade entered. if (!$short) { $result = get_string('nograde'); @@ -171,10 +175,12 @@ public function format_grade($subject, $grade, $short = false, $decimals = 0) { } } } + if ($short && (strlen($result) > 0)) { - $result = '('.$result.')'; + $result = '(' . $result . ')'; } } + return $result; } @@ -189,7 +195,7 @@ public function format_grade($subject, $grade, $short = false, $decimals = 0) { */ public function grading_choices($scheduler) { if ($scheduler->scale > 0) { - $scalegrades = array(); + $scalegrades = []; for ($i = 0; $i <= $scheduler->scale; $i++) { $scalegrades[$i] = $i; } @@ -197,7 +203,8 @@ public function grading_choices($scheduler) { $scaleid = - ($scheduler->scale); $scalegrades = $this->get_scale_levels($scaleid); } - $scalegrades = array(-1 => get_string('nograde')) + $scalegrades; + + $scalegrades = [-1 => get_string('nograde')] + $scalegrades; return $scalegrades; } @@ -243,13 +250,25 @@ public function format_appointment_notes(scheduler $scheduler, $data, $idfield = $note = ''; $id = $data->{$idfield}; if (isset($data->appointmentnote) && $scheduler->uses_appointmentnotes()) { - $note .= $this->format_notes($data->appointmentnote, $data->appointmentnoteformat, $scheduler->get_context(), - 'appointmentnote', $id); + $note .= $this->format_notes( + $data->appointmentnote, + $data->appointmentnoteformat, + $scheduler->get_context(), + 'appointmentnote', + $id + ); } + if (isset($data->teachernote) && $scheduler->uses_teachernotes()) { - $note .= $this->format_notes($data->teachernote, $data->teachernoteformat, $scheduler->get_context(), - 'teachernote', $id); + $note .= $this->format_notes( + $data->teachernote, + $data->teachernoteformat, + $scheduler->get_context(), + 'teachernote', + $id + ); } + return $note; } @@ -262,7 +281,7 @@ public function format_appointment_notes(scheduler $scheduler, $data, $idfield = * @return string HTML code of the link */ public function user_profile_link(scheduler $scheduler, stdClass $user) { - $profileurl = new moodle_url('/user/view.php', array('id' => $user->id, 'course' => $scheduler->course)); + $profileurl = new moodle_url('/user/view.php', ['id' => $user->id, 'course' => $scheduler->course]); return html_writer::link($profileurl, fullname($user)); } @@ -276,11 +295,11 @@ public function user_profile_link(scheduler $scheduler, stdClass $user) { * @return string HTML code of the link */ public function appointment_link($scheduler, $user, $appointmentid) { - $paras = array( + $paras = [ 'what' => 'viewstudent', 'id' => $scheduler->cmid, - 'appointmentid' => $appointmentid - ); + 'appointmentid' => $appointmentid, + ]; $url = new moodle_url('/mod/scheduler/view.php', $paras); return html_writer::link($url, fullname($user)); } @@ -302,18 +321,23 @@ public function render_attachments($contextid, $filearea, $itemid) { // at the sametime (e.g. in the case of drag/drop upload) we revert to using the filename. $files = $fs->get_area_files($contextid, 'mod_scheduler', $filearea, $itemid, "filename", false); if ($files) { - $o .= html_writer::start_tag('ul', array('class' => 'scheduler_filelist')); + $o .= html_writer::start_tag('ul', ['class' => 'scheduler_filelist']); foreach ($files as $file) { $filename = $file->get_filename(); $pathname = $file->get_filepath(); $mimetype = $file->get_mimetype(); - $iconimage = $this->pix_icon(file_file_icon($file), get_mimetype_description($file), - 'moodle', array('class' => 'icon')); + $iconimage = $this->pix_icon( + file_file_icon($file), + get_mimetype_description($file), + 'moodle', + ['class' => 'icon'] + ); $path = moodle_url::make_pluginfile_url($contextid, 'mod_scheduler', $filearea, $itemid, $pathname, $filename); $ulitem = html_writer::link($path, $iconimage) . html_writer::link($path, s($filename)); $o .= html_writer::tag('ul', $ulitem); } + $o .= html_writer::end_tag('ul'); } @@ -332,7 +356,7 @@ public function render_attachments($contextid, $filearea, $itemid) { * @return tabobject */ private function teacherview_tab(moodle_url $baseurl, $namekey, $what, $subpage = '', $nameargs = null) { - $taburl = new moodle_url($baseurl, array('what' => $what, 'subpage' => $subpage)); + $taburl = new moodle_url($baseurl, ['what' => $what, 'subpage' => $subpage]); $tabname = get_string($namekey, 'scheduler', $nameargs); $id = ($subpage != '') ? $subpage : $what; $tab = new tabobject($id, $taburl, $tabname); @@ -349,24 +373,34 @@ private function teacherview_tab(moodle_url $baseurl, $namekey, $what, $subpage * @param array $inactive any inactive tabs * @return string rendered tab tree */ - public function teacherview_tabs(scheduler $scheduler, scheduler_permissions $permissions, - moodle_url $baseurl, $selected, $inactive = null) { - + public function teacherview_tabs( + scheduler $scheduler, + scheduler_permissions $permissions, + moodle_url $baseurl, + $selected, + $inactive = null + ) { $statstab = $this->teacherview_tab($baseurl, 'statistics', 'viewstatistics', 'overall'); - $statstab->subtree = array( + $statstab->subtree = [ $this->teacherview_tab($baseurl, 'overall', 'viewstatistics', 'overall'), $this->teacherview_tab($baseurl, 'studentbreakdown', 'viewstatistics', 'studentbreakdown'), - $this->teacherview_tab($baseurl, 'staffbreakdown', 'viewstatistics', 'staffbreakdown', - $scheduler->get_teacher_name()), + $this->teacherview_tab( + $baseurl, + 'staffbreakdown', + 'viewstatistics', + 'staffbreakdown', + $scheduler->get_teacher_name() + ), $this->teacherview_tab($baseurl, 'lengthbreakdown', 'viewstatistics', 'lengthbreakdown'), - $this->teacherview_tab($baseurl, 'groupbreakdown', 'viewstatistics', 'groupbreakdown') - ); + $this->teacherview_tab($baseurl, 'groupbreakdown', 'viewstatistics', 'groupbreakdown'), + ]; - $level1 = array(); + $level1 = []; $level1[] = $this->teacherview_tab($baseurl, 'myappointments', 'view', 'myappointments'); if ($permissions->can_see_all_slots()) { $level1[] = $this->teacherview_tab($baseurl, 'allappointments', 'view', 'allappointments'); } + $level1[] = $this->teacherview_tab($baseurl, 'datelist', 'datelist'); $level1[] = $statstab; $level1[] = $this->teacherview_tab($baseurl, 'export', 'export'); @@ -384,21 +418,25 @@ public function render_scheduler_slot_table(scheduler_slot_table $slottable) { $table = new html_table(); if ($slottable->showslot) { - $table->head = array(get_string('date', 'scheduler')); - $table->align = array('left'); + $table->head = [get_string('date', 'scheduler')]; + $table->align = ['left']; } + if ($slottable->showstudent) { $table->head[] = get_string('name'); $table->align[] = 'left'; } + if ($slottable->showattended) { $table->head[] = get_string('seen', 'scheduler'); $table->align[] = 'center'; } + if ($slottable->showslot) { $table->head[] = $slottable->scheduler->get_teacher_name(); $table->align[] = 'left'; } + if ($slottable->showslot && $slottable->showlocation) { $table->head[] = get_string('location', 'scheduler'); $table->align[] = 'left'; @@ -414,22 +452,24 @@ public function render_scheduler_slot_table(scheduler_slot_table $slottable) { $table->head[] = get_string('otherstudents', 'scheduler'); $table->align[] = 'left'; } + if ($slottable->showactions) { $table->head[] = ''; $table->align[] = 'right'; } - $table->data = array(); + $table->data = []; foreach ($slottable->slots as $slot) { - $rowdata = array(); + $rowdata = []; - $studenturl = new moodle_url($slottable->actionurl, array('appointmentid' => $slot->appointmentid)); + $studenturl = new moodle_url($slottable->actionurl, ['appointmentid' => $slot->appointmentid]); $timedata = $this->userdate($slot->starttime); if ($slottable->showeditlink) { $timedata = $this->action_link($studenturl, $timedata); } + $timedata = html_writer::div($timedata, 'datelabel'); $starttime = $this->usertime($slot->starttime); @@ -445,6 +485,7 @@ public function render_scheduler_slot_table(scheduler_slot_table $slottable) { if ($slottable->showeditlink) { $name = $this->action_link($studenturl, $name); } + $rowdata[] = $name; } @@ -465,9 +506,15 @@ public function render_scheduler_slot_table(scheduler_slot_table $slottable) { $notes = ''; if ($slottable->showslot && isset($slot->slotnote)) { - $notes .= $this->format_notes($slot->slotnote, $slot->slotnoteformat, - $slottable->scheduler->get_context(), 'slotnote', $slot->slotid); + $notes .= $this->format_notes( + $slot->slotnote, + $slot->slotnoteformat, + $slottable->scheduler->get_context(), + 'slotnote', + $slot->slotid + ); } + $notes .= $this->format_appointment_notes($slottable->scheduler, $slot, 'appointmentid'); $rowdata[] = $notes; @@ -478,30 +525,42 @@ public function render_scheduler_slot_table(scheduler_slot_table $slottable) { } else if ($slottable->showgrades) { $gradedata = $this->format_grade($slottable->scheduler, $slot->grade); } + $rowdata[] = $gradedata; } + if ($slottable->showactions) { $actions = ''; if ($slot->canedit) { - $buttonurl = new moodle_url($slottable->actionurl, - array('what' => 'editbooking', 'appointmentid' => $slot->appointmentid)); + $buttonurl = new moodle_url( + $slottable->actionurl, + ['what' => 'editbooking', 'appointmentid' => $slot->appointmentid] + ); $button = new single_button($buttonurl, get_string('editbooking', 'scheduler')); $actions .= $this->render($button); } + if ($slot->canview) { - $buttonurl = new moodle_url($slottable->actionurl, - array('what' => 'viewbooking', 'appointmentid' => $slot->appointmentid)); + $buttonurl = new moodle_url( + $slottable->actionurl, + ['what' => 'viewbooking', 'appointmentid' => $slot->appointmentid] + ); $button = new single_button($buttonurl, get_string('viewbooking', 'scheduler')); $actions .= $this->render($button); } + if ($slot->cancancel) { - $buttonurl = new moodle_url($slottable->actionurl, - array('what' => 'cancelbooking', 'slotid' => $slot->slotid)); + $buttonurl = new moodle_url( + $slottable->actionurl, + ['what' => 'cancelbooking', 'slotid' => $slot->slotid] + ); $button = new single_button($buttonurl, get_string('cancelbooking', 'scheduler')); $actions .= $this->render($button); } + $rowdata[] = $actions; } + $table->data[] = $rowdata; } @@ -521,20 +580,24 @@ public function render_scheduler_student_list(scheduler_student_list $studentlis $toggleid = html_writer::random_id('toggle'); if ($studentlist->expandable && count($studentlist->students) > 0) { - $this->page->requires->js_call_amd('mod_scheduler/studentlist', 'init', [$toggleid, (boolean) $studentlist->expanded]); + $this->page->requires->js_call_amd('mod_scheduler/studentlist', 'init', [$toggleid, (bool) $studentlist->expanded]); $imgclass = 'studentlist-togglebutton'; $alttext = get_string('showparticipants', 'scheduler'); - $o .= $this->output->pix_icon('t/switch', $alttext, 'moodle', - array('id' => $toggleid, 'class' => $imgclass)); + $o .= $this->output->pix_icon( + 't/switch', + $alttext, + 'moodle', + ['id' => $toggleid, 'class' => $imgclass] + ); } - $divprops = array('id' => 'list'.$toggleid); + $divprops = ['id' => 'list' . $toggleid]; $o .= html_writer::start_div('studentlist', $divprops); if (count($studentlist->students) > 0) { $editable = $studentlist->actionurl && $studentlist->editable; if ($editable) { - $o .= html_writer::start_tag('form', array('action' => $studentlist->actionurl, - 'method' => 'post', 'class' => 'studentselectform')); + $o .= html_writer::start_tag('form', ['action' => $studentlist->actionurl, + 'method' => 'post', 'class' => 'studentselectform', ]); } foreach ($studentlist->students as $student) { @@ -542,53 +605,65 @@ public function render_scheduler_student_list(scheduler_student_list $studentlis $checkbox = ''; if ($studentlist->checkboxname) { if ($student->editattended) { - $checkbox = html_writer::checkbox($studentlist->checkboxname, $student->entryid, $student->checked, '', - array('class' => 'studentselect')); + $checkbox = html_writer::checkbox( + $studentlist->checkboxname, + $student->entryid, + $student->checked, + '', + ['class' => 'studentselect'] + ); } else { $img = $student->checked ? 'ticked' : 'unticked'; - $checkbox = $this->render(new pix_icon($img, '', 'scheduler', array('class' => 'statictickbox'))); + $checkbox = $this->render(new pix_icon($img, '', 'scheduler', ['class' => 'statictickbox'])); } } + if ($studentlist->linkappointment) { $name = $this->appointment_link($studentlist->scheduler, $student->user, $student->entryid); } else { $name = fullname($student->user); } + $studicons = ''; - $studprovided = array(); + $studprovided = []; if ($student->notesprovided) { $studprovided[] = get_string('message', 'scheduler'); } + if ($student->filesprovided) { $studprovided[] = get_string('nfiles', 'scheduler', $student->filesprovided); } + if ($studprovided) { $providedstr = implode(', ', $studprovided); $alttext = get_string('studentprovided', 'scheduler', $providedstr); - $attachicon = new pix_icon('attachment', $alttext, 'scheduler', array('class' => 'studdataicon')); + $attachicon = new pix_icon('attachment', $alttext, 'scheduler', ['class' => 'studdataicon']); $studicons .= $this->render($attachicon); } if ($student->highlight) { $class .= ' highlight'; } - $picture = $this->user_picture($student->user, array('courseid' => $studentlist->scheduler->courseid)); + + $picture = $this->user_picture($student->user, ['courseid' => $studentlist->scheduler->courseid]); $grade = ''; if ($studentlist->showgrades && $student->grade) { $grade = $this->format_grade($studentlist->scheduler, $student->grade, true); } + $o .= html_writer::div($checkbox . $picture . ' ' . $name . $studicons . ' ' . $grade, $class); } if ($editable) { - $o .= html_writer::empty_tag('input', array( + $o .= html_writer::empty_tag('input', [ 'type' => 'submit', 'class' => 'studentselectsubmit', - 'value' => $studentlist->buttontext - )); + 'value' => $studentlist->buttontext, + ]); $o .= html_writer::end_tag('form'); } } + $o .= html_writer::end_div(); return $o; @@ -603,13 +678,13 @@ public function render_scheduler_student_list(scheduler_student_list $studentlis public function render_scheduler_slot_booker(scheduler_slot_booker $booker) { $table = new html_table(); - $table->head = array( get_string('date', 'scheduler'), get_string('start', 'scheduler'), + $table->head = [ get_string('date', 'scheduler'), get_string('start', 'scheduler'), get_string('end', 'scheduler'), get_string('location', 'scheduler'), get_string('comments', 'scheduler'), s($booker->scheduler->get_teacher_name()), - get_string('groupsession', 'scheduler'), ''); - $table->align = array ('left', 'left', 'left', 'left', 'left', 'left', 'left', 'left'); + get_string('groupsession', 'scheduler'), '', ]; + $table->align = ['left', 'left', 'left', 'left', 'left', 'left', 'left', 'left']; $table->id = 'slotbookertable'; - $table->data = array(); + $table->data = []; $previousdate = ''; $previoustime = ''; @@ -617,8 +692,7 @@ public function render_scheduler_slot_booker(scheduler_slot_booker $booker) { $canappoint = false; foreach ($booker->slots as $slot) { - - $rowdata = array(); + $rowdata = []; $startdate = $this->userdate($slot->starttime); $starttime = $this->usertime($slot->starttime); @@ -647,8 +721,13 @@ public function render_scheduler_slot_booker(scheduler_slot_booker $booker) { $rowdata[] = format_string($slot->location); - $rowdata[] = $this->format_notes($slot->notes, $slot->notesformat, $booker->scheduler->get_context(), - 'slotnote', $slot->slotid); + $rowdata[] = $this->format_notes( + $slot->notes, + $slot->notesformat, + $booker->scheduler->get_context(), + 'slotnote', + $slot->slotid + ); $rowdata[] = $this->user_profile_link($booker->scheduler, $slot->teacher); @@ -661,7 +740,7 @@ public function render_scheduler_slot_booker(scheduler_slot_booker $booker) { if ($slot->canbook) { $bookaction = $booker->scheduler->uses_bookingform() ? 'bookingform' : 'bookslot'; - $bookurl = new moodle_url($booker->actionurl, array('what' => $bookaction, 'slotid' => $slot->slotid)); + $bookurl = new moodle_url($booker->actionurl, ['what' => $bookaction, 'slotid' => $slot->slotid]); $button = new single_button($bookurl, get_string('bookslot', 'scheduler')); $rowdata[] = $this->render($button); } else { @@ -685,6 +764,7 @@ public function render_scheduler_slot_booker(scheduler_slot_booker $booker) { * @return string HTML */ public function render_action_menu(action_menu $menu) { + global $CFG; // We don't want the class icon there! foreach ($menu->get_secondary_actions() as $action) { @@ -696,8 +776,11 @@ public function render_action_menu(action_menu $menu) { if ($menu->is_empty()) { return ''; } - $context = $menu->export_for_template($this); + $context = $menu->export_for_template($this); + if ($CFG->version > 2025041400) { + $context->primary->bs5 = "bs5"; + } return $this->render_from_template('mod_scheduler/action_menu', $context); } @@ -712,13 +795,16 @@ public function render_scheduler_command_bar(scheduler_command_bar $commandbar) foreach ($commandbar->linkactions as $id => $action) { $this->add_action_handler($action, $id); } + $o .= html_writer::start_div('commandbar'); if ($commandbar->title) { $o .= html_writer::span($commandbar->title, 'title'); } + foreach ($commandbar->menus as $m) { $o .= $this->render($m); } + $o .= html_writer::end_div(); return $o; } @@ -731,33 +817,33 @@ public function render_scheduler_command_bar(scheduler_command_bar $commandbar) */ public function render_scheduler_slot_manager(scheduler_slot_manager $slotman) { - $this->page->requires->js_call_amd('mod_scheduler/saveseen', 'init', [$slotman->scheduler->cmid] ); + $this->page->requires->js_call_amd('mod_scheduler/saveseen', 'init', [$slotman->scheduler->cmid]); $o = ''; $table = new html_table(); - $table->head = array('', get_string('date', 'scheduler'), get_string('start', 'scheduler'), - get_string('end', 'scheduler'), get_string('location', 'scheduler'), get_string('students', 'scheduler') ); - $table->align = array ('center', 'left', 'left', 'left', 'left', 'left'); + $table->head = ['', get_string('date', 'scheduler'), get_string('start', 'scheduler'), + get_string('end', 'scheduler'), get_string('location', 'scheduler'), get_string('students', 'scheduler'), ]; + $table->align = ['center', 'left', 'left', 'left', 'left', 'left']; if ($slotman->showteacher) { $table->head[] = s($slotman->scheduler->get_teacher_name()); $table->align[] = 'left'; } + $table->head[] = get_string('action', 'scheduler'); $table->align[] = 'center'; $table->id = 'slotmanager'; - $table->data = array(); + $table->data = []; $previousdate = ''; $previoustime = ''; $previousendtime = ''; foreach ($slotman->slots as $slot) { + $rowdata = []; - $rowdata = array(); - - $selectbox = html_writer::checkbox('selectedslot[]', $slot->slotid, false, '', array('class' => 'slotselect')); + $selectbox = html_writer::checkbox('selectedslot[]', $slot->slotid, false, '', ['class' => 'slotselect']); $rowdata[] = $slot->editable ? $selectbox : ''; $startdate = $this->userdate($slot->starttime); @@ -795,11 +881,11 @@ public function render_scheduler_slot_manager(scheduler_slot_manager $slotman) { $actions = ''; if ($slot->editable) { - $url = new moodle_url($slotman->actionurl, array('what' => 'deleteslot', 'slotid' => $slot->slotid)); + $url = new moodle_url($slotman->actionurl, ['what' => 'deleteslot', 'slotid' => $slot->slotid]); $confirmdelete = new confirm_action(get_string('confirmdelete-one', 'scheduler')); $actions .= $this->action_icon($url, new pix_icon('t/delete', get_string('delete')), $confirmdelete); - $url = new moodle_url($slotman->actionurl, array('what' => 'updateslot', 'slotid' => $slot->slotid)); + $url = new moodle_url($slotman->actionurl, ['what' => 'updateslot', 'slotid' => $slot->slotid]); $actions .= $this->action_icon($url, new pix_icon('t/edit', get_string('edit'))); } @@ -810,17 +896,19 @@ public function render_scheduler_slot_manager(scheduler_slot_manager $slotman) { } else { $groupicon = 't/groupv'; } - $groupalt = ''; $groupact = null; + + $groupalt = ''; + $groupact = null; if ($slot->isattended) { $groupalt = 'attended'; } else if ($slot->isappointed > 1) { $groupalt = 'isnonexclusive'; } else if ($slot->editable) { if ($slot->exclusivity == 1) { - $groupact = array('what' => 'allowgroup', 'slotid' => $slot->slotid); + $groupact = ['what' => 'allowgroup', 'slotid' => $slot->slotid]; $groupalt = 'allowgroup'; } else { - $groupact = array('what' => 'forbidgroup', 'slotid' => $slot->slotid); + $groupact = ['what' => 'forbidgroup', 'slotid' => $slot->slotid]; $groupalt = 'forbidgroup'; } } else { @@ -830,6 +918,7 @@ public function render_scheduler_slot_manager(scheduler_slot_manager $slotman) { $groupalt = 'forbidgroup'; } } + if ($groupact) { $url = new moodle_url($slotman->actionurl, $groupact); $actions .= $this->action_icon($url, new pix_icon($groupicon, get_string($groupalt, 'scheduler'))); @@ -838,14 +927,19 @@ public function render_scheduler_slot_manager(scheduler_slot_manager $slotman) { } if ($slot->editable && $slot->isappointed) { - $url = new moodle_url($slotman->actionurl, array('what' => 'revokeall', 'slotid' => $slot->slotid)); + $url = new moodle_url($slotman->actionurl, ['what' => 'revokeall', 'slotid' => $slot->slotid]); $confirmrevoke = new confirm_action(get_string('confirmrevoke', 'scheduler')); - $actions .= $this->action_icon($url, new pix_icon('s/no', get_string('revoke', 'scheduler')), $confirmrevoke); + $actions .= $this->action_icon( + $url, + new thumbsdown_icon('t/no', get_string('revoke', 'scheduler'), 'mod_scheduler'), + $confirmrevoke + ); } if ($slot->exclusivity > 1) { - $actions .= ' ('.$slot->exclusivity.')'; + $actions .= ' (' . $slot->exclusivity . ')'; } + $rowdata[] = $actions; $table->data[] = $rowdata; @@ -854,6 +948,7 @@ public function render_scheduler_slot_manager(scheduler_slot_manager $slotman) { $previousendtime = $endtime; $previousdate = $startdate; } + $o .= html_writer::table($table); return $o; @@ -870,30 +965,34 @@ public function render_scheduler_scheduling_list(scheduler_scheduling_list $list $mtable = new html_table(); $mtable->id = $list->id; - $mtable->head = array ('', get_string('name')); - $mtable->align = array ('center', 'left'); + $mtable->head = ['', get_string('name')]; + $mtable->align = ['center', 'left']; foreach ($list->extraheaders as $field) { $mtable->head[] = $field; $mtable->align[] = 'left'; } + $mtable->head[] = get_string('action', 'scheduler'); $mtable->align[] = 'center'; - $mtable->data = array(); + $mtable->data = []; foreach ($list->lines as $line) { - $data = array($line->pix, $line->name); + $data = [$line->pix, $line->name]; foreach ($line->extrafields as $field) { $data[] = $field; } + $actions = ''; if ($line->actions) { $menu = new action_menu($line->actions); $menu->actiontext = get_string('schedule', 'scheduler'); $actions = $this->render($menu); } + $data[] = $actions; $mtable->data[] = $data; } + return html_writer::table($mtable); } @@ -904,37 +1003,42 @@ public function render_scheduler_scheduling_list(scheduler_scheduling_list $list * @return string */ public function render_scheduler_totalgrade_info(scheduler_totalgrade_info $gradeinfo) { - $items = array(); + $items = []; if ($gradeinfo->showtotalgrade) { - $items[] = array('gradingstrategy', $this->format_grading_strategy($gradeinfo->scheduler->gradingstrategy)); - $items[] = array('totalgrade', $this->format_grade($gradeinfo->scheduler, $gradeinfo->totalgrade, false, 2)); + $items[] = ['gradingstrategy', $this->format_grading_strategy($gradeinfo->scheduler->gradingstrategy)]; + $items[] = ['totalgrade', $this->format_grade($gradeinfo->scheduler, $gradeinfo->totalgrade, false, 2)]; } if (!is_null($gradeinfo->gbgrade)) { $gbgradestr = $gradeinfo->gbgrade->str_grade; - $attributes = array(); + $attributes = []; if ($gradeinfo->gbgrade->hidden) { $attributes[] = get_string('hidden', 'grades'); } + if ($gradeinfo->gbgrade->locked) { $attributes[] = get_string('locked', 'grades'); } + if ($gradeinfo->gbgrade->overridden) { $attributes[] = get_string('overridden', 'grades'); } + if (count($attributes) > 0) { - $gbgradestr .= ' ('.implode(', ', $attributes) .')'; + $gbgradestr .= ' (' . implode(', ', $attributes) . ')'; } - $items[] = array('gradeingradebook', $gbgradestr); + + $items[] = ['gradeingradebook', $gbgradestr]; } $o = html_writer::start_div('totalgrade'); - $o .= html_writer::start_tag('dl', array('class' => 'totalgrade')); + $o .= html_writer::start_tag('dl', ['class' => 'totalgrade']); foreach ($items as $item) { $o .= html_writer::tag('dt', get_string($item[0], 'scheduler')); $o .= html_writer::tag('dd', $item[1]); } + $o .= html_writer::end_tag('dl'); $o .= html_writer::end_div('totalgrade'); return $o; @@ -962,6 +1066,7 @@ public function render_scheduler_conflict_list(scheduler_conflict_list $cl) { $a->schedulername = format_string($conflict->schedulername); $entry = get_string('conflictremote', 'scheduler', $a); } + $o .= html_writer::tag('li', $entry); } @@ -990,30 +1095,35 @@ public function render_scheduler_appointment_info(scheduler_appointment_info $ai $cell1 = new html_table_cell(get_string('slotdatetimelabel', 'scheduler')); $data = self::slotdatetime($ai->slot->starttime, $ai->slot->duration); $cell2 = new html_table_cell(get_string('slotdatetimelong', 'scheduler', $data)); - $row->cells = array($cell1, $cell2); + $row->cells = [$cell1, $cell2]; $t->data[] = $row; $row = new html_table_row(); $cell1 = new html_table_cell($ai->scheduler->get_teacher_name()); $cell2 = new html_table_cell(fullname($ai->slot->get_teacher())); - $row->cells = array($cell1, $cell2); + $row->cells = [$cell1, $cell2]; $t->data[] = $row; if ($ai->slot->appointmentlocation) { $row = new html_table_row(); $cell1 = new html_table_cell(get_string('location', 'scheduler')); $cell2 = new html_table_cell(format_string($ai->slot->appointmentlocation)); - $row->cells = array($cell1, $cell2); + $row->cells = [$cell1, $cell2]; $t->data[] = $row; } if ($ai->slot->notes) { $row = new html_table_row(); $cell1 = new html_table_cell(get_string('comments', 'scheduler')); - $notes = $this->format_notes($ai->slot->notes, $ai->slot->notesformat, $ai->scheduler->get_context(), - 'slotnote', $ai->slot->id); + $notes = $this->format_notes( + $ai->slot->notes, + $ai->slot->notesformat, + $ai->scheduler->get_context(), + 'slotnote', + $ai->slot->id + ); $cell2 = new html_table_cell($notes); - $row->cells = array($cell1, $cell2); + $row->cells = [$cell1, $cell2]; $t->data[] = $row; } } @@ -1022,7 +1132,7 @@ public function render_scheduler_appointment_info(scheduler_appointment_info $ai $row = new html_table_row(); $cell1 = new html_table_cell(get_string('appointfor', 'scheduler')); $cell2 = new html_table_cell(format_string($ai->groupinfo)); - $row->cells = array($cell1, $cell2); + $row->cells = [$cell1, $cell2]; $t->data[] = $row; } @@ -1030,10 +1140,15 @@ public function render_scheduler_appointment_info(scheduler_appointment_info $ai if ($ai->scheduler->has_bookinginstructions()) { $row = new html_table_row(); $cell1 = new html_table_cell(get_string('bookinginstructions', 'scheduler')); - $note = $this->format_notes($ai->scheduler->bookinginstructions, $ai->scheduler->bookinginstructionsformat, - $ai->scheduler->get_context(), 'bookinginstructions', 0); + $note = $this->format_notes( + $ai->scheduler->bookinginstructions, + $ai->scheduler->bookinginstructionsformat, + $ai->scheduler->get_context(), + 'bookinginstructions', + 0 + ); $cell2 = new html_table_cell($note); - $row->cells = array($cell1, $cell2); + $row->cells = [$cell1, $cell2]; $t->data[] = $row; } } @@ -1046,18 +1161,20 @@ public function render_scheduler_appointment_info(scheduler_appointment_info $ai } else { $key = 'studentnote'; } + $cell1 = new html_table_cell(get_string($key, 'scheduler')); $note = format_text($ai->appointment->studentnote, $ai->appointment->studentnoteformat); $cell2 = new html_table_cell($note); - $row->cells = array($cell1, $cell2); + $row->cells = [$cell1, $cell2]; $t->data[] = $row; } + if ($ai->scheduler->uses_studentfiles()) { $row = new html_table_row(); $cell1 = new html_table_cell(get_string('studentfiles', 'scheduler')); $att = $this->render_attachments($ai->scheduler->context->id, 'studentfiles', $ai->appointment->id); $cell2 = new html_table_cell($att); - $row->cells = array($cell1, $cell2); + $row->cells = [$cell1, $cell2]; $t->data[] = $row; } } @@ -1066,18 +1183,24 @@ public function render_scheduler_appointment_info(scheduler_appointment_info $ai if ($ai->scheduler->uses_appointmentnotes() && $ai->appointment->appointmentnote) { $row = new html_table_row(); $cell1 = new html_table_cell(get_string('appointmentnote', 'scheduler')); - $note = $this->format_notes($ai->appointment->appointmentnote, $ai->appointment->appointmentnoteformat, - $ai->scheduler->get_context(), 'appointmentnote', $ai->appointment->id); + $note = $this->format_notes( + $ai->appointment->appointmentnote, + $ai->appointment->appointmentnoteformat, + $ai->scheduler->get_context(), + 'appointmentnote', + $ai->appointment->id + ); $cell2 = new html_table_cell($note); - $row->cells = array($cell1, $cell2); + $row->cells = [$cell1, $cell2]; $t->data[] = $row; } + if ($ai->scheduler->uses_grades()) { $row = new html_table_row(); $cell1 = new html_table_cell(get_string('grade', 'scheduler')); $gradetext = $this->format_grade($ai->scheduler, $ai->appointment->grade, false); $cell2 = new html_table_cell($gradetext); - $row->cells = array($cell1, $cell2); + $row->cells = [$cell1, $cell2]; $t->data[] = $row; } } @@ -1088,5 +1211,4 @@ public function render_scheduler_appointment_info(scheduler_appointment_info $ai $o .= $this->output->container_end(); return $o; } - } diff --git a/settings.php b/settings.php index b2fee38b..21bfd8fe 100644 --- a/settings.php +++ b/settings.php @@ -25,37 +25,49 @@ defined('MOODLE_INTERNAL') || die; if ($ADMIN->fulltree) { + require_once($CFG->dirroot . '/mod/scheduler/lib.php'); - require_once($CFG->dirroot.'/mod/scheduler/lib.php'); + $settings->add(new admin_setting_configcheckbox( + 'mod_scheduler/showemailplain', + get_string('showemailplain', 'scheduler'), + get_string('showemailplain_desc', 'scheduler'), + 0 + )); - $settings->add(new admin_setting_configcheckbox('mod_scheduler/showemailplain', - get_string('showemailplain', 'scheduler'), - get_string('showemailplain_desc', 'scheduler'), - 0)); + $settings->add(new admin_setting_configcheckbox( + 'mod_scheduler/groupscheduling', + get_string('groupscheduling', 'scheduler'), + get_string('groupscheduling_desc', 'scheduler'), + 1 + )); - $settings->add(new admin_setting_configcheckbox('mod_scheduler/groupscheduling', - get_string('groupscheduling', 'scheduler'), - get_string('groupscheduling_desc', 'scheduler'), - 1)); + $settings->add(new admin_setting_configcheckbox( + 'mod_scheduler/mixindivgroup', + get_string('mixindivgroup', 'scheduler'), + get_string('mixindivgroup_desc', 'scheduler'), + 1 + )); - $settings->add(new admin_setting_configcheckbox('mod_scheduler/mixindivgroup', - get_string('mixindivgroup', 'scheduler'), - get_string('mixindivgroup_desc', 'scheduler'), - 1)); + $settings->add(new admin_setting_configtext( + 'mod_scheduler/maxstudentlistsize', + get_string('maxstudentlistsize', 'scheduler'), + get_string('maxstudentlistsize_desc', 'scheduler'), + 200, + PARAM_INT + )); - $settings->add(new admin_setting_configtext('mod_scheduler/maxstudentlistsize', - get_string('maxstudentlistsize', 'scheduler'), - get_string('maxstudentlistsize_desc', 'scheduler'), - 200, PARAM_INT)); - - $settings->add(new admin_setting_configtext('mod_scheduler/uploadmaxfiles', - get_string('uploadmaxfilesglobal', 'scheduler'), - get_string('uploadmaxfilesglobal_desc', 'scheduler'), - 5, PARAM_INT)); - - $settings->add(new admin_setting_configcheckbox('mod_scheduler/revealteachernotes', - get_string('revealteachernotes', 'scheduler'), - get_string('revealteachernotes_desc', 'scheduler'), - 0)); + $settings->add(new admin_setting_configtext( + 'mod_scheduler/uploadmaxfiles', + get_string('uploadmaxfilesglobal', 'scheduler'), + get_string('uploadmaxfilesglobal_desc', 'scheduler'), + 5, + PARAM_INT + )); + $settings->add(new admin_setting_configcheckbox( + 'mod_scheduler/revealteachernotes', + get_string('revealteachernotes', 'scheduler'), + get_string('revealteachernotes_desc', 'scheduler'), + 0 + )); } diff --git a/slotforms.php b/slotforms.php index c03384cb..1f3a1377 100644 --- a/slotforms.php +++ b/slotforms.php @@ -24,10 +24,12 @@ defined('MOODLE_INTERNAL') || die(); -use \mod_scheduler\model\scheduler; -use \mod_scheduler\model\slot; +use mod_scheduler\model\scheduler; +use mod_scheduler\model\slot; -require_once($CFG->libdir.'/formslib.php'); +require_once($CFG->libdir . '/formslib.php'); + +// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses /** * Base class for slot-related forms @@ -36,8 +38,8 @@ * @copyright 2013 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -abstract class scheduler_slotform_base extends moodleform { - +abstract class scheduler_slotform_base extends moodleform +{ /** * @var scheduler the scheduler that this form refers to */ @@ -67,11 +69,17 @@ abstract class scheduler_slotform_base extends moodleform { * @param array $usergroups groups to filter for * @param array $customdata */ - public function __construct($action, scheduler $scheduler, $cm, $usergroups, $customdata=null) { + public function __construct( + $action, + scheduler $scheduler, + $cm, + $usergroups, + $customdata = null + ) { $this->scheduler = $scheduler; $this->usergroups = $usergroups; - $this->noteoptions = array('trusttext' => true, 'maxfiles' => -1, 'maxbytes' => 0, - 'context' => $scheduler->get_context(), 'subdirs' => false); + $this->noteoptions = ['trusttext' => true, 'maxfiles' => -1, 'maxbytes' => 0, + 'context' => $scheduler->get_context(), 'subdirs' => false, ]; parent::__construct($action, $customdata); } @@ -86,9 +94,9 @@ protected function add_base_fields() { $mform = $this->_form; // Exclusivity. - $exclgroup = array(); + $exclgroup = []; - $exclgroup[] = $mform->createElement('text', 'exclusivity', '', array('size' => '10')); + $exclgroup[] = $mform->createElement('text', 'exclusivity', '', ['size' => '10']); $mform->setType('exclusivity', PARAM_INTEGER); $mform->setDefault('exclusivity', 1); @@ -100,7 +108,7 @@ protected function add_base_fields() { $mform->addHelpButton('exclusivitygroup', 'exclusivity', 'scheduler'); // Location of the appointment. - $mform->addElement('text', 'appointmentlocation', get_string('location', 'scheduler'), array('size' => '30')); + $mform->addElement('text', 'appointmentlocation', get_string('location', 'scheduler'), ['size' => '30']); $mform->setType('appointmentlocation', PARAM_TEXT); $mform->addRule('appointmentlocation', get_string('error'), 'maxlength', 255); $mform->setDefault('appointmentlocation', $this->scheduler->get_last_location($USER)); @@ -110,24 +118,25 @@ protected function add_base_fields() { if (has_capability('mod/scheduler:canscheduletootherteachers', $this->scheduler->get_context())) { $teachername = s($this->scheduler->get_teacher_name()); $teachers = $this->scheduler->get_available_teachers(); - $teachersmenu = array(); + $teachersmenu = []; if ($teachers) { foreach ($teachers as $teacher) { $teachersmenu[$teacher->id] = fullname($teacher); } + $mform->addElement('select', 'teacherid', $teachername, $teachersmenu); $mform->addRule('teacherid', get_string('noteacherforslot', 'scheduler'), 'required'); $mform->setDefault('teacherid', $USER->id); } else { $mform->addElement('static', 'teacherid', $teachername, get_string('noteachershere', 'scheduler', $teachername)); } + $mform->addHelpButton('teacherid', 'bookwithteacher', 'scheduler'); } else { $mform->addElement('hidden', 'teacherid'); $mform->setDefault('teacherid', $USER->id); $mform->setType('teacherid', PARAM_INT); } - } /** @@ -140,10 +149,10 @@ protected function add_base_fields() { */ protected function add_minutes_field($name, $label, $defaultval, $minuteslabel = 'minutes') { $mform = $this->_form; - $group = array(); - $group[] =& $mform->createElement('text', $name, '', array('size' => 5)); - $group[] =& $mform->createElement('static', $name.'mintext', '', get_string($minuteslabel, 'scheduler')); - $mform->addGroup($group, $name.'group', get_string($label, 'scheduler'), array(' '), false); + $group = []; + $group[] =& $mform->createElement('text', $name, '', ['size' => 5]); + $group[] =& $mform->createElement('static', $name . 'mintext', '', get_string($minuteslabel, 'scheduler')); + $mform->addGroup($group, $name . 'group', get_string($label, 'scheduler'), [' '], false); $mform->setType($name, PARAM_INT); $mform->setDefault($name, $defaultval); } @@ -170,7 +179,7 @@ public function validation($data, $files) { // Check duration for valid range. if ($this->hasduration) { - $limits = array('min' => 1, 'max' => 24 * 60); + $limits = ['min' => 1, 'max' => 24 * 60]; if ($data['duration'] < $limits['min'] || $data['duration'] > $limits['max']) { $errors['durationgroup'] = get_string('durationrange', 'scheduler', $limits); } @@ -178,7 +187,6 @@ public function validation($data, $files) { return $errors; } - } /** @@ -188,8 +196,8 @@ public function validation($data, $files) { * @copyright 2013 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_editslot_form extends scheduler_slotform_base { - +class scheduler_editslot_form extends scheduler_slotform_base +{ /** * @var int id of the slot being edited */ @@ -207,6 +215,7 @@ protected function definition() { if (isset($this->_customdata['slotid'])) { $this->slotid = $this->_customdata['slotid']; } + $timeoptions = null; if (isset($this->_customdata['timeoptions'])) { $timeoptions = $this->_customdata['timeoptions']; @@ -233,26 +242,35 @@ protected function definition() { $mform->setDefault('hideuntil', time()); // Send e-mail reminder? - $mform->addElement('date_selector', 'emaildate', get_string('emailreminderondate', 'scheduler'), - array('optional' => true)); + $mform->addElement( + 'date_selector', + 'emaildate', + get_string('emailreminderondate', 'scheduler'), + ['optional' => true] + ); $mform->setDefault('remindersel', -1); // Slot comments. - $mform->addElement('editor', 'notes_editor', get_string('comments', 'scheduler'), - array('rows' => 3, 'columns' => 60), $this->noteoptions); + $mform->addElement( + 'editor', + 'notes_editor', + get_string('comments', 'scheduler'), + ['rows' => 3, 'columns' => 60], + $this->noteoptions + ); $mform->setType('notes', PARAM_RAW); // Must be PARAM_RAW for rich text editor content. // Appointments. - $repeatarray = array(); - $grouparray = array(); + $repeatarray = []; + $grouparray = []; $repeatarray[] = $mform->createElement('header', 'appointhead', get_string('appointmentno', 'scheduler', '{no}')); // Choose student. $options = [ 'ajax' => 'mod_scheduler/studentid', 'valuehtmlcallback' => 'scheduler_student_autocomplete_callback', - 'scheduler' => $this->scheduler->id + 'scheduler' => $this->scheduler->id, ]; $grouparray[] = $mform->createElement('autocomplete', 'studentid', '', [], $options); $grouparray[] = $mform->createElement('hidden', 'appointid', 0); @@ -273,12 +291,23 @@ protected function definition() { // Appointment notes, visible to teacher and/or student. if ($this->scheduler->uses_appointmentnotes()) { - $repeatarray[] = $mform->createElement('editor', 'appointmentnote_editor', get_string('appointmentnote', 'scheduler'), - array('rows' => 3, 'columns' => 60), $this->noteoptions); + $repeatarray[] = $mform->createElement( + 'editor', + 'appointmentnote_editor', + get_string('appointmentnote', 'scheduler'), + ['rows' => 3, 'columns' => 60], + $this->noteoptions + ); } + if ($this->scheduler->uses_teachernotes()) { - $repeatarray[] = $mform->createElement('editor', 'teachernote_editor', get_string('teachernote', 'scheduler'), - array('rows' => 3, 'columns' => 60), $this->noteoptions); + $repeatarray[] = $mform->createElement( + 'editor', + 'teachernote_editor', + get_string('teachernote', 'scheduler'), + ['rows' => 3, 'columns' => 60], + $this->noteoptions + ); } // Tickbox to remove the student. @@ -287,16 +316,16 @@ protected function definition() { if (isset($this->_customdata['repeats'])) { $repeatno = $this->_customdata['repeats']; } else if ($this->slotid) { - $repeatno = $DB->count_records('scheduler_appointment', array('slotid' => $this->slotid)); + $repeatno = $DB->count_records('scheduler_appointment', ['slotid' => $this->slotid]); $repeatno += 1; } else { $repeatno = 1; } - $repeateloptions = array(); + $repeateloptions = []; $repeateloptions['appointid']['type'] = PARAM_INT; - $repeateloptions['studentid']['disabledif'] = array('appointid', 'neq', 0); - $nostudcheck = array('studentid', 'eq', 0); + $repeateloptions['studentid']['disabledif'] = ['appointid', 'neq', 0]; + $nostudcheck = ['studentid', 'eq', 0]; $repeateloptions['attended']['disabledif'] = $nostudcheck; $repeateloptions['appointmentnote_editor']['disabledif'] = $nostudcheck; $repeateloptions['teachernote_editor']['disabledif'] = $nostudcheck; @@ -304,11 +333,17 @@ protected function definition() { $repeateloptions['deletestudent']['disabledif'] = $nostudcheck; $repeateloptions['appointhead']['expanded'] = true; - $this->repeat_elements($repeatarray, $repeatno, $repeateloptions, - 'appointment_repeats', 'appointment_add', 1, get_string('addappointment', 'scheduler')); + $this->repeat_elements( + $repeatarray, + $repeatno, + $repeateloptions, + 'appointment_repeats', + 'appointment_add', + 1, + get_string('addappointment', 'scheduler') + ); $this->add_action_buttons(); - } /** @@ -331,6 +366,7 @@ public function validation($data, $files) { $numappointments++; } } + if ($data['exclusivityenable'] && $data['exclusivity'] <= 0) { $errors['exclusivitygroup'] = get_string('exclusivitypositive', 'scheduler'); } else if ($data['exclusivityenable'] && $numappointments > $data['exclusivity']) { @@ -345,10 +381,12 @@ public function validation($data, $files) { // Check whether students have been selected several times. for ($i = 0; $i < $data['appointment_repeats']; $i++) { for ($j = 0; $j < $i; $j++) { - if ($data['deletestudent'][$j] == 0 && $data['studentid'][$i] > 0 - && $data['studentid'][$i] == $data['studentid'][$j]) { - $errors['studgroup['.$i.']'] = get_string('studentmultiselect', 'scheduler'); - $errors['studgroup['.$j.']'] = get_string('studentmultiselect', 'scheduler'); + if ( + $data['deletestudent'][$j] == 0 && $data['studentid'][$i] > 0 + && $data['studentid'][$i] == $data['studentid'][$j] + ) { + $errors['studgroup[' . $i . ']'] = get_string('studentmultiselect', 'scheduler'); + $errors['studgroup[' . $j . ']'] = get_string('studentmultiselect', 'scheduler'); } } } @@ -356,11 +394,15 @@ public function validation($data, $files) { if (!isset($data['ignoreconflicts'])) { /* Avoid overlapping slots by warning the user */ $conflicts = $this->scheduler->get_conflicts( - $data['starttime'], $data['starttime'] + $data['duration'] * 60, - $data['teacherid'], 0, SCHEDULER_ALL, $this->slotid); + $data['starttime'], + $data['starttime'] + $data['duration'] * 60, + $data['teacherid'], + 0, + SCHEDULER_ALL, + $this->slotid + ); if (count($conflicts) > 0) { - $cl = new scheduler_conflict_list(); $cl->add_conflicts($conflicts); @@ -371,6 +413,7 @@ public function validation($data, $files) { $errors['starttime'] = $msg; } } + return $errors; } @@ -387,9 +430,16 @@ public function prepare_formdata(slot $slot) { $data = $slot->get_data(); $data->exclusivityenable = ($data->exclusivity > 0); - $data = file_prepare_standard_editor($data, "notes", $this->noteoptions, $context, - 'mod_scheduler', 'slotnote', $slot->id); - $data->notes = array(); + $data = file_prepare_standard_editor( + $data, + "notes", + $this->noteoptions, + $context, + 'mod_scheduler', + 'slotnote', + $slot->id + ); + $data->notes = []; $data->notes['text'] = $slot->notes; $data->notes['format'] = $slot->notesformat; @@ -404,20 +454,32 @@ public function prepare_formdata(slot $slot) { $data->attended[$i] = $appointment->attended; $draftid = file_get_submitted_draft_itemid('appointmentnote'); - $currenttext = file_prepare_draft_area($draftid, $context->id, - 'mod_scheduler', 'appointmentnote', $appointment->id, - $this->noteoptions, $appointment->appointmentnote); - $data->appointmentnote_editor[$i] = array('text' => $currenttext, + $currenttext = file_prepare_draft_area( + $draftid, + $context->id, + 'mod_scheduler', + 'appointmentnote', + $appointment->id, + $this->noteoptions, + $appointment->appointmentnote + ); + $data->appointmentnote_editor[$i] = ['text' => $currenttext, 'format' => $appointment->appointmentnoteformat, - 'itemid' => $draftid); + 'itemid' => $draftid, ]; $draftid = file_get_submitted_draft_itemid('teachernote'); - $currenttext = file_prepare_draft_area($draftid, $context->id, - 'mod_scheduler', 'teachernote', $appointment->id, - $this->noteoptions, $appointment->teachernote); - $data->teachernote_editor[$i] = array('text' => $currenttext, + $currenttext = file_prepare_draft_area( + $draftid, + $context->id, + 'mod_scheduler', + 'teachernote', + $appointment->id, + $this->noteoptions, + $appointment->teachernote + ); + $data->teachernote_editor[$i] = ['text' => $currenttext, 'format' => $appointment->teachernoteformat, - 'itemid' => $draftid); + 'itemid' => $draftid, ]; $data->grade[$i] = $appointment->grade; $i++; @@ -457,8 +519,15 @@ public function save_slot($slotid, $data) { } $editor = $data->notes_editor; - $slot->notes = file_save_draft_area_files($editor['itemid'], $context->id, 'mod_scheduler', 'slotnote', $slotid, - $this->noteoptions, $editor['text']); + $slot->notes = file_save_draft_area_files( + $editor['itemid'], + $context->id, + 'mod_scheduler', + 'slotnote', + $slotid, + $this->noteoptions, + $editor['text'] + ); $slot->notesformat = $editor['format']; $currentapps = $slot->get_appointments(); @@ -478,6 +547,7 @@ public function save_slot($slotid, $data) { $app->timecreated = time(); $app->save(); } + $app->attended = isset($data->attended[$i]); if (isset($data->grade)) { @@ -487,16 +557,29 @@ public function save_slot($slotid, $data) { if ($this->scheduler->uses_appointmentnotes()) { $editor = $data->appointmentnote_editor[$i]; - $app->appointmentnote = file_save_draft_area_files($editor['itemid'], $context->id, - 'mod_scheduler', 'appointmentnote', $app->id, - $this->noteoptions, $editor['text']); + $app->appointmentnote = file_save_draft_area_files( + $editor['itemid'], + $context->id, + 'mod_scheduler', + 'appointmentnote', + $app->id, + $this->noteoptions, + $editor['text'] + ); $app->appointmentnoteformat = $editor['format']; } + if ($this->scheduler->uses_teachernotes()) { $editor = $data->teachernote_editor[$i]; - $app->teachernote = file_save_draft_area_files($editor['itemid'], $context->id, - 'mod_scheduler', 'teachernote', $app->id, - $this->noteoptions, $editor['text']); + $app->teachernote = file_save_draft_area_files( + $editor['itemid'], + $context->id, + 'mod_scheduler', + 'teachernote', + $app->id, + $this->noteoptions, + $editor['text'] + ); $app->teachernoteformat = $editor['format']; } } @@ -518,7 +601,6 @@ public function save_slot($slotid, $data) { * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class scheduler_addsession_form extends scheduler_slotform_base { - /** * Form definition */ @@ -532,30 +614,37 @@ protected function definition() { $mform->addElement('date_selector', 'rangestart', get_string('date', 'scheduler')); $mform->setDefault('rangestart', time()); - $mform->addElement('date_selector', 'rangeend', get_string('enddate', 'scheduler'), - array('optional' => true) ); + $mform->addElement( + 'date_selector', + 'rangeend', + get_string('enddate', 'scheduler'), + ['optional' => true] + ); // Weekdays selection. - $checkboxes = array(); - $weekdays = array('monday', 'tuesday', 'wednesday', 'thursday', 'friday'); + $checkboxes = []; + $weekdays = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday']; foreach ($weekdays as $day) { $checkboxes[] = $mform->createElement('advcheckbox', $day, '', get_string($day, 'scheduler')); $mform->setDefault($day, true); } + $checkboxes[] = $mform->createElement('advcheckbox', 'saturday', '', get_string('saturday', 'scheduler')); $checkboxes[] = $mform->createElement('advcheckbox', 'sunday', '', get_string('sunday', 'scheduler')); $mform->addGroup($checkboxes, 'weekdays', get_string('addondays', 'scheduler'), null, false); // Start and end time. - $hours = array(); - $minutes = array(); + $hours = []; + $minutes = []; for ($i = 0; $i <= 23; $i++) { $hours[$i] = sprintf("%02d", $i); } + for ($i = 0; $i < 60; $i += 5) { $minutes[$i] = sprintf("%02d", $i); } - $timegroup = array(); + + $timegroup = []; if (right_to_left()) { $timegroup[] = $mform->createElement('static', 'timefrom', '', get_string('timefrom', 'scheduler')); $timegroup[] = $mform->createElement('select', 'startminute', get_string('minute', 'form'), $minutes); @@ -571,6 +660,7 @@ protected function definition() { $timegroup[] = $mform->createElement('select', 'endhour', get_string('hour', 'form'), $hours); $timegroup[] = $mform->createElement('select', 'endminute', get_string('minute', 'form'), $minutes); } + $mform->addGroup($timegroup, 'timerange', get_string('timerange', 'scheduler'), null, false); // Divide into slots? @@ -593,27 +683,30 @@ protected function definition() { $this->add_base_fields(); // Display slot from date - relative. - $hideuntilsel = array(); + $hideuntilsel = []; $hideuntilsel[0] = get_string('now', 'scheduler'); $hideuntilsel[DAYSECS] = get_string('onedaybefore', 'scheduler'); for ($i = 2; $i < 7; $i++) { $hideuntilsel[DAYSECS * $i] = get_string('xdaysbefore', 'scheduler', $i); } + $hideuntilsel[WEEKSECS] = get_string('oneweekbefore', 'scheduler'); for ($i = 2; $i < 7; $i++) { $hideuntilsel[WEEKSECS * $i] = get_string('xweeksbefore', 'scheduler', $i); } + $mform->addElement('select', 'hideuntilrel', get_string('displayfrom', 'scheduler'), $hideuntilsel); $mform->setDefault('hideuntilsel', 0); // E-mail reminder from. - $remindersel = array(); + $remindersel = []; $remindersel[-1] = get_string('never', 'scheduler'); $remindersel[0] = get_string('onthemorningofappointment', 'scheduler'); $remindersel[DAYSECS] = get_string('onedaybefore', 'scheduler'); for ($i = 2; $i < 7; $i++) { $remindersel[DAYSECS * $i] = get_string('xdaysbefore', 'scheduler', $i); } + $remindersel[WEEKSECS] = get_string('oneweekbefore', 'scheduler'); for ($i = 2; $i < 7; $i++) { $remindersel[WEEKSECS * $i] = get_string('xweeksbefore', 'scheduler', $i); @@ -623,7 +716,6 @@ protected function definition() { $mform->setDefault('remindersel', -1); $this->add_action_buttons(); - } /** diff --git a/studentview.controller.php b/studentview.controller.php index 1f0b5f06..2cab25e7 100644 --- a/studentview.controller.php +++ b/studentview.controller.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -require_once($CFG->dirroot.'/mod/scheduler/mailtemplatelib.php'); +require_once($CFG->dirroot . '/mod/scheduler/mailtemplatelib.php'); /** * scheduler_book_slot @@ -52,11 +52,12 @@ function scheduler_book_slot($scheduler, $slotid, $userid, $groupid, $mform, $fo } $requiredcapacity = 1; - $userstobook = array($userid); + $userstobook = [$userid]; if ($groupid > 0) { if (!$scheduler->is_group_scheduling_enabled()) { throw new moodle_exception('error'); } + $groupmembers = $scheduler->get_available_students($groupid); $requiredcapacity = count($groupmembers); $userstobook = array_keys($groupmembers); @@ -76,10 +77,11 @@ function scheduler_book_slot($scheduler, $slotid, $userid, $groupid, $mform, $fo $errormessage = get_string('selectedtoomany', 'scheduler', $bookinglimit); } else { // Validate our user ids. - $existingstudents = array(); + $existingstudents = []; foreach ($slot->get_appointments() as $app) { $existingstudents[] = $app->studentid; } + $userstobook = array_diff($userstobook, $existingstudents); $remaining = $slot->count_remaining_appointments(); @@ -115,28 +117,37 @@ function scheduler_book_slot($scheduler, $slotid, $userid, $groupid, $mform, $fo // Notify the teacher. if ($scheduler->allownotifications) { - $student = $DB->get_record('user', array('id' => $appointment->studentid), '*', MUST_EXIST); - $teacher = $DB->get_record('user', array('id' => $slot->teacherid), '*', MUST_EXIST); - scheduler_messenger::send_slot_notification($slot, 'bookingnotification', 'applied', - $student, $teacher, $teacher, $student, $COURSE); + $student = $DB->get_record('user', ['id' => $appointment->studentid], '*', MUST_EXIST); + $teacher = $DB->get_record('user', ['id' => $slot->teacherid], '*', MUST_EXIST); + scheduler_messenger::send_slot_notification( + $slot, + 'bookingnotification', + 'applied', + $student, + $teacher, + $teacher, + $student, + $COURSE + ); } } + $slot->save(); redirect($returnurl); - } -$returnurlparas = array('id' => $cm->id); +$returnurlparas = ['id' => $cm->id]; if ($scheduler->is_group_scheduling_enabled()) { $returnurlparas['appointgroup'] = $appointgroup; } + $returnurl = new moodle_url('/mod/scheduler/view.php', $returnurlparas); /******************************************** Show the booking form *******************************************/ if ($action == 'bookingform') { - require_once($CFG->dirroot.'/mod/scheduler/bookingform.php'); + require_once($CFG->dirroot . '/mod/scheduler/bookingform.php'); require_sesskey(); require_capability('mod/scheduler:appoint', $context); @@ -144,7 +155,7 @@ function scheduler_book_slot($scheduler, $slotid, $userid, $groupid, $mform, $fo $slotid = required_param('slotid', PARAM_INT); $slot = $scheduler->get_slot($slotid); - $actionurl = new moodle_url($returnurl, array('what' => 'bookingform', 'slotid' => $slotid)); + $actionurl = new moodle_url($returnurl, ['what' => 'bookingform', 'slotid' => $slotid]); $mform = new scheduler_booking_form($slot, $actionurl); @@ -171,13 +182,11 @@ function scheduler_book_slot($scheduler, $slotid, $userid, $groupid, $mform, $fo echo $output->footer(); exit(); } - } /************************************************ Book a slot ************************************************/ if ($action == 'bookslot') { - require_sesskey(); require_capability('mod/scheduler:appoint', $context); @@ -195,13 +204,13 @@ function scheduler_book_slot($scheduler, $slotid, $userid, $groupid, $mform, $fo /******************************************** Show details of booking *******************************************/ if ($action == 'viewbooking') { - require_once($CFG->dirroot.'/mod/scheduler/bookingform.php'); + require_once($CFG->dirroot . '/mod/scheduler/bookingform.php'); require_sesskey(); require_capability('mod/scheduler:appoint', $context); $appointmentid = required_param('appointmentid', PARAM_INT); - list($slot, $appointment) = $scheduler->get_slot_appointment($appointmentid); + [$slot, $appointment] = $scheduler->get_slot_appointment($appointmentid); if ($appointment->studentid != $USER->id) { throw new moodle_exception('nopermissions'); @@ -215,13 +224,12 @@ function scheduler_book_slot($scheduler, $slotid, $userid, $groupid, $mform, $fo echo $output->continue_button($returnurl); echo $output->footer(); exit(); - } /******************************************** Edit a booking *******************************************/ if ($action == 'editbooking') { - require_once($CFG->dirroot.'/mod/scheduler/bookingform.php'); + require_once($CFG->dirroot . '/mod/scheduler/bookingform.php'); require_sesskey(); require_capability('mod/scheduler:appoint', $context); @@ -231,16 +239,17 @@ function scheduler_book_slot($scheduler, $slotid, $userid, $groupid, $mform, $fo } $appointmentid = required_param('appointmentid', PARAM_INT); - list($slot, $appointment) = $scheduler->get_slot_appointment($appointmentid); + [$slot, $appointment] = $scheduler->get_slot_appointment($appointmentid); if ($appointment->studentid != $USER->id) { throw new moodle_exception('nopermissions'); } + if (!$slot->is_in_bookable_period()) { throw new moodle_exception('nopermissions'); } - $actionurl = new moodle_url($returnurl, array('what' => 'editbooking', 'appointmentid' => $appointmentid)); + $actionurl = new moodle_url($returnurl, ['what' => 'editbooking', 'appointmentid' => $appointmentid]); $mform = new scheduler_booking_form($slot, $actionurl, true); $mform->set_data($mform->prepare_booking_data($appointment)); @@ -260,14 +269,12 @@ function scheduler_book_slot($scheduler, $slotid, $userid, $groupid, $mform, $fo echo $output->footer(); exit(); } - } /******************************** Cancel a booking (for the current student or a group) ******************************/ if ($action == 'cancelbooking') { - require_sesskey(); require_capability('mod/scheduler:appoint', $context); @@ -282,7 +289,7 @@ function scheduler_book_slot($scheduler, $slotid, $userid, $groupid, $mform, $fo throw new moodle_exception('nopermissions'); } - $userstocancel = array($USER->id); + $userstocancel = [$USER->id]; if ($appointgroup) { $userstocancel = array_keys($scheduler->get_available_students($appointgroup)); } @@ -293,14 +300,23 @@ function scheduler_book_slot($scheduler, $slotid, $userid, $groupid, $mform, $fo // Notify the teacher. if ($scheduler->allownotifications) { - $student = $DB->get_record('user', array('id' => $USER->id)); - $teacher = $DB->get_record('user', array('id' => $slot->teacherid)); - scheduler_messenger::send_slot_notification($slot, 'bookingnotification', 'cancelled', - $student, $teacher, $teacher, $student, $COURSE); + $student = $DB->get_record('user', ['id' => $USER->id]); + $teacher = $DB->get_record('user', ['id' => $slot->teacherid]); + scheduler_messenger::send_slot_notification( + $slot, + 'bookingnotification', + 'cancelled', + $student, + $teacher, + $teacher, + $student, + $COURSE + ); } + \mod_scheduler\event\booking_removed::create_from_slot($slot)->trigger(); } } - redirect($returnurl); + redirect($returnurl); } diff --git a/studentview.php b/studentview.php index 833748d6..8721c44f 100644 --- a/studentview.php +++ b/studentview.php @@ -30,13 +30,14 @@ $PAGE->set_docs_path('mod/scheduler/studentview'); -$urlparas = array( +$urlparas = [ 'id' => $scheduler->cmid, - 'sesskey' => sesskey() -); + 'sesskey' => sesskey(), +]; if ($appointgroup >= 0) { $urlparas['appointgroup'] = $appointgroup; } + $actionurl = new moodle_url('/mod/scheduler/view.php', $urlparas); @@ -59,7 +60,7 @@ } -require_once($CFG->dirroot.'/mod/scheduler/studentview.controller.php'); +require_once($CFG->dirroot . '/mod/scheduler/studentview.controller.php'); echo $output->header(); @@ -72,13 +73,16 @@ $showowngrades = !$gradebookinfo->hidden; - if ($gradebookinfo && !$gradebookinfo->hidden && ($totalgrade || $gradebookinfo->overridden) ) { + if ($gradebookinfo && !$gradebookinfo->hidden && ($totalgrade || $gradebookinfo->overridden)) { $grademsg = ''; if ($gradebookinfo->overridden) { - $grademsg = html_writer::tag('p', - get_string('overriddennotice', 'grades'), array('class' => 'overriddennotice') - ); + $grademsg = html_writer::tag( + 'p', + get_string('overriddennotice', 'grades'), + ['class' => 'overriddennotice'] + ); } + $grademsg .= get_string('yourtotalgrade', 'scheduler', $gradebookinfo->str_grade); echo html_writer::div($grademsg, 'totalgrade'); } @@ -86,15 +90,23 @@ // Print group selection menu if given. if ($scheduler->is_group_scheduling_enabled()) { - $groupchoice = array(); + $groupchoice = []; if ($scheduler->is_individual_scheduling_enabled()) { $groupchoice[0] = get_string('myself', 'scheduler'); } + foreach ($mygroupsforscheduling as $group) { $groupchoice[$group->id] = $group->name; } - $select = $output->single_select($actionurl, 'appointgroup', $groupchoice, $appointgroup, - array(-1 => 'choosedots'), 'appointgroupform'); + + $select = $output->single_select( + $actionurl, + 'appointgroup', + $groupchoice, + $appointgroup, + [-1 => 'choosedots'], + 'appointgroupform' + ); echo html_writer::div(get_string('appointforgroup', 'scheduler', $select), 'dropdownmenu'); } @@ -117,6 +129,7 @@ } else { $others = null; } + $hasdetails = $scheduler->uses_studentdata(); $slottable->add_slot($pastslot, $appointment, $others, false, false, $hasdetails); } @@ -152,6 +165,7 @@ if ($scheduler->is_group_scheduling_enabled()) { $cancancel = $cancancel && ($appointgroup >= 0); } + $slottable->add_slot($slot, $appointment, $others, $cancancel, $canedit, $canview); } @@ -164,13 +178,10 @@ if (!$canseefull && $bookablecnt == 0) { echo html_writer::div(get_string('canbooknofurtherappointments', 'scheduler'), 'studentbookingmessage'); - } else if (count($bookableslots) == 0) { - // No slots are available at this time. $noslots = get_string('noslotsavailable', 'scheduler'); echo html_writer::div($noslots, 'studentbookingmessage'); - } else { // The student can book (or see) further appointments, and slots are available. // Show the booking form. @@ -194,6 +205,7 @@ foreach ($slot->get_appointments() as $otherapp) { $others->add_student($otherapp, $otherapp->studentid == $USER->id); } + $others->expandable = true; $others->expanded = false; } else { @@ -208,7 +220,7 @@ $groupinfo = get_string('no'); } else { if ($remaining > 0) { - $groupinfo = get_string('limited', 'scheduler', $remaining.'/'.$slot->exclusivity); + $groupinfo = get_string('limited', 'scheduler', $remaining . '/' . $slot->exclusivity); } else { // Group info should not be visible to students. $groupinfo = get_string('complete', 'scheduler'); $canbookthisslot = false; @@ -232,6 +244,7 @@ } else { $msgkey = 'canbookunlimitedappointments'; } + $bookingmsg2 = get_string($msgkey, 'scheduler', $a); echo $output->heading(get_string('availableslots', 'scheduler'), 3); @@ -239,14 +252,15 @@ echo html_writer::div($bookingmsg1, 'studentbookingmessage'); echo html_writer::div($bookingmsg2, 'studentbookingmessage'); } + if ($total > $pagesize) { echo $output->paging_bar($total, $offset, $pagesize, $actionurl, 'offset'); } + echo $output->render($booker); if ($total > $pagesize) { echo $output->paging_bar($total, $offset, $pagesize, $actionurl, 'offset'); } - } echo $output->footer(); diff --git a/styles.css b/styles.css index 9dba784e..e5cfe623 100644 --- a/styles.css +++ b/styles.css @@ -112,7 +112,6 @@ body.path-mod-scheduler.jsenabled input.studentselectsubmit { } .path-mod-scheduler .maildisplay { - width: 90%; margin-left: auto; margin-right: auto; background: #eee; diff --git a/teacherview.controller.php b/teacherview.controller.php index 6cdb092e..affe6016 100644 --- a/teacherview.controller.php +++ b/teacherview.controller.php @@ -56,47 +56,68 @@ function scheduler_action_doaddsession($scheduler, $formdata, moodle_url $return } else { $slot->duration = max(1, $data->endhour * 60 + $data->endminute - $data->starthour * 60 - $data->startminute); } + $slot->notes = ''; $slot->notesformat = FORMAT_HTML; $slot->timemodified = time(); - for ($d = 0; $d <= $fordays; $d ++) { + for ($d = 0; $d <= $fordays; $d++) { $starttime = $startfrom + ($d * DAYSECS); $eventdate = usergetdate($starttime); $dayofweek = $eventdate['wday']; - if ((($dayofweek == 1) && ($data->monday == 1)) || - (($dayofweek == 2) && ($data->tuesday == 1)) || - (($dayofweek == 3) && ($data->wednesday == 1)) || - (($dayofweek == 4) && ($data->thursday == 1)) || - (($dayofweek == 5) && ($data->friday == 1)) || - (($dayofweek == 6) && ($data->saturday == 1)) || - (($dayofweek == 0) && ($data->sunday == 1))) { - $slot->starttime = make_timestamp($eventdate['year'], $eventdate['mon'], $eventdate['mday'], - $data->starthour, $data->startminute); + if ( + (($dayofweek == 1) && ($data->monday == 1)) || + (($dayofweek == 2) && ($data->tuesday == 1)) || + (($dayofweek == 3) && ($data->wednesday == 1)) || + (($dayofweek == 4) && ($data->thursday == 1)) || + (($dayofweek == 5) && ($data->friday == 1)) || + (($dayofweek == 6) && ($data->saturday == 1)) || + (($dayofweek == 0) && ($data->sunday == 1)) + ) { + $slot->starttime = make_timestamp( + $eventdate['year'], + $eventdate['mon'], + $eventdate['mday'], + $data->starthour, + $data->startminute + ); $data->timestart = $slot->starttime; - $data->timeend = make_timestamp($eventdate['year'], $eventdate['mon'], $eventdate['mday'], - $data->endhour, $data->endminute); + $data->timeend = make_timestamp( + $eventdate['year'], + $eventdate['mon'], + $eventdate['mday'], + $data->endhour, + $data->endminute + ); // This corrects around midnight bug. if ($data->timestart > $data->timeend) { $data->timeend += DAYSECS; } + if ($data->hideuntilrel == 0) { $slot->hideuntil = time(); } else { $slot->hideuntil = make_timestamp($eventdate['year'], $eventdate['mon'], $eventdate['mday'], 6, 0) - $data->hideuntilrel; } + if ($data->emaildaterel == -1) { $slot->emaildate = 0; } else { $slot->emaildate = make_timestamp($eventdate['year'], $eventdate['mon'], $eventdate['mday'], 0, 0) - $data->emaildaterel; } + while ($slot->starttime <= $data->timeend - $slot->duration * 60) { - $conflicts = $scheduler->get_conflicts($data->timestart, $data->timestart + $slot->duration * 60, - $data->teacherid, 0, SCHEDULER_ALL); - $resolvable = (boolean) $data->forcewhenoverlap; + $conflicts = $scheduler->get_conflicts( + $data->timestart, + $data->timestart + $slot->duration * 60, + $data->teacherid, + 0, + SCHEDULER_ALL + ); + $resolvable = (bool) $data->forcewhenoverlap; foreach ($conflicts as $conflict) { $resolvable = $resolvable && $conflict->isself == 1 // Do not delete slots outside the current scheduler. @@ -117,18 +138,22 @@ function scheduler_action_doaddsession($scheduler, $formdata, moodle_url $return \mod_scheduler\event\slot_deleted::create_from_slot($cslot, 'addsession-conflict')->trigger(); $cslot->delete(); } + $conflictmsg .= get_string('deletedconflictingslots', 'scheduler', userdate($data->timestart)); $conflictmsg .= $output->doc_link('mod/scheduler/conflict', '', true); $conflictmsg .= $output->render($cl); } + \core\notification::warning($conflictmsg); } + if (!$conflicts || $resolvable) { $slotid = $DB->insert_record('scheduler_slots', $slot, true, true); $slotobj = $scheduler->get_slot($slotid); \mod_scheduler\event\slot_added::create_from_slot($slotobj)->trigger(); $countslots++; } + $slot->starttime += ($slot->duration + $data->break) * 60; $data->timestart += ($slot->duration + $data->break) * 60; } @@ -159,6 +184,7 @@ function scheduler_action_dosendmessage($scheduler, $formdata, $returnurl) { if ($data->copytomyself) { $recipients[$USER->id] = 1; } + $rawmessage = $data->body['text']; $format = $data->body['format']; $textmessage = format_text_email($rawmessage, $format); @@ -181,6 +207,7 @@ function scheduler_action_dosendmessage($scheduler, $formdata, $returnurl) { if ($htmlmessage) { $message->fullmessagehtml = $htmlmessage; } + $message->notification = '1'; message_send($message); @@ -214,6 +241,7 @@ function scheduler_action_delete_slots(array $slots, $action, moodle_url $return } else { $message = get_string('slotsdeleted', 'scheduler', $cnt); } + $messagetype = ($cnt > 0) ? \core\output\notification::NOTIFY_SUCCESS : \core\output\notification::NOTIFY_INFO; \core\notification::add($message, $messagetype); redirect($returnurl); @@ -230,13 +258,13 @@ function scheduler_action_delete_slots(array $slots, $action, moodle_url $return $slotid = required_param('slotid', PARAM_INT); $slot = $scheduler->get_slot($slotid); $permissions->ensure($permissions->can_edit_slot($slot)); - scheduler_action_delete_slots(array($slot), $action, $viewurl); + scheduler_action_delete_slots([$slot], $action, $viewurl); break; /************************************ Deleting multiple slots ***********************************************/ case 'deleteslots': $slotids = required_param('items', PARAM_SEQUENCE); $slotids = explode(",", $slotids); - $slots = array(); + $slots = []; foreach ($slotids as $slotid) { if ($slotid > 0) { $slot = $scheduler->get_slot($slotid); @@ -244,13 +272,14 @@ function scheduler_action_delete_slots(array $slots, $action, moodle_url $return $slots[] = $slot; } } + scheduler_action_delete_slots($slots, $action, $viewurl); break; /************************************ Students were seen ***************************************************/ case 'saveseen': $slotid = required_param('slotid', PARAM_INT); $slot = $scheduler->get_slot($slotid); - $seen = optional_param_array('seen', array(), PARAM_INT); + $seen = optional_param_array('seen', [], PARAM_INT); if (is_array($seen)) { foreach ($slot->get_appointments() as $app) { @@ -259,6 +288,7 @@ function scheduler_action_delete_slots(array $slots, $action, moodle_url $return $app->timemodified = time(); } } + $slot->save(); redirect($viewurl); break; @@ -268,21 +298,30 @@ function scheduler_action_delete_slots(array $slots, $action, moodle_url $return $slot = $scheduler->get_slot($slotid); $permissions->ensure($permissions->can_edit_slot($slot)); - $oldstudents = array(); + $oldstudents = []; foreach ($slot->get_appointments() as $app) { $oldstudents[] = $app->studentid; $slot->remove_appointment($app); } + // Notify the student. if ($scheduler->allownotifications) { foreach ($oldstudents as $oldstudent) { - include_once($CFG->dirroot.'/mod/scheduler/mailtemplatelib.php'); - - $student = $DB->get_record('user', array('id' => $oldstudent)); - $teacher = $DB->get_record('user', array('id' => $slot->teacherid)); - - scheduler_messenger::send_slot_notification($slot, 'bookingnotification', 'teachercancelled', - $teacher, $student, $teacher, $student, $COURSE); + include_once($CFG->dirroot . '/mod/scheduler/mailtemplatelib.php'); + + $student = $DB->get_record('user', ['id' => $oldstudent]); + $teacher = $DB->get_record('user', ['id' => $slot->teacherid]); + + scheduler_messenger::send_slot_notification( + $slot, + 'bookingnotification', + 'teachercancelled', + $teacher, + $student, + $teacher, + $student, + $COURSE + ); } } diff --git a/teacherview.php b/teacherview.php index a5dc7094..556fdaf3 100644 --- a/teacherview.php +++ b/teacherview.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -use \mod_scheduler\model\scheduler; +use mod_scheduler\model\scheduler; /** * Print a selection box of existing slots to be scheduler in @@ -40,7 +40,7 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid $startdatemem = ''; $starttimemem = ''; - $availableslotsmenu = array(); + $availableslotsmenu = []; foreach ($availableslots as $slot) { $startdatecnv = $output->userdate($slot->starttime); $starttimecnv = $output->usertime($slot->starttime); @@ -51,8 +51,10 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid $startdatemem = $startdatecnv; $starttimemem = $starttimecnv; - $url = new moodle_url('/mod/scheduler/view.php', - array('id' => $scheduler->cmid, 'slotid' => $slot->id, 'sesskey' => sesskey())); + $url = new moodle_url( + '/mod/scheduler/view.php', + ['id' => $scheduler->cmid, 'slotid' => $slot->id, 'sesskey' => sesskey()] + ); if ($groupid) { $url->param('what', 'schedulegroup'); $url->param('subaction', 'dochooseslot'); @@ -62,6 +64,7 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid $url->param('subaction', 'dochooseslot'); $url->param('studentid', $studentid); } + $availableslotsmenu[$url->out()] = "$startdatestr $starttimestr"; } @@ -92,25 +95,27 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid if (has_capability('moodle/site:accessallgroups', $context)) { $userfilter = 0; } + $groupsicansee = ''; $groupsicurrentlysee = ''; if ($groupmode) { if ($userfilter) { $groupsicansee = groups_get_all_groups($COURSE->id, $userfilter, $cm->groupingid); } + $groupsicurrentlysee = $groupsicansee; if ($currentgroup) { if ($userfilter && !groups_is_member($currentgroup, $userfilter)) { - $groupsicurrentlysee = array(); + $groupsicurrentlysee = []; } else { $cgobj = groups_get_group($currentgroup); - $groupsicurrentlysee = array($currentgroup => $cgobj); + $groupsicurrentlysee = [$currentgroup => $cgobj]; } } } // Find groups which the current teacher can schedule as a group ($groupsicanschedule). -$groupsicanschedule = array(); +$groupsicanschedule = []; if ($scheduler->is_group_scheduling_enabled()) { $groupsicanschedule = groups_get_all_groups($COURSE->id, $userfilter, $scheduler->bookingrouping); } @@ -123,29 +128,29 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid } -$taburl = new moodle_url('/mod/scheduler/view.php', array('id' => $scheduler->cmid, 'what' => 'view', 'subpage' => $subpage)); +$taburl = new moodle_url('/mod/scheduler/view.php', ['id' => $scheduler->cmid, 'what' => 'view', 'subpage' => $subpage]); -$baseurl = new moodle_url('/mod/scheduler/view.php', array( +$baseurl = new moodle_url('/mod/scheduler/view.php', [ 'id' => $scheduler->cmid, 'subpage' => $subpage, - 'offset' => $offset -)); + 'offset' => $offset, +]); // The URL that is used for jumping back to the view (e.g., after an action is performed). -$viewurl = new moodle_url($baseurl, array('what' => 'view')); +$viewurl = new moodle_url($baseurl, ['what' => 'view']); $PAGE->set_url($viewurl); if ($action != 'view') { - require_once($CFG->dirroot.'/mod/scheduler/slotforms.php'); - require_once($CFG->dirroot.'/mod/scheduler/teacherview.controller.php'); + require_once($CFG->dirroot . '/mod/scheduler/slotforms.php'); + require_once($CFG->dirroot . '/mod/scheduler/teacherview.controller.php'); } /************************************ View : New single slot form ****************************************/ if ($action == 'addslot') { $permissions->ensure($permissions->can_edit_own_slots()); - $actionurl = new moodle_url($baseurl, array('what' => 'addslot')); + $actionurl = new moodle_url($baseurl, ['what' => 'addslot']); if (!$scheduler->has_available_teachers()) { throw new moodle_exception('needteachers', 'scheduler', $viewurl); @@ -158,10 +163,12 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid } else if ($formdata = $mform->get_data()) { $slot = $mform->save_slot(0, $formdata); \mod_scheduler\event\slot_added::create_from_slot($slot)->trigger(); - redirect($viewurl, - get_string('oneslotadded', 'scheduler'), - 0, - \core\output\notification::NOTIFY_SUCCESS); + redirect( + $viewurl, + get_string('oneslotadded', 'scheduler'), + 0, + \core\output\notification::NOTIFY_SUCCESS + ); } else { echo $output->header(); echo $output->heading(get_string('addsingleslot', 'scheduler')); @@ -170,26 +177,25 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid die; } } + /************************************ View : Update single slot form ****************************************/ if ($action == 'updateslot') { - $slotid = required_param('slotid', PARAM_INT); $slot = $scheduler->get_slot($slotid); $permissions->ensure($permissions->can_edit_slot($slot)); if ($slot->starttime % 300 !== 0 || $slot->duration % 5 !== 0) { - $timeoptions = array('step' => 1, 'optional' => false); + $timeoptions = ['step' => 1, 'optional' => false]; } else { - $timeoptions = array('step' => 5, 'optional' => false); + $timeoptions = ['step' => 5, 'optional' => false]; } - $actionurl = new moodle_url($baseurl, array('what' => 'updateslot', 'slotid' => $slotid)); + $actionurl = new moodle_url($baseurl, ['what' => 'updateslot', 'slotid' => $slotid]); - $mform = new scheduler_editslot_form($actionurl, $scheduler, $cm, $groupsicansee, array( + $mform = new scheduler_editslot_form($actionurl, $scheduler, $cm, $groupsicansee, [ 'slotid' => $slotid, - 'timeoptions' => $timeoptions) - ); + 'timeoptions' => $timeoptions, ]); $data = $mform->prepare_formdata($slot); $mform->set_data($data); @@ -197,10 +203,12 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid redirect($viewurl); } else if ($formdata = $mform->get_data()) { $mform->save_slot($slotid, $formdata); - redirect($viewurl, - get_string('slotupdated', 'scheduler'), - 0, - \core\output\notification::NOTIFY_SUCCESS); + redirect( + $viewurl, + get_string('slotupdated', 'scheduler'), + 0, + \core\output\notification::NOTIFY_SUCCESS + ); } else { echo $output->header(); echo $output->heading(get_string('updatesingleslot', 'scheduler')); @@ -208,14 +216,13 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid echo $output->footer($course); die; } - } + /************************************ Add session multiple slots form ****************************************/ if ($action == 'addsession') { - $permissions->ensure($permissions->can_edit_own_slots()); - $actionurl = new moodle_url($baseurl, array('what' => 'addsession')); + $actionurl = new moodle_url($baseurl, ['what' => 'addsession']); if (!$scheduler->has_available_teachers()) { throw new moodle_exception('needteachers', 'scheduler', $viewurl); @@ -247,27 +254,31 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid $slot = $scheduler->get_slot($slotid); $studentid = required_param('studentid', PARAM_INT); - $actionurl = new moodle_url($baseurl, array('what' => 'updateslot', 'slotid' => $slotid)); + $actionurl = new moodle_url($baseurl, ['what' => 'updateslot', 'slotid' => $slotid]); $repeats = $slot->get_appointment_count() + 1; - $mform = new scheduler_editslot_form($actionurl, $scheduler, $cm, $groupsicansee, - array('slotid' => $slotid, 'repeats' => $repeats)); + $mform = new scheduler_editslot_form( + $actionurl, + $scheduler, + $cm, + $groupsicansee, + ['slotid' => $slotid, 'repeats' => $repeats] + ); $data = $mform->prepare_formdata($slot); $data->studentid[] = $studentid; $mform->set_data($data); echo $output->heading(get_string('updatesingleslot', 'scheduler'), 2); $mform->display(); - } else if (empty($subaction)) { $studentid = required_param('studentid', PARAM_INT); - $student = $DB->get_record('user', array('id' => $studentid), '*', MUST_EXIST); + $student = $DB->get_record('user', ['id' => $studentid], '*', MUST_EXIST); - $actionurl = new moodle_url($baseurl, array('what' => 'addslot')); + $actionurl = new moodle_url($baseurl, ['what' => 'addslot']); $mform = new scheduler_editslot_form($actionurl, $scheduler, $cm, $groupsicansee); - $data = array(); + $data = []; $data['studentid'][0] = $studentid; $mform->set_data($data); @@ -284,50 +295,54 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid echo $output->footer(); die(); } + /************************************ Schedule a whole group in form ***********************************************/ if ($action == 'schedulegroup') { - $permissions->ensure($permissions->can_edit_own_slots()); $groupid = required_param('groupid', PARAM_INT); - $group = $DB->get_record('groups', array('id' => $groupid), '*', MUST_EXIST); + $group = $DB->get_record('groups', ['id' => $groupid], '*', MUST_EXIST); $members = groups_get_members($groupid); echo $output->header(); if ($subaction == 'dochooseslot') { - $slotid = required_param('slotid', PARAM_INT); $groupid = required_param('groupid', PARAM_INT); $slot = $scheduler->get_slot($slotid); - $actionurl = new moodle_url($baseurl, array('what' => 'updateslot', 'slotid' => $slotid)); + $actionurl = new moodle_url($baseurl, ['what' => 'updateslot', 'slotid' => $slotid]); $repeats = $slot->get_appointment_count() + count($members); - $mform = new scheduler_editslot_form($actionurl, $scheduler, $cm, $groupsicansee, - array('slotid' => $slotid, 'repeats' => $repeats)); + $mform = new scheduler_editslot_form( + $actionurl, + $scheduler, + $cm, + $groupsicansee, + ['slotid' => $slotid, 'repeats' => $repeats] + ); $data = $mform->prepare_formdata($slot); foreach ($members as $member) { $data->studentid[] = $member->id; } + $mform->set_data($data); echo $output->heading(get_string('updatesingleslot', 'scheduler'), 3); $mform->display(); - } else if (empty($subaction)) { + $actionurl = new moodle_url($baseurl, ['what' => 'addslot']); - $actionurl = new moodle_url($baseurl, array('what' => 'addslot')); - - $data = array(); + $data = []; $i = 0; foreach ($members as $member) { $data['studentid'][$i] = $member->id; $i++; } + $data['exclusivity'] = $i; - $mform = new scheduler_editslot_form($actionurl, $scheduler, $cm, $groupsicansee, array('repeats' => $i)); + $mform = new scheduler_editslot_form($actionurl, $scheduler, $cm, $groupsicansee, ['repeats' => $i]); $mform->set_data($data); echo $output->heading(get_string('scheduleappointment', 'scheduler', $group->name)); @@ -338,8 +353,8 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid echo $output->heading(get_string('scheduleinnew', 'scheduler'), 3); $mform->display(); echo $output->box_end(); - } + echo $output->footer(); die(); } @@ -348,21 +363,26 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid if ($action == 'sendmessage') { $permissions->ensure($permissions->can_edit_own_slots()); - require_once($CFG->dirroot.'/mod/scheduler/message_form.php'); + require_once($CFG->dirroot . '/mod/scheduler/message_form.php'); $template = optional_param('template', 'none', PARAM_ALPHA); $recipientids = required_param('recipients', PARAM_SEQUENCE); - $actionurl = new moodle_url('/mod/scheduler/view.php', - array('what' => 'sendmessage', 'id' => $cm->id, 'subpage' => $subpage, - 'template' => $template, 'recipients' => $recipientids)); + $actionurl = new moodle_url( + '/mod/scheduler/view.php', + ['what' => 'sendmessage', 'id' => $cm->id, 'subpage' => $subpage, + 'template' => $template, + 'recipients' => $recipientids, + ] + ); - $templatedata = array(); + $templatedata = []; if ($template != 'none') { $vars = scheduler_messenger::get_scheduler_variables($scheduler, null, $USER, null, $COURSE, null); $templatedata['subject'] = scheduler_messenger::compile_mail_template($template, 'subject', $vars); $templatedata['body'] = scheduler_messenger::compile_mail_template($template, 'html', $vars); } + $templatedata['recipients'] = $DB->get_records_list('user', 'id', explode(',', $recipientids), 'lastname,firstname'); $mform = new scheduler_message_form($actionurl, $scheduler, $templatedata); @@ -390,11 +410,13 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid // Print top tabs. -$actionurl = new moodle_url($viewurl, array('sesskey' => sesskey())); +$actionurl = new moodle_url($viewurl, ['sesskey' => sesskey()]); -$inactive = array(); -if ($DB->count_records('scheduler_slots', array('schedulerid' => $scheduler->id)) <= - $DB->count_records('scheduler_slots', array('schedulerid' => $scheduler->id, 'teacherid' => $USER->id)) ) { +$inactive = []; +if ( + $DB->count_records('scheduler_slots', ['schedulerid' => $scheduler->id]) <= + $DB->count_records('scheduler_slots', ['schedulerid' => $scheduler->id, 'teacherid' => $USER->id]) +) { // We are alone in this scheduler. $inactive[] = 'allappointments'; if ($subpage = 'allappointments') { @@ -411,10 +433,11 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid } else { $a = new stdClass(); $a->groupmode = get_string($groupmode == VISIBLEGROUPS ? 'groupsvisible' : 'groupsseparate'); - $groupnames = array(); + $groupnames = []; foreach ($groupsthatcanseeme as $id => $group) { $groupnames[] = $group->name; } + $a->grouplist = implode(', ', $groupnames); $messagekey = $groupsthatcanseeme ? 'groupmodeyourgroups' : 'groupmodeyourgroupsempty'; $message = get_string($messagekey, 'scheduler', $a); @@ -431,6 +454,7 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid $slotgroup = 0; $subpage = 'myappointments'; } + $sqlcount = $scheduler->count_slots_for_teacher($teacherid, $slotgroup); $pagesize = 25; @@ -442,6 +466,7 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid $offset = 0; } } + if ($offset * $pagesize >= $sqlcount && $sqlcount > 0) { $offset = floor(($sqlcount - 1) / $pagesize); } @@ -458,36 +483,53 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid $commandbar = new scheduler_command_bar(); $commandbar->title = get_string('actions', 'scheduler'); -$addbuttons = array(); -$addbuttons[] = $commandbar->action_menu_link(new moodle_url($actionurl, array('what' => 'addsession')), 'addsession', 't/add'); -$addbuttons[] = $commandbar->action_menu_link(new moodle_url($actionurl, array('what' => 'addslot')), 'addsingleslot', 't/add'); +$addbuttons = []; +$addbuttons[] = $commandbar->action_menu_link(new moodle_url($actionurl, ['what' => 'addsession']), 'addsession', 't/add'); +$addbuttons[] = $commandbar->action_menu_link(new moodle_url($actionurl, ['what' => 'addslot']), 'addsingleslot', 't/add'); $commandbar->add_group(get_string('addcommands', 'scheduler'), $addbuttons); // If slots already exist, also show delete buttons. if ($slots) { - $delbuttons = array(); + $delbuttons = []; - $delselectedurl = new moodle_url($actionurl, array('what' => 'deleteslots')); + $delselectedurl = new moodle_url($actionurl, ['what' => 'deleteslots']); $PAGE->requires->js_call_amd('mod_scheduler/delselected', 'init', [$delselectedurl->out(false)]); - $delselected = $commandbar->action_menu_link($delselectedurl, 'deleteselection', 't/delete', - 'confirmdelete-selected', 'delselected'); - $delselected->formid = 'delselected'; + $delselected = $commandbar->action_menu_link( + $delselectedurl, + 'deleteselection', + 't/delete', + 'confirmdelete-selected', + 'delselected' + ); $delbuttons[] = $delselected; if ($permissions->can_edit_all_slots() && $subpage == 'allappointments') { $delbuttons[] = $commandbar->action_menu_link( - new moodle_url($actionurl, array('what' => 'deleteall')), - 'deleteallslots', 't/delete', 'confirmdelete-all'); + new moodle_url($actionurl, ['what' => 'deleteall']), + 'deleteallslots', + 't/delete', + 'confirmdelete-all' + ); $delbuttons[] = $commandbar->action_menu_link( - new moodle_url($actionurl, array('what' => 'deleteallunused')), - 'deleteallunusedslots', 't/delete', 'confirmdelete-unused'); + new moodle_url($actionurl, ['what' => 'deleteallunused']), + 'deleteallunusedslots', + 't/delete', + 'confirmdelete-unused' + ); } + $delbuttons[] = $commandbar->action_menu_link( - new moodle_url($actionurl, array('what' => 'deleteunused')), - 'deleteunusedslots', 't/delete', 'confirmdelete-myunused'); + new moodle_url($actionurl, ['what' => 'deleteunused']), + 'deleteunusedslots', + 't/delete', + 'confirmdelete-myunused' + ); $delbuttons[] = $commandbar->action_menu_link( - new moodle_url($actionurl, array('what' => 'deleteonlymine')), - 'deletemyslots', 't/delete', 'confirmdelete-mine'); + new moodle_url($actionurl, ['what' => 'deleteonlymine']), + 'deletemyslots', + 't/delete', + 'confirmdelete-mine' + ); $commandbar->add_group(get_string('deletecommands', 'scheduler'), $delbuttons); } @@ -497,12 +539,10 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid // Some slots already exist - prepare the table of slots. if ($slots) { - $slotman = new scheduler_slot_manager($scheduler, $actionurl); $slotman->showteacher = ($subpage == 'allappointments'); foreach ($slots as $slot) { - $editable = $permissions->can_edit_slot($slot); $studlist = new scheduler_student_list($slotman->scheduler); @@ -512,10 +552,16 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid $studlist->linkappointment = true; $studlist->checkboxname = 'seen[]'; $studlist->buttontext = get_string('saveseen', 'scheduler'); - $studlist->actionurl = new moodle_url($actionurl, array('what' => 'saveseen', 'slotid' => $slot->id)); + $studlist->actionurl = new moodle_url($actionurl, ['what' => 'saveseen', 'slotid' => $slot->id]); foreach ($slot->get_appointments() as $app) { - $studlist->add_student($app, false, $app->is_attended(), true, $scheduler->uses_studentdata(), - $permissions->can_edit_attended($app)); + $studlist->add_student( + $app, + false, + $app->is_attended(), + true, + $scheduler->uses_studentdata(), + $permissions->can_edit_attended($app) + ); } $slotman->add_slot($slot, $studlist, $editable); @@ -529,13 +575,12 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid // Instruction for teacher to click Seen box after appointment. echo html_writer::div(get_string('markseen', 'scheduler')); - } $groupfilter = ($subpage == 'myappointments') ? $groupsthatcanseeme : $groupsicurrentlysee; $maxlistsize = get_config('mod_scheduler', 'maxstudentlistsize'); -$students = array(); -$reminderstudents = array(); +$students = []; +$reminderstudents = []; if ($groupfilter === '') { $students = $scheduler->get_students_for_scheduling('', $maxlistsize); if ($scheduler->allows_unlimited_bookings()) { @@ -555,22 +600,21 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid if ($students === 0) { $nostudentstr = get_string('noexistingstudents', 'scheduler'); if ($COURSE->id == SITEID) { - $nostudentstr .= '
'.get_string('howtoaddstudents', 'scheduler'); + $nostudentstr .= '
' . get_string('howtoaddstudents', 'scheduler'); } + echo $output->notification($nostudentstr, 'notifyproblem'); } else if (is_integer($students)) { // There are too many students who still have to make appointments, don't display a list. $toomanystr = get_string('missingstudentsmany', 'scheduler', $students); echo $output->notification($toomanystr, 'notifymessage'); - } else if (count($students) > 0) { - if (count($reminderstudents) > 0) { $studids = implode(',', array_keys($reminderstudents)); - $messageurl = new moodle_url($actionurl, array('what' => 'sendmessage', 'recipients' => $studids)); - $invitationurl = new moodle_url($messageurl, array('template' => 'invite')); - $reminderurl = new moodle_url($messageurl, array('template' => 'invitereminder')); + $messageurl = new moodle_url($actionurl, ['what' => 'sendmessage', 'recipients' => $studids]); + $invitationurl = new moodle_url($messageurl, ['template' => 'invite']); + $reminderurl = new moodle_url($messageurl, ['template' => 'invitereminder']); $maildisplay = ''; $maildisplay .= html_writer::link($invitationurl, get_string('sendinvitation', 'scheduler')); @@ -586,35 +630,39 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid } $userfields = scheduler_get_user_fields(null, $context); - $fieldtitles = array(); + $fieldtitles = []; foreach ($userfields as $f) { $fieldtitles[] = $f->title; } + $studtable = new scheduler_scheduling_list($scheduler, $fieldtitles); $studtable->id = 'studentstoschedule'; foreach ($students as $student) { $picture = $output->user_picture($student); $name = $output->user_profile_link($scheduler, $student); - $actions = array(); + $actions = []; $actions[] = new action_menu_link_secondary( - new moodle_url($actionurl, array('what' => 'schedule', 'studentid' => $student->id)), - new pix_icon('e/insert_date', '', 'moodle'), - get_string('scheduleinslot', 'scheduler') ); + new moodle_url($actionurl, ['what' => 'schedule', 'studentid' => $student->id]), + new pix_icon('e/insert_date', '', 'moodle'), + get_string('scheduleinslot', 'scheduler') + ); $actions[] = new action_menu_link_secondary( - new moodle_url($actionurl, array('what' => 'markasseennow', 'studentid' => $student->id)), - new pix_icon('t/approve', '', 'moodle'), - get_string('markasseennow', 'scheduler') ); + new moodle_url($actionurl, ['what' => 'markasseennow', 'studentid' => $student->id]), + new pix_icon('t/approve', '', 'moodle'), + get_string('markasseennow', 'scheduler') + ); $userfields = scheduler_get_user_fields($student, $context); - $fieldvals = array(); + $fieldvals = []; foreach ($userfields as $f) { $fieldvals[] = $f->value; } + $studtable->add_line($picture, $name, $fieldvals, $actions); } - $divclass = 'schedulelist '.($scheduler->is_group_scheduling_enabled() ? 'halfsize' : 'fullsize'); + $divclass = 'schedulelist ' . ($scheduler->is_group_scheduling_enabled() ? 'halfsize' : 'fullsize'); echo html_writer::start_div($divclass); echo $output->heading(get_string('schedulestudents', 'scheduler'), 3); @@ -623,7 +671,6 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid echo html_writer::end_div(); if ($scheduler->is_group_scheduling_enabled()) { - // Print list of groups that can be scheduled. echo html_writer::start_div('schedulelist halfsize'); @@ -632,7 +679,7 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid if (empty($groupsicanschedule)) { echo $output->notification(get_string('nogroups', 'scheduler')); } else { - $grouptable = new scheduler_scheduling_list($scheduler, array()); + $grouptable = new scheduler_scheduling_list($scheduler, []); $grouptable->id = 'groupstoschedule'; $groupcnt = 0; @@ -641,25 +688,28 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid if (empty($members)) { continue; } - if (!$scheduler->has_slots_booked_for_group($group->id, false, $scheduler->schedulermode == 'onetime')) { + if (!$scheduler->has_slots_booked_for_group($group->id, false, $scheduler->schedulermode == 'onetime')) { $picture = print_group_picture($group, $course->id, false, true, true); $name = $group->name; - $groupmembers = array(); + $groupmembers = []; foreach ($members as $member) { $groupmembers[] = fullname($member); } - $name .= ' ['. implode(', ', $groupmembers) . ']'; - $actions = array(); + + $name .= ' [' . implode(', ', $groupmembers) . ']'; + $actions = []; $actions[] = new action_menu_link_secondary( - new moodle_url($actionurl, array('what' => 'schedulegroup', 'groupid' => $group->id)), - new pix_icon('e/insert_date', '', 'moodle'), - get_string('scheduleinslot', 'scheduler') ); + new moodle_url($actionurl, ['what' => 'schedulegroup', 'groupid' => $group->id]), + new pix_icon('e/insert_date', '', 'moodle'), + get_string('scheduleinslot', 'scheduler') + ); - $grouptable->add_line($picture, $name, array(), $actions); + $grouptable->add_line($picture, $name, [], $actions); $groupcnt++; } } + // Print table of groups that still need to make appointments. if ($groupcnt > 0) { echo $output->render($grouptable); @@ -667,10 +717,11 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid echo $output->notification(get_string('nogroups', 'scheduler')); } } + echo html_writer::end_div(); } - } else { echo $output->notification(get_string('noexistingstudents', 'scheduler')); } + echo $output->footer(); diff --git a/templates/action_menu.mustache b/templates/action_menu.mustache index b8eafd95..bd4e5d8f 100644 --- a/templates/action_menu.mustache +++ b/templates/action_menu.mustache @@ -23,6 +23,7 @@ { "classes": "", "instance": "1", + "triggerrole": "button", "primary": { "items": [{"rawhtml": "

Item in primary menu

"}] }, diff --git a/templates/action_menu_link.mustache b/templates/action_menu_link.mustache index 28039a02..9ed19193 100644 --- a/templates/action_menu_link.mustache +++ b/templates/action_menu_link.mustache @@ -21,6 +21,7 @@ Example context (json): { + "id": "example-action-menu-link", "text": "Example link text", "showtext": true, "url": "http://example.com/link" diff --git a/templates/action_menu_trigger.mustache b/templates/action_menu_trigger.mustache index 5d467d8f..98b6029a 100644 --- a/templates/action_menu_trigger.mustache +++ b/templates/action_menu_trigger.mustache @@ -15,13 +15,14 @@ along with Moodle. If not, see . }} {{! - @template core/action_menu_trigger + @template mod_scheduler/action_menu_trigger Action menu trigger. Example context (json): { "actiontext": "Example link text", + "bs5": "bs5", "title": "Example link title", "triggerrole": "button", "triggerattributes": [ @@ -39,7 +40,7 @@ "classes": "menu align-tr-br", "dropdownalignment": "dropdown-menu-right", "attributes": [ - {"name": "id", "value": "action-menu-0-menu"}, + {"name": "id", "value": "action-menu-1-menu"}, {"name": "data-rel", "value": "menu-content"}, {"name": "role", "value": "menu"}, {"name": "data-align", "value": "tr-br"} @@ -89,7 +90,7 @@ class="{{triggerextraclasses}} dropdown-toggle icon-no-margin" id="action-menu-toggle-{{instance}}" aria-label="{{title}}" - data-toggle="dropdown" + data-{{#bs5}}bs-{{/bs5}}toggle="dropdown" role="{{triggerrole}}" aria-haspopup="true" aria-expanded="false" diff --git a/templates/thumbsdown_icon.mustache b/templates/thumbsdown_icon.mustache new file mode 100644 index 00000000..ec4081eb --- /dev/null +++ b/templates/thumbsdown_icon.mustache @@ -0,0 +1,46 @@ +{{! + 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 . +}} +{{! + @template mod_scheduler/thumbsdown_icon + + Scheduler thumbs-down icon template. + + The purpose of this template is to render a thumbs-down icon. + + Classes required for JS: + * none + + Data attributes required for JS: + * none + + Context variables required for this template: + * pix + * title + * extraclasses + * aria-hidden - whether the icon is hidden from assistive technologies + + Example context (json): + { + "key": "fa-meh-o", + "title": "Meh", + "alt": "Meh Meh", + "extraclasses": "fa-spin", + "unmappedIcon": false, + "aria-hidden": false + } +}} + diff --git a/tests/behat/behat_mod_scheduler.php b/tests/behat/behat_mod_scheduler.php index ad7e7db0..96ca6459 100644 --- a/tests/behat/behat_mod_scheduler.php +++ b/tests/behat/behat_mod_scheduler.php @@ -24,9 +24,11 @@ */ // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php. + +use Behat\Gherkin\Node\TableNode; + require_once(__DIR__ . '/../../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given, Behat\Behat\Context\Step\When as When, Behat\Gherkin\Node\TableNode as TableNode; /** * Scheduler-related steps definitions. * @@ -35,8 +37,8 @@ * @copyright 2015 Henning Bostelmann * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class behat_mod_scheduler extends behat_base { - +class behat_mod_scheduler extends behat_base +{ /** * Adds a series of slots to the scheduler * @@ -49,25 +51,28 @@ class behat_mod_scheduler extends behat_base { * @param TableNode $fielddata */ public function i_add_a_slot_days_ahead_at_in_scheduler_and_i_fill_the_form_with( - $daysahead, $time, $activityname, TableNode $fielddata) { - + $daysahead, + $time, + $activityname, + TableNode $fielddata + ) { $hours = floor($time / 100); $mins = $time - 100 * $hours; $startdate = time() + $daysahead * DAYSECS; - $this->execute('behat_navigation::i_am_on_page_instance', array($this->escape($activityname), 'Activity')); - $this->execute('behat_general::i_click_on', array('Add slots', 'link')); + $this->execute('behat_navigation::i_am_on_page_instance', [$this->escape($activityname), 'Activity']); + $this->execute('behat_general::i_click_on', ['Add slots', 'link']); $this->execute('behat_general::click_link', 'Add single slot'); $this->execute('behat_forms::i_expand_all_fieldsets'); - $rows = array(); - $rows[] = array('starttime[day]', date("j", $startdate)); - $rows[] = array('starttime[month]', date("F", $startdate)); - $rows[] = array('starttime[year]', date("Y", $startdate)); - $rows[] = array('starttime[hour]', $hours); - $rows[] = array('starttime[minute]', $mins); - $rows[] = array('duration', '45'); + $rows = []; + $rows[] = ['starttime[day]', date("j", $startdate)]; + $rows[] = ['starttime[month]', date("F", $startdate)]; + $rows[] = ['starttime[year]', date("Y", $startdate)]; + $rows[] = ['starttime[hour]', $hours]; + $rows[] = ['starttime[minute]', $mins]; + $rows[] = ['duration', '45']; foreach ($fielddata->getRows() as $row) { if ($row[0] == 'studentid[0]') { $this->execute('behat_forms::i_open_the_autocomplete_suggestions_list'); @@ -76,9 +81,10 @@ public function i_add_a_slot_days_ahead_at_in_scheduler_and_i_fill_the_form_with $rows[] = $row; } } + $this->execute('behat_forms::i_set_the_following_fields_to_these_values', new TableNode($rows)); - $this->execute('behat_general::i_click_on', array('Save changes', 'button')); + $this->execute('behat_general::i_click_on', ['Save changes', 'button']); } @@ -93,32 +99,34 @@ public function i_add_a_slot_days_ahead_at_in_scheduler_and_i_fill_the_form_with * @param TableNode $fielddata */ public function i_add_slots_days_ahead_in_scheduler_and_i_fill_the_form_with( - $slotcount, $daysahead, $activityname, TableNode $fielddata) { - + $slotcount, + $daysahead, + $activityname, + TableNode $fielddata + ) { $startdate = time() + $daysahead * DAYSECS; - $this->execute('behat_navigation::i_am_on_page_instance', array($this->escape($activityname), 'Activity')); - $this->execute('behat_general::i_click_on', array('Add slots', 'link')); + $this->execute('behat_navigation::i_am_on_page_instance', [$this->escape($activityname), 'Activity']); + $this->execute('behat_general::i_click_on', ['Add slots', 'link']); $this->execute('behat_general::click_link', 'Add repeated slots'); - $rows = array(); - $rows[] = array('rangestart[day]', date("j", $startdate)); - $rows[] = array('rangestart[month]', date("F", $startdate)); - $rows[] = array('rangestart[year]', date("Y", $startdate)); - $rows[] = array('Saturday', '1'); - $rows[] = array('Sunday', '1'); - $rows[] = array('starthour', '1'); - $rows[] = array('endhour', $slotcount + 1); - $rows[] = array('duration', '45'); - $rows[] = array('break', '15'); + $rows = []; + $rows[] = ['rangestart[day]', date("j", $startdate)]; + $rows[] = ['rangestart[month]', date("F", $startdate)]; + $rows[] = ['rangestart[year]', date("Y", $startdate)]; + $rows[] = ['Saturday', '1']; + $rows[] = ['Sunday', '1']; + $rows[] = ['starthour', '1']; + $rows[] = ['endhour', $slotcount + 1]; + $rows[] = ['duration', '45']; + $rows[] = ['break', '15']; foreach ($fielddata->getRows() as $row) { $rows[] = $row; } $this->execute('behat_forms::i_set_the_following_fields_to_these_values', new TableNode($rows)); - $this->execute('behat_general::i_click_on', array('Save changes', 'button')); - + $this->execute('behat_general::i_click_on', ['Save changes', 'button']); } /** @@ -129,18 +137,24 @@ public function i_add_slots_days_ahead_in_scheduler_and_i_fill_the_form_with( * @Given /^I add the upcoming events block globally$/ */ public function i_add_the_upcoming_events_block_globally() { + global $CFG; + if ($CFG->version > 2026042000) { + // Moodle 5.2 onwards has "Home" not enabled by default. + set_config('enablemyhome', 1); + set_config('defaulthomepage', 1); + } - $this->execute('behat_data_generators::the_following_entities_exist', array('users', - new TableNode(array( - array('username', 'firstname', 'lastname', 'email'), - array('globalmanager1', 'GlobalManager', '1', 'globalmanager1@example.com') - )) ) ); + $this->execute('behat_data_generators::the_following_entities_exist', ['users', + new TableNode([ + ['username', 'firstname', 'lastname', 'email'], + ['globalmanager1', 'GlobalManager', '1', 'globalmanager1@example.com'], + ]), ]); - $this->execute('behat_data_generators::the_following_entities_exist', array('system role assigns', - new TableNode(array( - array('user', 'role'), - array('globalmanager1', 'manager') - )) ) ); + $this->execute('behat_data_generators::the_following_entities_exist', ['system role assigns', + new TableNode([ + ['user', 'role'], + ['globalmanager1', 'manager'], + ]), ]); $this->execute('behat_auth::i_log_in_as', 'globalmanager1'); $this->execute('behat_general::i_am_on_site_homepage'); @@ -149,12 +163,11 @@ public function i_add_the_upcoming_events_block_globally() { $this->execute('behat_blocks::i_open_the_blocks_action_menu', 'Upcoming events'); $this->execute('behat_general::click_link', 'Configure Upcoming events block'); - $this->execute('behat_forms::i_set_the_following_fields_to_these_values', new TableNode(array( - array('Page contexts', 'Display throughout the entire site') - )) ); - $this->execute('behat_general::i_click_on', array('Save changes', 'button')); + $this->execute('behat_forms::i_set_the_following_fields_to_these_values', new TableNode([ + ['Page contexts', 'Display throughout the entire site'], + ])); + $this->execute('behat_general::i_click_on', ['Save changes', 'button']); $this->execute('behat_auth::i_log_out'); - } /** @@ -171,7 +184,7 @@ public function i_click_on_item_in_the_nth_autocomplete_list($item, $listnumber) $this->execute('behat_general::i_click_on', [$downarrowtarget, 'xpath_element']); $xpathtarget = "(//descendant::ul[@class='form-autocomplete-suggestions'][$listnumber]//" - ."*[contains(concat('|', string(.), '|'),'|$item|')])"; + . "*[contains(concat('|', string(.), '|'),'|$item|')])"; $this->execute('behat_general::i_click_on', [$xpathtarget, 'xpath_element']); } } diff --git a/tests/behat/grades.feature b/tests/behat/grades.feature index 06fa1954..d52f6e2f 100644 --- a/tests/behat/grades.feature +++ b/tests/behat/grades.feature @@ -166,7 +166,7 @@ Feature: Teachers can grade student appointments with totals automatically compu And I expand all fieldsets And I set the field "Grading strategy" to "Take the highest grade" And I press "Save and display" - And I click on "Edit" "icon" in the "3:00 AM" "table_row" + And I click on "//table[@id='slotmanager']//tr[1]//td[contains(@class,'lastcol')]//a[@aria-label='Edit']" "xpath_element" And I set the following fields to these values: | grade[0] | 5 | And I click on "Save" "button" @@ -175,7 +175,7 @@ Feature: Teachers can grade student appointments with totals automatically compu And I should see "5.00" in the "div.totalgrade" "css_element" When I am on the "scheduler1" Activity page logged in as "teacher1" - And I click on "Edit" "icon" in the "4:00 AM" "table_row" + And I click on "//table[@id='slotmanager']//tr[2]//td[contains(@class,'lastcol')]//a[@aria-label='Edit']" "xpath_element" And I set the following fields to these values: | grade[0] | 7 | And I click on "Save" "button" @@ -185,7 +185,7 @@ Feature: Teachers can grade student appointments with totals automatically compu And I should see "7.00" in the "div.totalgrade" "css_element" When I am on the "scheduler1" Activity page logged in as "teacher1" - And I click on "Edit" "icon" in the "4:00 AM" "table_row" + And I click on "//table[@id='slotmanager']//tr[2]//td[contains(@class,'lastcol')]//a[@aria-label='Edit']" "xpath_element" And I set the following fields to these values: | grade[0] | 2 | And I click on "Save" "button" @@ -195,7 +195,7 @@ Feature: Teachers can grade student appointments with totals automatically compu And I should see "5.00" in the "div.totalgrade" "css_element" When I am on the "scheduler1" Activity page logged in as "teacher1" - And I click on "Edit" "icon" in the "3:00 AM" "table_row" + And I click on "//table[@id='slotmanager']//tr[1]//td[contains(@class,'lastcol')]//a[@aria-label='Edit']" "xpath_element" And I set the following fields to these values: | grade[0] | No grade | And I click on "Save" "button" diff --git a/tests/generator/behat_mod_scheduler_generator.php b/tests/generator/behat_mod_scheduler_generator.php index 19ec172e..5d906f69 100644 --- a/tests/generator/behat_mod_scheduler_generator.php +++ b/tests/generator/behat_mod_scheduler_generator.php @@ -22,8 +22,8 @@ * @copyright 2022 Henning Bostelmann * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class behat_mod_scheduler_generator extends behat_generator_base { - +class behat_mod_scheduler_generator extends behat_generator_base +{ /** * Get a list of the entities that Behat can create using the generator step. * @@ -73,5 +73,4 @@ protected function get_student_id(string $idnumber): int { return 0; } } - } diff --git a/tests/generator/lib.php b/tests/generator/lib.php index e1276424..785b1fb6 100644 --- a/tests/generator/lib.php +++ b/tests/generator/lib.php @@ -29,8 +29,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class mod_scheduler_generator extends testing_module_generator { - +class mod_scheduler_generator extends testing_module_generator +{ /** * set default * @@ -46,11 +46,12 @@ private function set_default($record, $property, $value) { /** * Create new scheduler module instance - * @param array|stdClass $record - * @param array $options + * + * @param array|stdClass $record data for module being generated. + * @param null|array $options general options for module. * @return stdClass activity record with extra cmid field */ - public function create_instance($record = null, array $options = null) { + public function create_instance($record = null, ?array $options = null) { global $CFG, $DB; require_once("$CFG->dirroot/mod/scheduler/lib.php"); @@ -63,8 +64,9 @@ public function create_instance($record = null, array $options = null) { if (empty($record->course)) { throw new coding_exception('module generator requires $record->course'); } - self::set_default($record, 'name', get_string('pluginname', 'scheduler').' '.$i); - self::set_default($record, 'intro', 'Test scheduler '.$i); + + self::set_default($record, 'name', get_string('pluginname', 'scheduler') . ' ' . $i); + self::set_default($record, 'intro', 'Test scheduler ' . $i); self::set_default($record, 'introformat', FORMAT_MOODLE); self::set_default($record, 'schedulermode', 'onetime'); self::set_default($record, 'guardtime', 0); @@ -146,5 +148,4 @@ public function create_slot(array $data): void { $slot->save(); } - } diff --git a/tests/model_test.php b/tests/model_test.php index 095166d4..7ea48831 100644 --- a/tests/model_test.php +++ b/tests/model_test.php @@ -26,8 +26,8 @@ defined('MOODLE_INTERNAL') || die(); -use \mod_scheduler\model\scheduler; -use \mod_scheduler\model\appointment_factory; +use mod_scheduler\model\scheduler; +use mod_scheduler\model\appointment_factory; global $CFG; require_once($CFG->dirroot . '/mod/scheduler/locallib.php'); @@ -39,8 +39,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class model_test extends \advanced_testcase { - +final class model_test extends \advanced_testcase +{ /** * @var int Course_modules id used for testing */ @@ -65,24 +65,26 @@ protected function setUp(): void { global $DB, $CFG; $this->resetAfterTest(true); + parent::setUp(); $course = $this->getDataGenerator()->create_course(); - $options = array(); - $options['slottimes'] = array(); - $options['slotstudents'] = array(); + $options = []; + $options['slottimes'] = []; + $options['slotstudents'] = []; for ($c = 0; $c < 4; $c++) { $options['slottimes'][$c] = time() + ($c + 1) * DAYSECS; - $options['slotstudents'][$c] = array($this->getDataGenerator()->create_user()->id); + $options['slotstudents'][$c] = [$this->getDataGenerator()->create_user()->id]; } + $options['slottimes'][4] = time() + 10 * DAYSECS; $options['slottimes'][5] = time() + 11 * DAYSECS; - $options['slotstudents'][5] = array( + $options['slotstudents'][5] = [ + $this->getDataGenerator()->create_user()->id, $this->getDataGenerator()->create_user()->id, - $this->getDataGenerator()->create_user()->id - ); + ]; - $scheduler = $this->getDataGenerator()->create_module('scheduler', array('course' => $course->id), $options); - $coursemodule = $DB->get_record('course_modules', array('id' => $scheduler->cmid)); + $scheduler = $this->getDataGenerator()->create_module('scheduler', ['course' => $course->id], $options); + $coursemodule = $DB->get_record('course_modules', ['id' => $scheduler->cmid]); $this->schedulerid = $scheduler->id; $this->moduleid = $coursemodule->id; @@ -95,15 +97,14 @@ protected function setUp(): void { * * @covers \mod_scheduler\model\scheduler::load_by_coursemodule_id */ - public function test_scheduler() { + public function test_scheduler(): void { global $DB; - $dbdata = $DB->get_record('scheduler', array('id' => $this->schedulerid)); + $dbdata = $DB->get_record('scheduler', ['id' => $this->schedulerid]); $instance = scheduler::load_by_coursemodule_id($this->moduleid); - $this->assertEquals( $dbdata->name, $instance->get_name()); - + $this->assertEquals($dbdata->name, $instance->get_name()); } /** @@ -112,7 +113,7 @@ public function test_scheduler() { * * @covers \mod_scheduler\model\scheduler::load_by_coursemodule_id */ - public function test_appointment() { + public function test_appointment(): void { global $DB; @@ -149,7 +150,5 @@ public function test_appointment() { $this->assertEquals(fullname($user), fullname($appobj->get_student())); $this->assertTrue($appobj->is_attended()); $this->assertEquals(-7, $appobj->grade); - } - } diff --git a/tests/permissions_test.php b/tests/permissions_test.php index 619c75a6..b599ad23 100644 --- a/tests/permissions_test.php +++ b/tests/permissions_test.php @@ -26,9 +26,9 @@ defined('MOODLE_INTERNAL') || die(); -use \mod_scheduler\model\scheduler; -use \mod_scheduler\model\slot; -use \mod_scheduler\permission\scheduler_permissions; +use mod_scheduler\model\scheduler; +use mod_scheduler\model\slot; +use mod_scheduler\permission\scheduler_permissions; global $CFG; require_once($CFG->dirroot . '/mod/scheduler/locallib.php'); @@ -40,8 +40,8 @@ * @copyright 2019 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class permissions_test extends \advanced_testcase { - +final class permissions_test extends \advanced_testcase +{ /** * @var int Course_modules id used for testing */ @@ -106,10 +106,11 @@ protected function setUp(): void { $dg = $this->getDataGenerator(); $this->resetAfterTest(false); + parent::setUp(); $course = $dg->create_course(); - $this->students = array(); + $this->students = []; for ($i = 0; $i < 3; $i++) { $this->students[$i] = $dg->create_user()->id; $dg->enrol_user($this->students[$i], $course->id, 'student'); @@ -129,21 +130,21 @@ protected function setUp(): void { $this->administ = $dg->create_user()->id; $dg->enrol_user($this->administ, $course->id, $adminrole); - $options = array(); + $options = []; $options['slottimes'] = [time() + DAYSECS, time() + 2 * DAYSECS, time() + 3 * DAYSECS]; $options['slotstudents'] = array_values($this->students); $options['slotteachers'] = [$this->edteacher, $this->nonedteacher]; $schedrec = $this->getDataGenerator()->create_module('scheduler', ['course' => $course->id], $options); - $coursemodule = $DB->get_record('course_modules', array('id' => $schedrec->cmid)); + $coursemodule = $DB->get_record('course_modules', ['id' => $schedrec->cmid]); $this->scheduler = scheduler::load_by_coursemodule_id($coursemodule->id); $this->moduleid = $coursemodule->id; $this->courseid = $coursemodule->course; $this->context = $this->scheduler->context; - $slotids = array_keys($DB->get_records('scheduler_slots', array('schedulerid' => $this->scheduler->id), 'starttime ASC')); - $this->slots = array(); - $this->appts = array(); + $slotids = array_keys($DB->get_records('scheduler_slots', ['schedulerid' => $this->scheduler->id], 'starttime ASC')); + $this->slots = []; + $this->appts = []; foreach ($slotids as $key => $id) { $this->slots[$key] = $this->scheduler->get_slot($id); $this->appts[$key] = array_values($this->slots[$key]->get_appointments())[0]; @@ -155,7 +156,7 @@ protected function setUp(): void { * * @coversNothing */ - public function test_teacher_can_see_slot() { + public function test_teacher_can_see_slot(): void { // Editing teacher sees all slots. $p = new scheduler_permissions($this->context, $this->edteacher); @@ -166,7 +167,7 @@ public function test_teacher_can_see_slot() { // Nonediting teacher sees only his own slot. $p = new scheduler_permissions($this->context, $this->nonedteacher); $this->assertFalse($p->teacher_can_see_slot($this->slots[0])); - $this->assertTrue ($p->teacher_can_see_slot($this->slots[1])); + $this->assertTrue($p->teacher_can_see_slot($this->slots[1])); $this->assertFalse($p->teacher_can_see_slot($this->slots[2])); // Adminstrator sees all slots. @@ -180,7 +181,6 @@ public function test_teacher_can_see_slot() { $this->assertFalse($p->teacher_can_see_slot($this->slots[0])); $this->assertFalse($p->teacher_can_see_slot($this->slots[1])); $this->assertFalse($p->teacher_can_see_slot($this->slots[2])); - } /** @@ -188,7 +188,7 @@ public function test_teacher_can_see_slot() { * * @coversNothing */ - public function test_can_edit_slot() { + public function test_can_edit_slot(): void { // Editing teacher can edit all slots. $p = new scheduler_permissions($this->context, $this->edteacher); @@ -199,7 +199,7 @@ public function test_can_edit_slot() { // Nonediting teacher can only edit his own slot. $p = new scheduler_permissions($this->context, $this->nonedteacher); $this->assertFalse($p->can_edit_slot($this->slots[0])); - $this->assertTrue ($p->can_edit_slot($this->slots[1])); + $this->assertTrue($p->can_edit_slot($this->slots[1])); $this->assertFalse($p->can_edit_slot($this->slots[2])); // Adminstrator cannot edit any slots. @@ -213,7 +213,6 @@ public function test_can_edit_slot() { $this->assertFalse($p->can_edit_slot($this->slots[0])); $this->assertFalse($p->can_edit_slot($this->slots[1])); $this->assertFalse($p->can_edit_slot($this->slots[2])); - } /** @@ -221,7 +220,7 @@ public function test_can_edit_slot() { * * @coversNothing */ - public function test_can_edit_own_slots() { + public function test_can_edit_own_slots(): void { // Both teachers can edit their own slots. $p = new scheduler_permissions($this->context, $this->edteacher); @@ -234,7 +233,6 @@ public function test_can_edit_own_slots() { $this->assertFalse($p->can_edit_own_slots()); $p = new scheduler_permissions($this->context, $this->students[1]); $this->assertFalse($p->can_edit_own_slots()); - } /** @@ -242,7 +240,7 @@ public function test_can_edit_own_slots() { * * @coversNothing */ - public function test_can_edit_all_slots() { + public function test_can_edit_all_slots(): void { // Editing teachers can edit all slots. $p = new scheduler_permissions($this->context, $this->edteacher); @@ -255,7 +253,6 @@ public function test_can_edit_all_slots() { $this->assertFalse($p->can_edit_all_slots()); $p = new scheduler_permissions($this->context, $this->students[1]); $this->assertFalse($p->can_edit_all_slots()); - } /** @@ -263,7 +260,7 @@ public function test_can_edit_all_slots() { * * @coversNothing */ - public function test_can_see_all_slots() { + public function test_can_see_all_slots(): void { // Editing teachers can see all slots. $p = new scheduler_permissions($this->context, $this->edteacher); @@ -280,7 +277,6 @@ public function test_can_see_all_slots() { // Students cannot see all slots. $p = new scheduler_permissions($this->context, $this->students[1]); $this->assertFalse($p->can_see_all_slots()); - } /** @@ -288,7 +284,7 @@ public function test_can_see_all_slots() { * * @coversNothing */ - public function test_can_see_appointment() { + public function test_can_see_appointment(): void { // Editing teacher can all appointments. $p = new scheduler_permissions($this->context, $this->edteacher); @@ -299,7 +295,7 @@ public function test_can_see_appointment() { // Nonediting teacher can only see his own appointment. $p = new scheduler_permissions($this->context, $this->nonedteacher); $this->assertFalse($p->can_see_appointment($this->appts[0])); - $this->assertTrue ($p->can_see_appointment($this->appts[1])); + $this->assertTrue($p->can_see_appointment($this->appts[1])); $this->assertFalse($p->can_see_appointment($this->appts[2])); // Administrator can see all appointments. @@ -318,8 +314,5 @@ public function test_can_see_appointment() { $this->assertEquals($expected, $actual, $msg); } } - } - - } diff --git a/tests/privacy_test.php b/tests/privacy_test.php index 520eca12..03f097ac 100644 --- a/tests/privacy_test.php +++ b/tests/privacy_test.php @@ -36,7 +36,7 @@ use core_privacy\local\request\approved_userlist; use core_privacy\local\request\writer; -require_once($CFG->dirroot.'/mod/scheduler/locallib.php'); +require_once($CFG->dirroot . '/mod/scheduler/locallib.php'); /** * Data provider testcase class. @@ -45,8 +45,8 @@ * @copyright 2018 Henning Bostelmann * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class privacy_test extends provider_testcase { - +final class privacy_test extends provider_testcase +{ /** * @var int course_module id used for testing */ @@ -96,6 +96,7 @@ protected function setUp(): void { global $DB, $CFG; $this->resetAfterTest(true); + parent::setUp(); $course = $this->getDataGenerator()->create_course(); $this->courseid = $course->id; @@ -104,32 +105,33 @@ protected function setUp(): void { $this->student2 = $this->getDataGenerator()->create_user(); $this->allstudents = [$this->student1->id, $this->student2->id]; - $options = array(); - $options['slottimes'] = array(); - $options['slotstudents'] = array(); + $options = []; + $options['slottimes'] = []; + $options['slotstudents'] = []; for ($c = 0; $c < 4; $c++) { $options['slottimes'][$c] = time() + ($c + 1) * DAYSECS; $stud = $this->getDataGenerator()->create_user()->id; $this->allstudents[] = $stud; - $options['slotstudents'][$c] = array($stud); + $options['slotstudents'][$c] = [$stud]; } + $options['slottimes'][4] = time() + 10 * DAYSECS; $options['slottimes'][5] = time() + 11 * DAYSECS; - $options['slotstudents'][5] = array( + $options['slotstudents'][5] = [ $this->student1->id, - $this->student2->id - ); + $this->student2->id, + ]; - $scheduler = $this->getDataGenerator()->create_module('scheduler', array('course' => $course->id), $options); - $coursemodule = $DB->get_record('course_modules', array('id' => $scheduler->cmid)); + $scheduler = $this->getDataGenerator()->create_module('scheduler', ['course' => $course->id], $options); + $coursemodule = $DB->get_record('course_modules', ['id' => $scheduler->cmid]); $this->schedulerid = $scheduler->id; $this->moduleid = $coursemodule->id; $this->context = \context_module::instance($scheduler->cmid); - $recs = $DB->get_records('scheduler_slots', array('schedulerid' => $scheduler->id), 'id DESC'); + $recs = $DB->get_records('scheduler_slots', ['schedulerid' => $scheduler->id], 'id DESC'); $this->slotid = array_keys($recs)[0]; - $this->appointmentids = array_keys($DB->get_records('scheduler_appointment', array('slotid' => $this->slotid))); + $this->appointmentids = array_keys($DB->get_records('scheduler_appointment', ['slotid' => $this->slotid])); } /** @@ -147,7 +149,7 @@ private function assert_appointment_status($schedulerid, $studentid, $expected) JOIN {scheduler_appointment} a ON a.slotid = t.id WHERE s.id = :schedulerid AND a.studentid = :studentid"; - $params = array('schedulerid' => $schedulerid, 'studentid' => $studentid); + $params = ['schedulerid' => $schedulerid, 'studentid' => $studentid]; $actual = $DB->record_exists_sql($sql, $params); $this->assertEquals($expected, $actual, "Checking whether student $studentid has appointment in scheduler $schedulerid"); } @@ -157,7 +159,7 @@ private function assert_appointment_status($schedulerid, $studentid, $expected) * * @covers \mod_scheduler\privacy\provider::get_contexts_for_userid */ - public function test_get_contexts_for_userid() { + public function test_get_contexts_for_userid(): void { // Get contexts for the first user. $contextids = provider::get_contexts_for_userid($this->student1->id)->get_contextids(); @@ -169,7 +171,7 @@ public function test_get_contexts_for_userid() { * * @covers \mod_scheduler\privacy\provider::get_users_in_context */ - public function test_get_users_in_context() { + public function test_get_users_in_context(): void { global $DB; $component = 'mod_scheduler'; @@ -191,12 +193,12 @@ public function test_get_users_in_context() { * * @covers \mod_scheduler\privacy\provider::export_user_data */ - public function test_export_teacher_data() { + public function test_export_teacher_data(): void { global $DB; // Export all contexts for the teacher. $contextids = [$this->context->id]; - $teacher = $DB->get_record('user', array('id' => 2)); + $teacher = $DB->get_record('user', ['id' => 2]); $appctx = new approved_contextlist($teacher, 'mod_scheduler', $contextids); provider::export_user_data($appctx); $data = writer::with_context($this->context)->get_data([]); @@ -208,7 +210,7 @@ public function test_export_teacher_data() { * * @covers \mod_scheduler\privacy\provider::export_user_data */ - public function test_export_user_data1() { + public function test_export_user_data1(): void { // Export all contexts for the first user. $contextids = [$this->context->id]; @@ -223,7 +225,7 @@ public function test_export_user_data1() { * * @covers \mod_scheduler\privacy\provider::delete_data_for_all_users_in_context */ - public function test_delete_data_for_all_users_in_context() { + public function test_delete_data_for_all_users_in_context(): void { provider::delete_data_for_all_users_in_context($this->context); foreach ($this->allstudents as $u) { @@ -236,13 +238,12 @@ public function test_delete_data_for_all_users_in_context() { * * @covers \mod_scheduler\privacy\provider::delete_data_for_user */ - public function test_delete_data_for_user() { + public function test_delete_data_for_user(): void { $appctx = new approved_contextlist($this->student1, 'mod_scheduler', [$this->context->id]); provider::delete_data_for_user($appctx); $this->assert_appointment_status($this->schedulerid, $this->student1->id, false); $this->assert_appointment_status($this->schedulerid, $this->student2->id, true); - } /** @@ -250,7 +251,7 @@ public function test_delete_data_for_user() { * * @covers \mod_scheduler\privacy\provider::delete_data_for_users */ - public function test_delete_data_for_users() { + public function test_delete_data_for_users(): void { $component = 'mod_scheduler'; $approveduserids = [$this->student1->id, $this->student2->id]; diff --git a/tests/scheduler_test.php b/tests/scheduler_test.php index 7f191d9a..8cf646e3 100644 --- a/tests/scheduler_test.php +++ b/tests/scheduler_test.php @@ -26,9 +26,9 @@ defined('MOODLE_INTERNAL') || die(); -use \mod_scheduler\model\scheduler; -use \mod_scheduler\model\slot; -use \mod_scheduler\model\appointment; +use mod_scheduler\model\scheduler; +use mod_scheduler\model\slot; +use mod_scheduler\model\appointment; global $CFG; require_once($CFG->dirroot . '/mod/scheduler/locallib.php'); @@ -40,8 +40,8 @@ * @copyright 2011 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class scheduler_test extends \advanced_testcase { - +final class scheduler_test extends \advanced_testcase +{ /** * @var int Course_module id used for testing */ @@ -71,33 +71,35 @@ protected function setUp(): void { global $DB, $CFG; $this->resetAfterTest(true); + parent::setUp(); $course = $this->getDataGenerator()->create_course(); $this->courseid = $course->id; - $options = array(); - $options['slottimes'] = array(); - $options['slotstudents'] = array(); + $options = []; + $options['slottimes'] = []; + $options['slotstudents'] = []; for ($c = 0; $c < 4; $c++) { $options['slottimes'][$c] = time() + ($c + 1) * DAYSECS; - $options['slotstudents'][$c] = array($this->getDataGenerator()->create_user()->id); + $options['slotstudents'][$c] = [$this->getDataGenerator()->create_user()->id]; } + $options['slottimes'][4] = time() + 10 * DAYSECS; $options['slottimes'][5] = time() + 11 * DAYSECS; - $options['slotstudents'][5] = array( + $options['slotstudents'][5] = [ + $this->getDataGenerator()->create_user()->id, $this->getDataGenerator()->create_user()->id, - $this->getDataGenerator()->create_user()->id - ); + ]; - $scheduler = $this->getDataGenerator()->create_module('scheduler', array('course' => $course->id), $options); - $coursemodule = $DB->get_record('course_modules', array('id' => $scheduler->cmid)); + $scheduler = $this->getDataGenerator()->create_module('scheduler', ['course' => $course->id], $options); + $coursemodule = $DB->get_record('course_modules', ['id' => $scheduler->cmid]); $this->schedulerid = $scheduler->id; $this->moduleid = $coursemodule->id; - $recs = $DB->get_records('scheduler_slots', array('schedulerid' => $scheduler->id), 'id DESC'); + $recs = $DB->get_records('scheduler_slots', ['schedulerid' => $scheduler->id], 'id DESC'); $this->slotid = array_keys($recs)[0]; - $this->appointmentids = array_keys($DB->get_records('scheduler_appointment', array('slotid' => $this->slotid))); + $this->appointmentids = array_keys($DB->get_records('scheduler_appointment', ['slotid' => $this->slotid])); } /** @@ -110,6 +112,7 @@ private function create_student($courseid = 0) { if ($courseid == 0) { $courseid = $this->courseid; } + $userid = $this->getDataGenerator()->create_user()->id; $this->getDataGenerator()->enrol_user($userid, $courseid); return $userid; @@ -126,7 +129,7 @@ private function create_student($courseid = 0) { private function assert_record_count($table, $field, $value, $expect) { global $DB; - $act = $DB->count_records($table, array($field => $value)); + $act = $DB->count_records($table, [$field => $value]); $this->assertEquals($expect, $act, "Checking whether table $table has $expect records with $field equal to $value"); } @@ -135,15 +138,14 @@ private function assert_record_count($table, $field, $value, $expect) { * * @covers \mod_scheduler\model\scheduler::load_by_coursemodule_id */ - public function test_scheduler() { + public function test_scheduler(): void { global $DB; - $dbdata = $DB->get_record('scheduler', array('id' => $this->schedulerid)); + $dbdata = $DB->get_record('scheduler', ['id' => $this->schedulerid]); $instance = scheduler::load_by_coursemodule_id($this->moduleid); $this->assertEquals($dbdata->name, $instance->get_name()); - } /** @@ -151,7 +153,7 @@ public function test_scheduler() { * * @covers \mod_scheduler\model\scheduler::load_by_coursemodule_id */ - public function test_load_slots() { + public function test_load_slots(): void { global $DB; $instance = scheduler::load_by_coursemodule_id($this->moduleid); @@ -181,6 +183,7 @@ public function test_load_slots() { } else { $expectedapp = 1; } + $this->assertEquals($expectedapp, $slot->get_appointment_count()); $apps = $slot->get_appointments(); @@ -189,9 +192,9 @@ public function test_load_slots() { foreach ($apps as $app) { $this->assertTrue($app instanceof appointment); } + $cnt++; } - } /** @@ -199,7 +202,7 @@ public function test_load_slots() { * * @covers \mod_scheduler\model\scheduler::load_by_coursemodule_id */ - public function test_add_slot() { + public function test_add_slot(): void { $scheduler = scheduler::load_by_coursemodule_id($this->moduleid); @@ -212,7 +215,6 @@ public function test_add_slot() { $this->assertEquals(7, count($allslots)); $scheduler->save(); - } /** @@ -220,17 +222,17 @@ public function test_add_slot() { * * @covers \mod_scheduler\model\scheduler::load_by_id */ - public function test_delete_scheduler() { + public function test_delete_scheduler(): void { - $options = array(); - $options['slottimes'] = array(); - $options['slotstudents'] = array(); + $options = []; + $options['slottimes'] = []; + $options['slotstudents'] = []; for ($c = 0; $c < 10; $c++) { $options['slottimes'][$c] = time() + ($c + 1) * DAYSECS; - $options['slotstudents'][$c] = array($this->getDataGenerator()->create_user()->id); + $options['slotstudents'][$c] = [$this->getDataGenerator()->create_user()->id]; } - $delrec = $this->getDataGenerator()->create_module('scheduler', array('course' => $this->courseid), $options); + $delrec = $this->getDataGenerator()->create_module('scheduler', ['course' => $this->courseid], $options); $delid = $delrec->id; $delsched = scheduler::load_by_id($delid); @@ -250,7 +252,6 @@ public function test_delete_scheduler() { $this->assert_record_count('scheduler', 'id', $delid, 0); $this->assert_record_count('scheduler_slots', 'schedulerid', $delid, 0); - } /** @@ -262,12 +263,13 @@ public function test_delete_scheduler() { */ private function assert_slot_times($expected, $actual, $options, $message) { $this->assertEquals(count($expected), count($actual), "Slot count - $message"); - $slottimes = array(); + $slottimes = []; foreach ($expected as $e) { $slottimes[] = $options['slottimes'][$e]; } + foreach ($actual as $a) { - $this->assertTrue( in_array($a->starttime, $slottimes), "Slot at {$a->starttime} - $message"); + $this->assertTrue(in_array($a->starttime, $slottimes), "Slot at {$a->starttime} - $message"); } } @@ -282,9 +284,15 @@ private function assert_slot_times($expected, $actual, $options, $message) { * @param unknown $expavailable which slots are expected to be "available" (including already booked ones) * @param unknown $expbookable which slots are expected to be "bookable" */ - private function check_timed_slots($schedulerid, $studentid, $slotoptions, - $expattended, $expupcoming, $expavailable, $expbookable) { - + private function check_timed_slots( + $schedulerid, + $studentid, + $slotoptions, + $expattended, + $expupcoming, + $expavailable, + $expbookable + ) { $sched = scheduler::load_by_id($schedulerid); $attended = $sched->get_attended_slots_for_student($studentid); @@ -298,7 +306,6 @@ private function check_timed_slots($schedulerid, $studentid, $slotoptions, $bookable = $sched->get_slots_available_to_student($studentid, true); $this->assert_slot_times($expbookable, $bookable, $slotoptions, 'Booked slots'); - } /** @@ -306,17 +313,17 @@ private function check_timed_slots($schedulerid, $studentid, $slotoptions, * * @coversNothing */ - public function test_load_slot_timing() { + public function test_load_slot_timing(): void { global $DB; $currentstud = $this->getDataGenerator()->create_user()->id; $otherstud = $this->getDataGenerator()->create_user()->id; - $options = array(); - $options['slottimes'] = array(); - $options['slotstudents'] = array(); - $options['slotattended'] = array(); + $options = []; + $options['slottimes'] = []; + $options['slotstudents'] = []; + $options['slotattended'] = []; // Create slots 0 to 5, n days in the future, booked by the student but not attended. for ($c = 0; $c <= 5; $c++) { @@ -351,45 +358,60 @@ public function test_load_slot_timing() { $options['slottimes'][$c] = time() + ($c - 10) * DAYSECS + 10 * HOURSECS; } - $schedrec = $this->getDataGenerator()->create_module('scheduler', array('course' => $this->courseid), $options); + $schedrec = $this->getDataGenerator()->create_module('scheduler', ['course' => $this->courseid], $options); $schedid = $schedrec->id; $schedrec->guardtime = 0; $DB->update_record('scheduler', $schedrec); - $this->check_timed_slots($schedid, $currentstud, $options, - array(7, 8), - array(0, 1, 2, 3, 4, 5, 6), - array(10, 11, 12, 13, 14), - array(10, 11, 12, 13, 14, 9) ); + $this->check_timed_slots( + $schedid, + $currentstud, + $options, + [7, 8], + [0, 1, 2, 3, 4, 5, 6], + [10, 11, 12, 13, 14], + [10, 11, 12, 13, 14, 9] + ); $schedrec->guardtime = DAYSECS; $DB->update_record('scheduler', $schedrec); - $this->check_timed_slots($schedid, $currentstud, $options, - array(7, 8), - array(0, 1, 2, 3, 4, 5, 6), - array(11, 12, 13, 14), - array(11, 12, 13, 14, 9) ); + $this->check_timed_slots( + $schedid, + $currentstud, + $options, + [7, 8], + [0, 1, 2, 3, 4, 5, 6], + [11, 12, 13, 14], + [11, 12, 13, 14, 9] + ); $schedrec->guardtime = 4 * DAYSECS; $DB->update_record('scheduler', $schedrec); - $this->check_timed_slots($schedid, $currentstud, $options, - array(7, 8), - array(0, 1, 2, 3, 4, 5, 6), - array(14), - array(14, 9) ); + $this->check_timed_slots( + $schedid, + $currentstud, + $options, + [7, 8], + [0, 1, 2, 3, 4, 5, 6], + [14], + [14, 9] + ); $schedrec->guardtime = 20 * DAYSECS; $DB->update_record('scheduler', $schedrec); - $this->check_timed_slots($schedid, $currentstud, $options, - array(7, 8), - array(0, 1, 2, 3, 4, 5, 6), - array(), - array() ); - + $this->check_timed_slots( + $schedid, + $currentstud, + $options, + [7, 8], + [0, 1, 2, 3, 4, 5, 6], + [], + [] + ); } /** @@ -402,22 +424,33 @@ public function test_load_slot_timing() { * * @covers \mod_scheduler\model\scheduler::load_by_id */ - private function assert_bookable_appointments($expectedwithchangeables, $expectedwithoutchangeables, - $schedid, $studentid) { + private function assert_bookable_appointments( + $expectedwithchangeables, + $expectedwithoutchangeables, + $schedid, + $studentid + ) { $scheduler = scheduler::load_by_id($schedid); $actualwithchangeables = $scheduler->count_bookable_appointments($studentid, true); - $this->assertEquals($expectedwithchangeables, $actualwithchangeables, - 'Checking number of bookable appointments (including changeable bookings)'); + $this->assertEquals( + $expectedwithchangeables, + $actualwithchangeables, + 'Checking number of bookable appointments (including changeable bookings)' + ); $actualwithoutchangeables = $scheduler->count_bookable_appointments($studentid, false); - $this->assertEquals($expectedwithoutchangeables, $actualwithoutchangeables, - 'Checking number of bookable appointments (excluding changeable bookings)'); + $this->assertEquals( + $expectedwithoutchangeables, + $actualwithoutchangeables, + 'Checking number of bookable appointments (excluding changeable bookings)' + ); $studs = $scheduler->get_students_for_scheduling(); if ($expectedwithoutchangeables != 0) { $this->assertTrue(is_array($studs), 'Checking that get_students_for_scheduling returns an array'); } + $actualnum = count($studs); $expectednum = ($expectedwithoutchangeables > 0) ? 3 : 2; $this->assertEquals($expectednum, $actualnum, 'Checking number of students available for scheduling'); @@ -439,15 +472,20 @@ private function assert_bookable_appointments($expectedwithchangeables, $expecte * @param array $bookedslots slots to book the student in * @param array $attendedslots slots which the student has attended */ - private function create_data_for_bookable_appointments($schedulermode, $maxbookings, $guardtime, $studentid, - array $bookedslots, array $attendedslots) { - + private function create_data_for_bookable_appointments( + $schedulermode, + $maxbookings, + $guardtime, + $studentid, + array $bookedslots, + array $attendedslots + ) { global $DB; $course = $this->getDataGenerator()->create_course(); $this->getDataGenerator()->enrol_user($studentid, $course->id); - $options['slottimes'] = array(); + $options['slottimes'] = []; for ($c = 0; $c < 10; $c++) { $options['slottimes'][$c] = time() + $c * DAYSECS + HOURSECS; if (in_array($c, $bookedslots) || in_array($c, $attendedslots)) { @@ -455,7 +493,7 @@ private function create_data_for_bookable_appointments($schedulermode, $maxbooki } } - $schedrec = $this->getDataGenerator()->create_module('scheduler', array('course' => $course->id), $options); + $schedrec = $this->getDataGenerator()->create_module('scheduler', ['course' => $course->id], $options); $scheduler = scheduler::load_by_id($schedrec->id); @@ -464,11 +502,11 @@ private function create_data_for_bookable_appointments($schedulermode, $maxbooki $scheduler->guardtime = $guardtime; $scheduler->save(); - $slotrecs = $DB->get_records('scheduler_slots', array('schedulerid' => $scheduler->id), 'starttime ASC'); + $slotrecs = $DB->get_records('scheduler_slots', ['schedulerid' => $scheduler->id], 'starttime ASC'); $slotrecs = array_values($slotrecs); foreach ($attendedslots as $id) { - $DB->set_field('scheduler_appointment', 'attended', 1, array('slotid' => $slotrecs[$id]->id)); + $DB->set_field('scheduler_appointment', 'attended', 1, ['slotid' => $slotrecs[$id]->id]); } for ($i = 0; $i < 2; $i++) { @@ -483,50 +521,48 @@ private function create_data_for_bookable_appointments($schedulermode, $maxbooki * * @coversNothing */ - public function test_bookable_appointments() { + public function test_bookable_appointments(): void { $studid = $this->create_student(); - $sid = $this->create_data_for_bookable_appointments('oneonly', 1, 0, $studid, array(), array()); + $sid = $this->create_data_for_bookable_appointments('oneonly', 1, 0, $studid, [], []); $this->assert_bookable_appointments(1, 1, $sid, $studid); - $sid = $this->create_data_for_bookable_appointments('oneonly', 1, 0, $studid, array(5), array()); + $sid = $this->create_data_for_bookable_appointments('oneonly', 1, 0, $studid, [5], []); $this->assert_bookable_appointments(1, 0, $sid, $studid); - $sid = $this->create_data_for_bookable_appointments('oneonly', 1, 0, $studid, array(5, 6, 7), array()); + $sid = $this->create_data_for_bookable_appointments('oneonly', 1, 0, $studid, [5, 6, 7], []); $this->assert_bookable_appointments(1, 0, $sid, $studid); - $sid = $this->create_data_for_bookable_appointments('oneonly', 1, 0, $studid, array(5, 6), array(8)); + $sid = $this->create_data_for_bookable_appointments('oneonly', 1, 0, $studid, [5, 6], [8]); $this->assert_bookable_appointments(0, 0, $sid, $studid); // One booking inside guard time, cannot be rebooked. - $sid = $this->create_data_for_bookable_appointments('oneonly', 1, 5 * DAYSECS, $studid, array(1), array()); + $sid = $this->create_data_for_bookable_appointments('oneonly', 1, 5 * DAYSECS, $studid, [1], []); $this->assert_bookable_appointments(0, 0, $sid, $studid); // Five bookings allowed, three booked, one of which attended. - $sid = $this->create_data_for_bookable_appointments('oneonly', 5, 0, $studid, array(2, 3), array(4)); + $sid = $this->create_data_for_bookable_appointments('oneonly', 5, 0, $studid, [2, 3], [4]); $this->assert_bookable_appointments(4, 2, $sid, $studid); // Five bookings allowed, three booked, one of which inside guard time. - $sid = $this->create_data_for_bookable_appointments('oneonly', 5, 5 * DAYSECS, $studid, array(2, 7, 8), array()); + $sid = $this->create_data_for_bookable_appointments('oneonly', 5, 5 * DAYSECS, $studid, [2, 7, 8], []); $this->assert_bookable_appointments(4, 2, $sid, $studid); // Five bookings allowed, four booked, of which two inside guard time (one attended), two outside guard time (one attended). - $sid = $this->create_data_for_bookable_appointments('oneonly', 5, 5 * DAYSECS, $studid, array(2, 7), array(1, 8)); + $sid = $this->create_data_for_bookable_appointments('oneonly', 5, 5 * DAYSECS, $studid, [2, 7], [1, 8]); $this->assert_bookable_appointments(2, 1, $sid, $studid); // One booking allowed at a time. Two attended already present (one inside GT, one outside GT). - $sid = $this->create_data_for_bookable_appointments('onetime', 1, 5 * DAYSECS, $studid, array(), array(3, 7)); + $sid = $this->create_data_for_bookable_appointments('onetime', 1, 5 * DAYSECS, $studid, [], [3, 7]); $this->assert_bookable_appointments(1, 1, $sid, $studid); // One booking allowed at a time. One booked outside GT. - $sid = $this->create_data_for_bookable_appointments('onetime', 1, 5 * DAYSECS, $studid, array(7), array()); + $sid = $this->create_data_for_bookable_appointments('onetime', 1, 5 * DAYSECS, $studid, [7], []); $this->assert_bookable_appointments(1, 0, $sid, $studid); // One booking allowed at a time. One booked inside GT. - $sid = $this->create_data_for_bookable_appointments('onetime', 1, 5 * DAYSECS, $studid, array(2), array()); + $sid = $this->create_data_for_bookable_appointments('onetime', 1, 5 * DAYSECS, $studid, [2], []); $this->assert_bookable_appointments(0, 0, $sid, $studid); - } - } diff --git a/tests/slot_test.php b/tests/slot_test.php index 9f6f784a..36e73796 100644 --- a/tests/slot_test.php +++ b/tests/slot_test.php @@ -26,8 +26,8 @@ defined('MOODLE_INTERNAL') || die(); -use \mod_scheduler\model\scheduler; -use \mod_scheduler\model\slot; +use mod_scheduler\model\scheduler; +use mod_scheduler\model\slot; global $CFG; require_once($CFG->dirroot . '/mod/scheduler/locallib.php'); @@ -39,8 +39,8 @@ * @copyright 2014 Henning Bostelmann and others (see README.txt) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class slot_test extends \advanced_testcase { - +final class slot_test extends \advanced_testcase +{ /** * @var int Course_modules id used for testing */ @@ -80,29 +80,30 @@ protected function setUp(): void { global $DB, $CFG; $this->resetAfterTest(true); + parent::setUp(); $course = $this->getDataGenerator()->create_course(); - $this->students = array(); + $this->students = []; for ($i = 0; $i < 3; $i++) { $this->students[$i] = $this->getDataGenerator()->create_user()->id; } - $options = array(); - $options['slottimes'] = array(); - $options['slotstudents'] = array(); + $options = []; + $options['slottimes'] = []; + $options['slotstudents'] = []; $options['slottimes'][0] = time() + DAYSECS; $options['slotstudents'][0] = $this->students; - $scheduler = $this->getDataGenerator()->create_module('scheduler', array('course' => $course->id), $options); - $coursemodule = $DB->get_record('course_modules', array('id' => $scheduler->cmid)); + $scheduler = $this->getDataGenerator()->create_module('scheduler', ['course' => $course->id], $options); + $coursemodule = $DB->get_record('course_modules', ['id' => $scheduler->cmid]); $this->schedulerid = $scheduler->id; $this->moduleid = $coursemodule->id; $this->courseid = $coursemodule->course; $this->teacherid = 2; // Admin user. - $this->slotid = $DB->get_field('scheduler_slots', 'id', array('schedulerid' => $scheduler->id), MUST_EXIST); - $this->appointmentids = array_keys($DB->get_records('scheduler_appointment', array('slotid' => $this->slotid))); + $this->slotid = $DB->get_field('scheduler_slots', 'id', ['schedulerid' => $scheduler->id], MUST_EXIST); + $this->appointmentids = array_keys($DB->get_records('scheduler_appointment', ['slotid' => $this->slotid])); } /** @@ -115,7 +116,7 @@ protected function setUp(): void { private function assert_record_present($table, $id, $msg = "") { global $DB; - $ex = $DB->record_exists($table, array('id' => $id)); + $ex = $DB->record_exists($table, ['id' => $id]); $this->assertTrue($ex, "Checking whether record $id is present in table $table: $msg"); } @@ -129,7 +130,7 @@ private function assert_record_present($table, $id, $msg = "") { private function assert_record_absent($table, $id, $msg = "") { global $DB; - $ex = $DB->record_exists($table, array('id' => $id)); + $ex = $DB->record_exists($table, ['id' => $id]); $this->assertFalse($ex, "Checking whether record $id is absent in table $table: $msg"); } @@ -138,7 +139,7 @@ private function assert_record_absent($table, $id, $msg = "") { * * @covers \mod_scheduler\model\scheduler::load_by_id */ - public function test_create() { + public function test_create(): void { global $DB; @@ -159,9 +160,8 @@ public function test_create() { $newid = $slot->get_id(); $this->assertNotEquals(0, $newid, "Checking slot id after creation"); - $newcnt = $DB->count_records('scheduler_appointment', array('slotid' => $newid)); + $newcnt = $DB->count_records('scheduler_appointment', ['slotid' => $newid]); $this->assertEquals(2, $newcnt, "Counting number of appointments after addition"); - } @@ -170,7 +170,7 @@ public function test_create() { * * @covers \mod_scheduler\model\scheduler::load_by_id */ - public function test_delete() { + public function test_delete(): void { $scheduler = scheduler::load_by_id($this->schedulerid); @@ -192,7 +192,6 @@ public function test_delete() { foreach ($this->students as $student) { $this->assert_event_absent($student, $start, ""); } - } /** @@ -200,14 +199,14 @@ public function test_delete() { * * @covers \mod_scheduler\model\scheduler::load_by_id */ - public function test_add_appointment() { + public function test_add_appointment(): void { global $DB; $scheduler = scheduler::load_by_id($this->schedulerid); $slot = slot::load_by_id($this->slotid, $scheduler); - $oldcnt = $DB->count_records('scheduler_appointment', array('slotid' => $slot->get_id())); + $oldcnt = $DB->count_records('scheduler_appointment', ['slotid' => $slot->get_id()]); $this->assertEquals(3, $oldcnt, "Counting number of appointments before addition"); $newapp = $slot->create_appointment(); @@ -215,9 +214,8 @@ public function test_add_appointment() { $slot->save(); - $newcnt = $DB->count_records('scheduler_appointment', array('slotid' => $slot->get_id())); + $newcnt = $DB->count_records('scheduler_appointment', ['slotid' => $slot->get_id()]); $this->assertEquals(4, $newcnt, "Counting number of appointments after addition"); - } /** @@ -225,7 +223,7 @@ public function test_add_appointment() { * * @covers \mod_scheduler\model\scheduler::load_by_id */ - public function test_remove_appointment() { + public function test_remove_appointment(): void { global $DB; @@ -249,7 +247,7 @@ public function test_remove_appointment() { * * @covers \mod_scheduler\model\scheduler::load_by_id */ - public function test_calendar_events() { + public function test_calendar_events(): void { global $DB; $scheduler = scheduler::load_by_id($this->schedulerid); @@ -271,6 +269,7 @@ public function test_calendar_events() { $this->assert_event_absent($student, $oldstart); $this->assert_event_exists($student, $newstart, "Meeting with your Teacher"); } + $this->assert_event_absent($this->teacherid, $oldstart); $this->assert_event_exists($this->teacherid, $newstart, "Meeting with your Students"); @@ -284,15 +283,15 @@ public function test_calendar_events() { $this->assert_event_exists($this->teacherid, $newstart, "Meeting with your Students"); // Delete all appointments. - $DB->delete_records('scheduler_appointment', array('slotid' => $this->slotid)); + $DB->delete_records('scheduler_appointment', ['slotid' => $this->slotid]); $slot = slot::load_by_id($this->slotid, $scheduler); $slot->save(); foreach ($this->students as $student) { $this->assert_event_absent($student, $newstart); } - $this->assert_event_absent($this->teacherid, $newstart); + $this->assert_event_absent($this->teacherid, $newstart); } /** diff --git a/version.php b/version.php index 4952256a..d8c555c6 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,8 @@ */ $plugin->component = 'mod_scheduler'; // Full name of the plugin (used for diagnostics). -$plugin->version = 2024080103; // The current module version (Date: YYYYMMDDXX). -$plugin->release = '4.x dev'; // Human-friendly version name. -$plugin->requires = 2023100905; // Requires Moodle 4.3. -$plugin->maturity = MATURITY_ALPHA; // Development release - not for production use. +$plugin->version = 2026080400; // The current module version (Date: YYYYMMDDXX). +$plugin->release = 'v5.2-r1'; +$plugin->requires = 2024100712; // Requires Moodle 4.5. +$plugin->supported = [500, 502]; +$plugin->maturity = MATURITY_STABLE; diff --git a/view.php b/view.php index 1edfed23..e2d6b0fa 100644 --- a/view.php +++ b/view.php @@ -22,12 +22,12 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -use \mod_scheduler\model\scheduler; +use mod_scheduler\model\scheduler; require_once(dirname(__FILE__) . '/../../config.php'); -require_once($CFG->dirroot.'/mod/scheduler/lib.php'); -require_once($CFG->dirroot.'/mod/scheduler/locallib.php'); -require_once($CFG->dirroot.'/mod/scheduler/renderable.php'); +require_once($CFG->dirroot . '/mod/scheduler/lib.php'); +require_once($CFG->dirroot . '/mod/scheduler/locallib.php'); +require_once($CFG->dirroot . '/mod/scheduler/renderable.php'); // Read common request parameters. $id = optional_param('id', '', PARAM_INT); // Course Module ID - if it's not specified, must specify 'a', see below. @@ -43,7 +43,8 @@ $scheduler = scheduler::load_by_id($a); $cm = $scheduler->get_cm(); } -$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + +$course = $DB->get_record('course', ['id' => $cm->course], '*', MUST_EXIST); require_login($course->id, true, $cm); @@ -51,7 +52,7 @@ $permissions = new \mod_scheduler\permission\scheduler_permissions($context, $USER->id); // Initialize $PAGE, compute blocks. -$PAGE->set_url('/mod/scheduler/view.php', array('id' => $cm->id)); +$PAGE->set_url('/mod/scheduler/view.php', ['id' => $cm->id]); $output = $PAGE->get_renderer('mod_scheduler'); @@ -60,6 +61,7 @@ } else { $defaultsubpage = 'allappointments'; } + $subpage = optional_param('subpage', $defaultsubpage, PARAM_ALPHA); @@ -77,21 +79,19 @@ if ($isteacher) { // Teacher side. if ($action == 'viewstatistics') { - include($CFG->dirroot.'/mod/scheduler/viewstatistics.php'); + include($CFG->dirroot . '/mod/scheduler/viewstatistics.php'); } else if ($action == 'viewstudent') { - include($CFG->dirroot.'/mod/scheduler/viewstudent.php'); + include($CFG->dirroot . '/mod/scheduler/viewstudent.php'); } else if ($action == 'export') { - include($CFG->dirroot.'/mod/scheduler/export.php'); + include($CFG->dirroot . '/mod/scheduler/export.php'); } else if ($action == 'datelist') { - include($CFG->dirroot.'/mod/scheduler/datelist.php'); + include($CFG->dirroot . '/mod/scheduler/datelist.php'); } else { - include($CFG->dirroot.'/mod/scheduler/teacherview.php'); + include($CFG->dirroot . '/mod/scheduler/teacherview.php'); } - } else if ($isstudent) { // Student side. - include($CFG->dirroot.'/mod/scheduler/studentview.php'); - + include($CFG->dirroot . '/mod/scheduler/studentview.php'); } else { // For guests. echo $OUTPUT->header(); diff --git a/viewstatistics.php b/viewstatistics.php index 4379bfb4..6fb8165f 100644 --- a/viewstatistics.php +++ b/viewstatistics.php @@ -35,8 +35,8 @@ function byname($a, $b) { return strcasecmp($a[0], $b[0]); } -$taburl = new moodle_url('/mod/scheduler/view.php', array('id' => $scheduler->cmid, - 'what' => 'viewstatistics', 'subpage' => $subpage)); +$taburl = new moodle_url('/mod/scheduler/view.php', ['id' => $scheduler->cmid, + 'what' => 'viewstatistics', 'subpage' => $subpage, ]); $PAGE->set_url($taburl); echo $OUTPUT->header(); @@ -55,7 +55,7 @@ function byname($a, $b) { // Display correct type of statistics by request. -$usergroups = ($currentgroupid > 0) ? array($currentgroupid) : ''; +$usergroups = ($currentgroupid > 0) ? [$currentgroupid] : ''; $attendees = $scheduler->get_available_students($usergroups); switch ($subpage) { @@ -71,7 +71,7 @@ function byname($a, $b) { s.schedulerid = ? AND a.attended = 1 '; - $attended = $DB->count_records_sql($sql, array($scheduler->id)); + $attended = $DB->count_records_sql($sql, [$scheduler->id]); $sql = ' SELECT @@ -84,7 +84,7 @@ function byname($a, $b) { s.schedulerid = ? AND a.attended = 0 '; - $registered = $DB->count_records_sql($sql, array($scheduler->id)); + $registered = $DB->count_records_sql($sql, [$scheduler->id]); $sql = ' SELECT @@ -100,7 +100,7 @@ function byname($a, $b) { s.teacherid = ? AND a.attended IS NULL '; - $freeowned = $DB->count_records_sql($sql, array($scheduler->id, $USER->id)); + $freeowned = $DB->count_records_sql($sql, [$scheduler->id, $USER->id]); $sql = ' SELECT @@ -116,22 +116,22 @@ function byname($a, $b) { s.teacherid != ? AND a.attended IS NULL '; - $freenotowned = $DB->count_records_sql($sql, array($scheduler->id, $USER->id)); + $freenotowned = $DB->count_records_sql($sql, [$scheduler->id, $USER->id]); $allattendees = ($attendees) ? count($attendees) : 0; - $str = '

'.get_string('attendable', 'scheduler').'

'; - $str .= ''.get_string('attendablelbl', 'scheduler').': ' . $allattendees . '
'; - $str .= '

'.get_string('attended', 'scheduler').'

'; - $str .= ''.get_string('attendedlbl', 'scheduler').': ' . $attended . '

'; - $str .= '

'.get_string('unattended', 'scheduler').'

'; - $str .= ''.get_string('registeredlbl', 'scheduler').': ' . $registered . '
'; - $str .= ''.get_string('unregisteredlbl', 'scheduler').': ' . + $str = '

' . get_string('attendable', 'scheduler') . '

'; + $str .= '' . get_string('attendablelbl', 'scheduler') . ': ' . $allattendees . '
'; + $str .= '

' . get_string('attended', 'scheduler') . '

'; + $str .= '' . get_string('attendedlbl', 'scheduler') . ': ' . $attended . '

'; + $str .= '

' . get_string('unattended', 'scheduler') . '

'; + $str .= '' . get_string('registeredlbl', 'scheduler') . ': ' . $registered . '
'; + $str .= '' . get_string('unregisteredlbl', 'scheduler') . ': ' . ($allattendees - $registered - $attended) . '
'; - $str .= '

'.get_string('availableslots', 'scheduler').'

'; - $str .= ''.get_string('availableslotsowned', 'scheduler').': ' . $freeowned . '
'; - $str .= ''.get_string('availableslotsnotowned', 'scheduler').': ' . $freenotowned . '
'; - $str .= ''.get_string('availableslotsall', 'scheduler').': ' . ($freeowned + $freenotowned) . '
'; + $str .= '

' . get_string('availableslots', 'scheduler') . '

'; + $str .= '' . get_string('availableslotsowned', 'scheduler') . ': ' . $freeowned . '
'; + $str .= '' . get_string('availableslotsnotowned', 'scheduler') . ': ' . $freenotowned . '
'; + $str .= '' . get_string('availableslotsall', 'scheduler') . ': ' . ($freeowned + $freenotowned) . '
'; echo $OUTPUT->box($str); @@ -141,10 +141,10 @@ function byname($a, $b) { if (!empty($attendees)) { $table = new html_table(); - $table->head = array (get_string('student', 'scheduler'), get_string('duration', 'scheduler')); - $table->align = array ('LEFT', 'CENTER'); + $table->head = [get_string('student', 'scheduler'), get_string('duration', 'scheduler')]; + $table->align = ['LEFT', 'CENTER']; $table->width = '70%'; - $table->data = array(); + $table->data = []; $sql = ' SELECT a.studentid, @@ -159,14 +159,16 @@ function byname($a, $b) { GROUP BY a.studentid '; - if ($statrecords = $DB->get_records_sql($sql, array($scheduler->id))) { + if ($statrecords = $DB->get_records_sql($sql, [$scheduler->id])) { foreach ($statrecords as $arecord) { if (array_key_exists($arecord->studentid, $attendees)) { - $table->data[] = array (fullname($attendees[$arecord->studentid]), $arecord->totaltime); + $table->data[] = [fullname($attendees[$arecord->studentid]), $arecord->totaltime]; } } + uasort($table->data, 'byname'); } + echo html_writer::table($table); } else { echo $OUTPUT->box(get_string('nostudents', 'scheduler'), 'center', '70%'); @@ -182,21 +184,23 @@ function byname($a, $b) { WHERE s.schedulerid = :sid AND a.studentid IS NOT NULL"; - $params = array('sid' => $scheduler->id); + $params = ['sid' => $scheduler->id]; if ($currentgroupid > 0) { $sql .= " AND EXISTS (SELECT 1 FROM {groups_members} gm WHERE gm.userid = a.studentid AND gm.groupid = :gid)"; $params['gid'] = $currentgroupid; } + $sql .= " GROUP BY s.teacherid"; if ($statrecords = $DB->get_records_sql($sql, $params)) { $table = new html_table(); $table->width = '70%'; - $table->head = array (s($scheduler->get_teacher_name()), get_string('cumulatedduration', 'scheduler')); - $table->align = array ('LEFT', 'CENTER'); + $table->head = [s($scheduler->get_teacher_name()), get_string('cumulatedduration', 'scheduler')]; + $table->align = ['LEFT', 'CENTER']; foreach ($statrecords as $arecord) { - $ateacher = $DB->get_record('user', array('id' => $arecord->teacherid)); - $table->data[] = array (fullname($ateacher), $arecord->totaltime); + $ateacher = $DB->get_record('user', ['id' => $arecord->teacherid]); + $table->data[] = [fullname($ateacher), $arecord->totaltime]; } + uasort($table->data, 'byname'); echo html_writer::table($table); } @@ -217,29 +221,32 @@ function byname($a, $b) { WHERE a.studentid IS NOT NULL AND schedulerid = :sid'; - $params = array('sid' => $scheduler->id); + $params = ['sid' => $scheduler->id]; if ($currentgroupid > 0) { $sql .= " AND EXISTS (SELECT 1 FROM {groups_members} gm WHERE gm.userid = a.studentid AND gm.groupid = :gid)"; $params['gid'] = $currentgroupid; } + $sql .= " GROUP BY s.starttime ORDER BY groupsize DESC"; if ($groupslots = $DB->get_records_sql($sql, $params)) { $table = new html_table(); - $table->head = array (get_string('duration', 'scheduler'), get_string('appointments', 'scheduler')); - $table->align = array ('LEFT', 'CENTER'); + $table->head = [get_string('duration', 'scheduler'), get_string('appointments', 'scheduler')]; + $table->align = ['LEFT', 'CENTER']; $table->width = '70%'; - $durationcount = array(); + $durationcount = []; foreach ($groupslots as $slot) { if (array_key_exists($slot->duration, $durationcount)) { - $durationcount[$slot->duration] ++; + $durationcount[$slot->duration]++; } else { $durationcount[$slot->duration] = 1; } } + foreach ($durationcount as $key => $duration) { - $table->data[] = array ($key, $duration); + $table->data[] = [$key, $duration]; } + echo html_writer::table($table); } break; @@ -259,37 +266,42 @@ function byname($a, $b) { WHERE a.studentid IS NOT NULL AND s.schedulerid = :sid"; - $params = array('sid' => $scheduler->id); + $params = ['sid' => $scheduler->id]; if ($currentgroupid > 0) { $sql .= " AND EXISTS (SELECT 1 FROM {groups_members} gm WHERE gm.userid = s.teacherid AND gm.groupid = :gid)"; $params['gid'] = $currentgroupid; } + $sql .= " GROUP BY s.starttime ORDER BY groupsize DESC"; if ($groupslots = $DB->get_records_sql($sql, $params)) { $table = new html_table(); - $table->head = array (get_string('groupsize', 'scheduler'), get_string('occurrences', 'scheduler'), - get_string('cumulatedduration', 'scheduler')); - $table->align = array ('LEFT', 'CENTER', 'CENTER'); + $table->head = [get_string('groupsize', 'scheduler'), get_string('occurrences', 'scheduler'), + get_string('cumulatedduration', 'scheduler'), ]; + $table->align = ['LEFT', 'CENTER', 'CENTER']; $table->width = '70%'; - $grouprows = array(); + $grouprows = []; foreach ($groupslots as $agroup) { if (!array_key_exists($agroup->groupsize, $grouprows)) { $grouprows[$agroup->groupsize] = new stdClass(); $grouprows[$agroup->groupsize]->occurrences = 0; $grouprows[$agroup->groupsize]->duration = 0; } + $grouprows[$agroup->groupsize]->occurrences++; $grouprows[$agroup->groupsize]->duration += $agroup->duration; } + foreach (array_keys($grouprows) as $agroupsize) { - $table->data[] = array ($agroupsize, $grouprows[$agroupsize]->occurrences, $grouprows[$agroupsize]->duration); + $table->data[] = [$agroupsize, $grouprows[$agroupsize]->occurrences, $grouprows[$agroupsize]->duration]; } + echo html_writer::table($table); } } + echo '
'; -echo $OUTPUT->continue_button("$CFG->wwwroot/mod/scheduler/view.php?id=".$cm->id); +echo $OUTPUT->continue_button("$CFG->wwwroot/mod/scheduler/view.php?id=" . $cm->id); // Finish the page. echo $OUTPUT->footer($course); exit; diff --git a/viewstudent.php b/viewstudent.php index 23d57e28..90f98eeb 100644 --- a/viewstudent.php +++ b/viewstudent.php @@ -24,41 +24,42 @@ defined('MOODLE_INTERNAL') || die(); -require_once($CFG->dirroot.'/mod/scheduler/locallib.php'); +require_once($CFG->dirroot . '/mod/scheduler/locallib.php'); $appointmentid = required_param('appointmentid', PARAM_INT); -list($slot, $appointment) = $scheduler->get_slot_appointment($appointmentid); +[$slot, $appointment] = $scheduler->get_slot_appointment($appointmentid); $studentid = $appointment->studentid; $permissions->ensure($permissions->can_see_appointment($appointment)); -$urlparas = array('what' => 'viewstudent', +$urlparas = ['what' => 'viewstudent', 'id' => $scheduler->cmid, 'appointmentid' => $appointmentid, - 'course' => $scheduler->courseid); + 'course' => $scheduler->courseid, ]; $taburl = new moodle_url('/mod/scheduler/view.php', $urlparas); $PAGE->set_url($taburl); $appts = $scheduler->get_appointments_for_student($studentid); -$pages = array('thisappointment'); +$pages = ['thisappointment']; if ($slot->get_appointment_count() > 1) { $pages[] = 'otherstudents'; } + if (count($appts) > 1) { $pages[] = 'otherappointments'; } -if (!in_array($subpage, $pages) ) { +if (!in_array($subpage, $pages)) { $subpage = 'thisappointment'; } // Process edit form before page output starts. if ($subpage == 'thisappointment') { - require_once($CFG->dirroot.'/mod/scheduler/appointmentforms.php'); + require_once($CFG->dirroot . '/mod/scheduler/appointmentforms.php'); - $actionurl = new moodle_url($taburl, array('page' => 'thisappointment')); - $returnurl = new moodle_url($taburl, array('page' => 'thisappointment')); + $actionurl = new moodle_url($taburl, ['page' => 'thisappointment']); + $returnurl = new moodle_url($taburl, ['page' => 'thisappointment']); $distribute = ($slot->get_appointment_count() > 1); $gradeedit = $permissions->can_edit_grade($appointment); @@ -77,17 +78,18 @@ // Print user summary. -scheduler_print_user($DB->get_record('user', array('id' => $appointment->studentid)), $course); +scheduler_print_user($DB->get_record('user', ['id' => $appointment->studentid]), $course); // Print tabs. -$tabrows = array(); -$row = array(); +$tabrows = []; +$row = []; if (count($pages) > 1) { foreach ($pages as $tabpage) { - $tabname = get_string('tab-'.$tabpage, 'scheduler'); - $row[] = new tabobject($tabpage, new moodle_url($taburl, array('subpage' => $tabpage)), $tabname); + $tabname = get_string('tab-' . $tabpage, 'scheduler'); + $row[] = new tabobject($tabpage, new moodle_url($taburl, ['subpage' => $tabpage]), $tabname); } + $tabrows[] = $row; print_tabs($tabrows, $subpage); } @@ -95,7 +97,6 @@ $totalgradeinfo = new scheduler_totalgrade_info($scheduler, $scheduler->get_gradebook_info($appointment->studentid)); if ($subpage == 'thisappointment') { - $ai = scheduler_appointment_info::make_for_teacher($slot, $appointment); echo $output->render($ai); @@ -104,11 +105,10 @@ if ($scheduler->uses_grades()) { echo $output->render($totalgradeinfo); } - } else if ($subpage == 'otherappointments') { // Print table of other appointments of the same student. - $studenturl = new moodle_url($taburl, array('page' => 'thisappointment')); + $studenturl = new moodle_url($taburl, ['page' => 'thisappointment']); $table = new scheduler_slot_table($scheduler, true, $studenturl); $table->showattended = true; $table->showteachernotes = true; @@ -126,14 +126,13 @@ $totalgradeinfo->totalgrade = $scheduler->get_user_grade($appointment->studentid); echo $output->render($totalgradeinfo); } - } else if ($subpage == 'otherstudents') { // Print table of other students in the same slot. $ai = scheduler_appointment_info::make_from_slot($slot, false); echo $output->render($ai); - $studenturl = new moodle_url($taburl, array('page' => 'thisappointment')); + $studenturl = new moodle_url($taburl, ['page' => 'thisappointment']); $table = new scheduler_slot_table($scheduler, true, $studenturl); $table->showattended = true; $table->showslot = false; @@ -148,6 +147,6 @@ echo $output->render($table); } -echo $output->continue_button(new moodle_url('/mod/scheduler/view.php', array('id' => $scheduler->cmid))); +echo $output->continue_button(new moodle_url('/mod/scheduler/view.php', ['id' => $scheduler->cmid])); echo $output->footer($course); exit;