diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 228e62b..ce7f2b3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -9,16 +9,13 @@ jobs:
matrix:
# Note: Workflow block has SQL that only works in Postgres.
include:
- - php: '7.4'
- moodle-branch: 'master'
- database: 'pgsql'
- - php: '7.4'
- moodle-branch: 'MOODLE_311_STABLE'
- database: 'pgsql'
+ - { php: '8.2', moodle-branch: MOODLE_405_STABLE, database: pgsql }
+ - { php: '8.3', moodle-branch: MOODLE_500_STABLE, database: pgsql }
+ - { php: '8.3', moodle-branch: main, database: pgsql }
services:
postgres:
- image: postgres
+ image: postgres:15
env:
POSTGRES_USER: 'postgres'
POSTGRES_HOST_AUTH_METHOD: 'trust'
@@ -32,7 +29,7 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
path: plugin
@@ -45,16 +42,17 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
- extensions: mbstring, pgsql, mysqli
+ 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 ^3
- # Add dirs to $PATH
+ composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^4
echo $(cd ci/bin; pwd) >> $GITHUB_PATH
echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH
- # PHPUnit depends on en_AU.UTF-8 locale
sudo locale-gen en_AU.UTF-8
+ echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV
- name: Install Moodle
run: moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1
@@ -67,8 +65,9 @@ jobs:
run: moodle-plugin-ci phplint
- name: phpcpd
+ continue-on-error: true
if: ${{ always() }}
- run: moodle-plugin-ci phpcpd || true
+ run: moodle-plugin-ci phpcpd
- name: phpmd
if: ${{ always() }}
diff --git a/addworkflow.php b/addworkflow.php
index def7286..049a79e 100644
--- a/addworkflow.php
+++ b/addworkflow.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
diff --git a/ajax.php b/ajax.php
deleted file mode 100644
index 58d357d..0000000
--- a/ajax.php
+++ /dev/null
@@ -1,108 +0,0 @@
-.
-
-/**
- * Server-side script for all ajax request for workflow API
- *
- * @package block_workflow
- * @copyright 2011 Lancaster University Network Services Limited
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-define('AJAX_SCRIPT', true);
-
-require_once(dirname(__FILE__) . '/../../config.php');
-require_once(dirname(__FILE__) . '/locallib.php');
-require_once($CFG->dirroot . '/lib/form/editor.php');
-
-// Require the session key.
-require_sesskey();
-
-$action = required_param('action', PARAM_ACTION);
-$stateid = required_param('stateid', PARAM_INT);
-
-$state = new block_workflow_step_state($stateid);
-list($context, $course, $cm) = get_context_info_array($state->contextid);
-
-// Require login.
-require_login($course, false, $cm);
-
-$PAGE->set_context($context);
-$PAGE->set_url('/blocks/workflow/ajax.php', array('stateid' => $stateid, 'action' => $action));
-
-// Send headers.
-echo $OUTPUT->header();
-
-$outcome = new stdClass;
-$outcome->success = true;
-$outcome->response = new stdClass;
-$outcome->error = '';
-
-if (!block_workflow_can_make_changes($state)) {
- // Check that the user is allowed to work on this step.
- throw new block_workflow_ajax_exception(get_string('notallowedtodothisstep', 'block_workflow'));
-}
-
-switch ($action) {
- case 'getcomment':
- $outcome->response->comment = $state->comment;
- break;
- case 'savecomment':
- $text = required_param('text', PARAM_CLEANHTML);
- $format = required_param('format', PARAM_INT);
- $state->update_comment($text, $format);
- $outcome->response->blockcomments = shorten_text($text, BLOCK_WORKFLOW_MAX_COMMENT_LENGTH);
- break;
- case 'finishstep':
- $text = required_param('text', PARAM_CLEANHTML);
- $format = required_param('format', PARAM_INT);
- $renderer = $PAGE->get_renderer('block_workflow');
-
- // Retrieve the next step.
- $newstate = $state->finish_step($text, $format);
- $canview = ($newstate) ? has_capability('block/workflow:view', $newstate->context()) : false;
-
- if ($newstate && ($canview || block_workflow_can_make_changes($newstate))) {
- // There is a next possible state, and the current user may view and/or work on it.
- $outcome->response->blockcontent = $renderer->block_display($newstate, true);
- $outcome->response->stateid = $newstate->id;
- } else if ($newstate) {
- // There is a new step, but this user can't view it, and can't work on it ...
- $outcome->response->blockcontent = $renderer->block_display_step_complete_confirmation();
- } else {
- // Last step has been reached, if permitted retrieve the list of workflows.
- $workflows = new block_workflow_workflow();
- $previous = $workflows->load_context_workflows($state->contextid);
- $canadd = has_capability('block/workflow:manage', $state->context());
- $appliesto = $state->step()->workflow()->appliesto;
- $addableworkflows = block_workflow_workflow::available_workflows($appliesto);
- $outcome->response->listworkflows = $canadd && $addableworkflows;
-
- // Display.
- $outcome->response->blockcontent = $renderer->block_display_no_more_steps(
- $state->contextid, $canadd, $addableworkflows, $previous);
- }
- break;
- case 'toggletaskdone':
- // Toggle the todo item (mark as done).
- $todoid = required_param('todoid', PARAM_INT);
- $outcome->response->iscompleted = $state->todo_toggle($todoid);
- break;
- default:
- throw new block_workflow_ajax_exception('unknowajaxaction');
-}
-
-echo json_encode($outcome);
diff --git a/amd/build/comments.min.js b/amd/build/comments.min.js
new file mode 100644
index 0000000..23db647
--- /dev/null
+++ b/amd/build/comments.min.js
@@ -0,0 +1,11 @@
+define("block_workflow/comments",["exports","core/modal_factory","core/str","core/notification","block_workflow/todolist","core/fragment","core/templates","core/ajax","core/pending","core/loadingicon","core_form/events"],(function(_exports,_modal_factory,Str,_notification,_todolist,_fragment,_templates,_ajax,_pending,_loadingicon,FormEvents){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.initComments=void 0,_modal_factory=_interopRequireDefault(_modal_factory),Str=_interopRequireWildcard(Str),_notification=_interopRequireDefault(_notification),_fragment=_interopRequireDefault(_fragment),_templates=_interopRequireDefault(_templates),_pending=_interopRequireDefault(_pending),FormEvents=_interopRequireWildcard(FormEvents);
+/**
+ * JavaScript to handle comment.
+ *
+ * @module block_workflow/comments
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class Comment{constructor(options){var obj,key,value;value={BLOCKWORKFLOW:"block_workflow",BLOCKCOMMENTS:"block_workflow_comments",BLOCKCOMMBTN:"block_workflow_editcommentbutton",BLOCKFINISHBTN:"block_workflow_finishstepbutton",PANEL:"block-workflow-panel",CONTENT:"content",LIGHTBOX:"loading-lightbox",SUBMIT:"wfk-submit"},(key="CSS")in(obj=this)?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,this.editorid=options.editorid,this.editorname=options.editorname,this.stateid=options.stateid,this.contextid=options.contextid}async buildCommentModal(){return _modal_factory.default.create({type:_modal_factory.default.types.DEFAULT})}async initializer(){this.modal=await this.buildCommentModal(),this.modal.attachToDOM(),this.modal.hide(),this.attachEvents()}attachEvents(){const commentButton=document.querySelector("."+this.CSS.BLOCKCOMMBTN+" button, ."+this.CSS.BLOCKCOMMBTN+" input[type=submit]");commentButton&&(commentButton.onclick=event=>this.show(event,!1));const finishButton=document.querySelector("."+this.CSS.BLOCKFINISHBTN+" button, ."+this.CSS.BLOCKFINISHBTN+" input[type=submit]");finishButton&&(finishButton.onclick=event=>this.show(event,!0))}async show(event,finishStep){event.preventDefault();const[editCommentString,saveChangesString,finishString]=await Str.get_strings([{key:"editcomments",component:"block_workflow"},{key:"savechanges",component:"moodle"},{key:"finishstep",component:"block_workflow"}]);let inputLabel;finishStep?(this.modal.setTitle(finishString),inputLabel=finishString):(inputLabel=saveChangesString,this.modal.setTitle(editCommentString));const fragment=_fragment.default.loadFragment("block_workflow","commentform",this.contextid,{inputLabel:inputLabel}),pendingModalReady=new _pending.default("block_workflow/actions:show");fragment.then(function(html,js){this.modal.getBody()[0].innerHTML=html,_templates.default.runTemplateJS(js);const body=this.modal.getBody()[0];(0,_loadingicon.addIconToContainerRemoveOnCompletion)(this.modal.getBody()[0].querySelector("."+this.CSS.PANEL),pendingModalReady),this.modal.getRoot()[0].querySelector(".modal-dialog").style.cssText="width: fit-content; max-width: 1280px;",this.modal.getRoot()[0].querySelector(".modal-dialog").style.width="fit-content",this.modal.show(),body.querySelector(".".concat(this.CSS.PANEL," .col-md-3")).classList.add("hidden","d-none");const submitButton=body.querySelector('button[name="'.concat(this.CSS.SUBMIT,'"]'));submitButton.classList.add("ml-auto","mr-0"),submitButton.onclick=finishStep?this.finishStep.bind(this):this.save.bind(this);const editorId=this.editorid;this.getStepStateComment(this.stateid).then((function(result){const editor=document.getElementById(editorId+"editable");editor&&(editor.innerHTML=result.response),setTimeout((function(){window.tinyMCE&&window.tinyMCE.activeEditor&&(window.tinyMCE.activeEditor.setContent(result.response),window.tinyMCE.activeEditor.save())})),document.getElementById(editorId).value=result.response,pendingModalReady.resolve()})).catch(_notification.default.exception)}.bind(this))}getStepStateComment(stateid){return(0,_ajax.call)([{methodname:"block_workflow_get_step_state_comment",args:{stateid:stateid}}])[0]}finishStep(){const comment=document.getElementById(this.editorid).value,worklowBlock=document.querySelector("."+this.CSS.BLOCKWORKFLOW+" ."+this.CSS.CONTENT),modal=this.modal,commentCls=this;this.updateFinishStep(this.stateid,comment,document.getElementsByName(this.editorname+"[format]")[0].value).then(function(result){if(result.response){if(worklowBlock.innerHTML=result.response,result.stateid){commentCls.attachEvents();const todo=new _todolist.TodoList({stateid:result.stateid});commentCls.stateid=result.stateid,todo.initializer()}if(result.listworkflows){const selectId=worklowBlock.querySelector(".singleselect form select").getAttribute("id");document.getElementById(selectId).onchange=function(){void 0===this.selectedOptions[0].dataset.ignore&&this.closest("form").submit()}}}modal.hide(),this.resetAutoSaveData()}.bind(this)).catch(_notification.default.exception)}updateFinishStep(stateid,comment,format){return(0,_ajax.call)([{methodname:"block_workflow_finish_step",args:{stateid:this.stateid,text:comment,format:format}}])[0]}async save(){const comment=document.getElementById(this.editorid).value,commentsBlock=document.querySelector("."+this.CSS.BLOCKWORKFLOW+" ."+this.CSS.BLOCKCOMMENTS),noCommentString=await Str.get_string("nocomments","block_workflow"),modal=this.modal;this.updateStepStateComment(this.stateid,comment,document.getElementsByName(this.editorname+"[format]")[0].value).then(function(result){result.response?commentsBlock.innerHTML=result.response:commentsBlock.innerText=noCommentString,modal.hide(),this.resetAutoSaveData()}.bind(this)).catch(_notification.default.exception)}updateStepStateComment(stateid,comment,format){return(0,_ajax.call)([{methodname:"block_workflow_update_step_state_comment",args:{stateid:this.stateid,newcomment:comment,newcommentformat:format}}])[0]}resetAutoSaveData(){void 0!==window.tinyMCE&&window.tinyMCE.activeEditor&&FormEvents.notifyFormSubmittedByJavascript(window.tinyMCE.activeEditor.formElement)}}_exports.initComments=options=>{new Comment(options).initializer()}}));
+
+//# sourceMappingURL=comments.min.js.map
\ No newline at end of file
diff --git a/amd/build/comments.min.js.map b/amd/build/comments.min.js.map
new file mode 100644
index 0000000..7e851db
--- /dev/null
+++ b/amd/build/comments.min.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"comments.min.js","sources":["../src/comments.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\nimport ModalFactory from 'core/modal_factory';\nimport * as Str from 'core/str';\nimport Notification from 'core/notification';\nimport {TodoList} from 'block_workflow/todolist';\nimport Fragment from 'core/fragment';\nimport Templates from 'core/templates';\nimport {call as fetchMany} from 'core/ajax';\nimport Pending from 'core/pending';\nimport {addIconToContainerRemoveOnCompletion} from 'core/loadingicon';\nimport * as FormEvents from 'core_form/events';\n\n/**\n * JavaScript to handle comment.\n *\n * @module block_workflow/comments\n * @copyright 2023 The Open University\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nclass Comment {\n\n CSS = {\n BLOCKWORKFLOW: 'block_workflow',\n BLOCKCOMMENTS: 'block_workflow_comments',\n BLOCKCOMMBTN: 'block_workflow_editcommentbutton',\n BLOCKFINISHBTN: 'block_workflow_finishstepbutton',\n PANEL: 'block-workflow-panel',\n CONTENT: 'content',\n LIGHTBOX: 'loading-lightbox',\n SUBMIT: 'wfk-submit',\n };\n\n constructor(options) {\n this.editorid = options.editorid;\n this.editorname = options.editorname;\n this.stateid = options.stateid;\n this.contextid = options.contextid;\n }\n\n /**\n * Method that creates the comment modal.\n *\n * @returns {Promise} The modal promise (modal's body will be rendered later).\n */\n async buildCommentModal() {\n return ModalFactory.create({type: ModalFactory.types.DEFAULT});\n }\n\n /**\n * Initial function.\n */\n async initializer() {\n // Setup and attach the modal to DOM.\n this.modal = await this.buildCommentModal();\n this.modal.attachToDOM();\n this.modal.hide();\n this.attachEvents();\n }\n\n /**\n * Attach events to buttons.\n */\n attachEvents() {\n // Attach event for comment button.\n const commentButton = document.querySelector('.' + this.CSS.BLOCKCOMMBTN + ' button, .' +\n this.CSS.BLOCKCOMMBTN + ' input[type=submit]');\n if (commentButton) {\n commentButton.onclick = event => this.show(event, false);\n }\n // Attach event for finish step button.\n const finishButton = document.querySelector('.' + this.CSS.BLOCKFINISHBTN + ' button, .' +\n this.CSS.BLOCKFINISHBTN + ' input[type=submit]');\n if (finishButton) {\n finishButton.onclick = event => this.show(event, true);\n }\n }\n\n /**\n * Show comment action.\n *\n * @param {Object} event Event object.\n * @param {Boolean} finishStep Finish step flag.\n */\n async show(event, finishStep) {\n event.preventDefault();\n const [editCommentString, saveChangesString, finishString] = await Str.get_strings([\n {key: 'editcomments', component: 'block_workflow'},\n {key: 'savechanges', component: 'moodle'},\n {key: 'finishstep', component: 'block_workflow'},\n ]);\n\n let inputLabel;\n\n if (finishStep) {\n this.modal.setTitle(finishString);\n inputLabel = finishString;\n } else {\n inputLabel = saveChangesString;\n this.modal.setTitle(editCommentString);\n }\n\n const fragment = Fragment.loadFragment('block_workflow', 'commentform', this.contextid, {inputLabel});\n const pendingModalReady = new Pending('block_workflow/actions:show');\n fragment.then(function(html, js) {\n this.modal.getBody()[0].innerHTML = html;\n Templates.runTemplateJS(js);\n const body = this.modal.getBody()[0];\n addIconToContainerRemoveOnCompletion(\n this.modal.getBody()[0].querySelector('.' + this.CSS.PANEL), pendingModalReady\n );\n this.modal.getRoot()[0].querySelector('.modal-dialog').style.cssText = 'width: fit-content; max-width: 1280px;';\n this.modal.getRoot()[0].querySelector('.modal-dialog').style.width = 'fit-content';\n this.modal.show();\n body.querySelector(`.${this.CSS.PANEL} .col-md-3`).classList.add('hidden', 'd-none');\n const submitButton = body.querySelector(`button[name=\"${this.CSS.SUBMIT}\"]`);\n // Change position of the button.\n submitButton.classList.add('ml-auto', 'mr-0');\n if (finishStep) {\n submitButton.onclick = this.finishStep.bind(this);\n } else {\n submitButton.onclick = this.save.bind(this);\n }\n const editorId = this.editorid;\n // Fetch the comment and update the form\n this.getStepStateComment(this.stateid).then(function(result) {\n const editor = document.getElementById(editorId + 'editable');\n // Atto specific.\n if (editor) {\n editor.innerHTML = result.response;\n }\n // Tiny specific.\n // To make sure Tiny MCE has already loaded.\n setTimeout(function() {\n if (window.tinyMCE && window.tinyMCE.activeEditor) {\n window.tinyMCE.activeEditor.setContent(result.response);\n window.tinyMCE.activeEditor.save();\n }\n });\n document.getElementById(editorId).value = result.response;\n pendingModalReady.resolve();\n }).catch(Notification.exception);\n }.bind(this));\n }\n\n /**\n * Get the current comment of the step_state.\n *\n * @param {Number} stateid\n */\n getStepStateComment(stateid) {\n return fetchMany([{\n methodname: 'block_workflow_get_step_state_comment',\n args: {\n stateid: stateid,\n },\n }])[0];\n }\n\n /**\n * Handle finish step.\n */\n finishStep() {\n const comment = document.getElementById(this.editorid).value;\n const worklowBlock = document.querySelector('.' + this.CSS.BLOCKWORKFLOW + ' .' + this.CSS.CONTENT);\n const modal = this.modal;\n const commentCls = this;\n this.updateFinishStep(this.stateid, comment, document.getElementsByName(this.editorname + '[format]')[0].value)\n .then(function(result) {\n if (result.response) {\n // Update content\n worklowBlock.innerHTML = result.response;\n if (result.stateid) {\n // Re-attach events to block buttons\n commentCls.attachEvents();\n // Reinit to-do events\n const todo = new TodoList({stateid: result.stateid});\n commentCls.stateid = result.stateid;\n // We are on the next step\n todo.initializer();\n }\n if (result.listworkflows) {\n // Last step, available workflows are listed\n const selectId = worklowBlock.querySelector('.singleselect form select').getAttribute('id');\n // Reinit single_select event\n // This is horrible, but the core JS we need is now inline in the template,\n // so we have to copy it.\n document.getElementById(selectId).onchange = function() {\n if (this.selectedOptions[0].dataset.ignore === undefined) {\n this.closest('form').submit();\n }\n };\n }\n }\n modal.hide();\n this.resetAutoSaveData();\n }.bind(this)).catch(Notification.exception);\n }\n\n /**\n * Finish the current step_state.\n *\n * @param {Number} stateid stateid id of the current step_state.\n * @param {String} comment new comment of the finish step.\n * @param {Number} format format of the editor.\n */\n updateFinishStep(stateid, comment, format) {\n return fetchMany([{\n methodname: 'block_workflow_finish_step',\n args: {\n stateid: this.stateid,\n text: comment,\n format: format\n },\n }])[0];\n }\n\n /**\n * Handle save action.\n */\n async save() {\n const comment = document.getElementById(this.editorid).value;\n const commentsBlock = document.querySelector('.' + this.CSS.BLOCKWORKFLOW + ' .' + this.CSS.BLOCKCOMMENTS);\n const noCommentString = await Str.get_string('nocomments', 'block_workflow');\n const modal = this.modal;\n this.updateStepStateComment(this.stateid, comment, document.getElementsByName(this.editorname + '[format]')[0].value)\n .then(function(result) {\n if (result.response) {\n commentsBlock.innerHTML = result.response;\n } else {\n commentsBlock.innerText = noCommentString;\n }\n modal.hide();\n this.resetAutoSaveData();\n }.bind(this)).catch(Notification.exception);\n }\n\n /**\n * Update the comment of the step_state.\n *\n * @param {Number} stateid id of the current step_state.\n * @param {String} comment new comment of\n * @param {Number} format format of the editor.\n */\n updateStepStateComment(stateid, comment, format) {\n return fetchMany([{\n methodname: 'block_workflow_update_step_state_comment',\n args: {\n stateid: this.stateid,\n newcomment: comment,\n newcommentformat: format\n },\n }])[0];\n }\n\n /**\n * Reset auto-save data.\n */\n resetAutoSaveData() {\n if (window.tinyMCE !== undefined && window.tinyMCE.activeEditor) {\n FormEvents.notifyFormSubmittedByJavascript(window.tinyMCE.activeEditor.formElement);\n }\n }\n}\n\n/**\n * Handle action with comments.\n *\n * @param {Object} options The comment settings.\n */\nexport const initComments = (options) => {\n const comment = new Comment(options);\n comment.initializer();\n};\n"],"names":["Comment","constructor","options","BLOCKWORKFLOW","BLOCKCOMMENTS","BLOCKCOMMBTN","BLOCKFINISHBTN","PANEL","CONTENT","LIGHTBOX","SUBMIT","editorid","editorname","stateid","contextid","ModalFactory","create","type","types","DEFAULT","modal","this","buildCommentModal","attachToDOM","hide","attachEvents","commentButton","document","querySelector","CSS","onclick","event","show","finishButton","finishStep","preventDefault","editCommentString","saveChangesString","finishString","Str","get_strings","key","component","inputLabel","setTitle","fragment","Fragment","loadFragment","pendingModalReady","Pending","then","html","js","getBody","innerHTML","runTemplateJS","body","getRoot","style","cssText","width","classList","add","submitButton","bind","save","editorId","getStepStateComment","result","editor","getElementById","response","setTimeout","window","tinyMCE","activeEditor","setContent","value","resolve","catch","Notification","exception","methodname","args","comment","worklowBlock","commentCls","updateFinishStep","getElementsByName","todo","TodoList","initializer","listworkflows","selectId","getAttribute","onchange","undefined","selectedOptions","dataset","ignore","closest","submit","resetAutoSaveData","format","text","commentsBlock","noCommentString","get_string","updateStepStateComment","innerText","newcomment","newcommentformat","FormEvents","notifyFormSubmittedByJavascript","formElement"],"mappings":";;;;;;;;MAiCMA,QAaFC,YAAYC,iCAXN,CACFC,cAAgB,iBAChBC,cAAgB,0BAChBC,aAAgB,mCAChBC,eAAgB,kCAChBC,MAAgB,uBAChBC,QAAgB,UAChBC,SAAgB,mBAChBC,OAAgB,iJAIXC,SAAWT,QAAQS,cACnBC,WAAaV,QAAQU,gBACrBC,QAAUX,QAAQW,aAClBC,UAAYZ,QAAQY,2CASlBC,uBAAaC,OAAO,CAACC,KAAMF,uBAAaG,MAAMC,mCAQhDC,YAAcC,KAAKC,yBACnBF,MAAMG,mBACNH,MAAMI,YACNC,eAMTA,qBAEUC,cAAgBC,SAASC,cAAc,IAAMP,KAAKQ,IAAIxB,aAAe,aACvEgB,KAAKQ,IAAIxB,aAAe,uBACxBqB,gBACAA,cAAcI,QAAUC,OAASV,KAAKW,KAAKD,OAAO,UAGhDE,aAAeN,SAASC,cAAc,IAAMP,KAAKQ,IAAIvB,eAAiB,aACxEe,KAAKQ,IAAIvB,eAAiB,uBAC1B2B,eACAA,aAAaH,QAAUC,OAASV,KAAKW,KAAKD,OAAO,eAU9CA,MAAOG,YACdH,MAAMI,uBACCC,kBAAmBC,kBAAmBC,oBAAsBC,IAAIC,YAAY,CAC/E,CAACC,IAAK,eAAgBC,UAAW,kBACjC,CAACD,IAAK,cAAeC,UAAW,UAChC,CAACD,IAAK,aAAcC,UAAW,wBAG/BC,WAEAT,iBACKd,MAAMwB,SAASN,cACpBK,WAAaL,eAEbK,WAAaN,uBACRjB,MAAMwB,SAASR,0BAGlBS,SAAWC,kBAASC,aAAa,iBAAkB,cAAe1B,KAAKP,UAAW,CAAC6B,WAAAA,aACnFK,kBAAoB,IAAIC,iBAAQ,+BACtCJ,SAASK,KAAK,SAASC,KAAMC,SACpBhC,MAAMiC,UAAU,GAAGC,UAAYH,wBAC1BI,cAAcH,UAClBI,KAAOnC,KAAKD,MAAMiC,UAAU,yDAE9BhC,KAAKD,MAAMiC,UAAU,GAAGzB,cAAc,IAAMP,KAAKQ,IAAItB,OAAQyC,wBAE5D5B,MAAMqC,UAAU,GAAG7B,cAAc,iBAAiB8B,MAAMC,QAAU,8CAClEvC,MAAMqC,UAAU,GAAG7B,cAAc,iBAAiB8B,MAAME,MAAQ,mBAChExC,MAAMY,OACXwB,KAAK5B,yBAAkBP,KAAKQ,IAAItB,qBAAmBsD,UAAUC,IAAI,SAAU,gBACrEC,aAAeP,KAAK5B,qCAA8BP,KAAKQ,IAAInB,cAEjEqD,aAAaF,UAAUC,IAAI,UAAW,QAElCC,aAAajC,QADbI,WACuBb,KAAKa,WAAW8B,KAAK3C,MAErBA,KAAK4C,KAAKD,KAAK3C,YAEpC6C,SAAW7C,KAAKV,cAEjBwD,oBAAoB9C,KAAKR,SAASqC,MAAK,SAASkB,cAC3CC,OAAS1C,SAAS2C,eAAeJ,SAAW,YAE9CG,SACAA,OAAOf,UAAYc,OAAOG,UAI9BC,YAAW,WACHC,OAAOC,SAAWD,OAAOC,QAAQC,eACjCF,OAAOC,QAAQC,aAAaC,WAAWR,OAAOG,UAC9CE,OAAOC,QAAQC,aAAaV,WAGpCtC,SAAS2C,eAAeJ,UAAUW,MAAQT,OAAOG,SACjDvB,kBAAkB8B,aACnBC,MAAMC,sBAAaC,YACxBjB,KAAK3C,OAQX8C,oBAAoBtD,gBACT,cAAU,CAAC,CACdqE,WAAY,wCACZC,KAAM,CACFtE,QAASA,YAEb,GAMRqB,mBACUkD,QAAUzD,SAAS2C,eAAejD,KAAKV,UAAUkE,MACjDQ,aAAe1D,SAASC,cAAc,IAAMP,KAAKQ,IAAI1B,cAAgB,KAAOkB,KAAKQ,IAAIrB,SACrFY,MAAQC,KAAKD,MACbkE,WAAajE,UACdkE,iBAAiBlE,KAAKR,QAASuE,QAASzD,SAAS6D,kBAAkBnE,KAAKT,WAAa,YAAY,GAAGiE,OACpG3B,KAAK,SAASkB,WACPA,OAAOG,SAAU,IAEjBc,aAAa/B,UAAYc,OAAOG,SAC5BH,OAAOvD,QAAS,CAEhByE,WAAW7D,qBAELgE,KAAO,IAAIC,mBAAS,CAAC7E,QAASuD,OAAOvD,UAC3CyE,WAAWzE,QAAUuD,OAAOvD,QAE5B4E,KAAKE,iBAELvB,OAAOwB,cAAe,OAEhBC,SAAWR,aAAazD,cAAc,6BAA6BkE,aAAa,MAItFnE,SAAS2C,eAAeuB,UAAUE,SAAW,gBACMC,IAA3C3E,KAAK4E,gBAAgB,GAAGC,QAAQC,aAC3BC,QAAQ,QAAQC,WAKrCjF,MAAMI,YACD8E,qBACPtC,KAAK3C,OAAO0D,MAAMC,sBAAaC,WAUzCM,iBAAiB1E,QAASuE,QAASmB,eACxB,cAAU,CAAC,CACdrB,WAAY,6BACZC,KAAM,CACFtE,QAASQ,KAAKR,QACd2F,KAAMpB,QACNmB,OAAQA,WAEZ,sBAOEnB,QAAUzD,SAAS2C,eAAejD,KAAKV,UAAUkE,MACjD4B,cAAgB9E,SAASC,cAAc,IAAMP,KAAKQ,IAAI1B,cAAgB,KAAOkB,KAAKQ,IAAIzB,eACtFsG,sBAAwBnE,IAAIoE,WAAW,aAAc,kBACrDvF,MAAQC,KAAKD,WACdwF,uBAAuBvF,KAAKR,QAASuE,QAASzD,SAAS6D,kBAAkBnE,KAAKT,WAAa,YAAY,GAAGiE,OAC1G3B,KAAK,SAASkB,QACPA,OAAOG,SACPkC,cAAcnD,UAAYc,OAAOG,SAEjCkC,cAAcI,UAAYH,gBAE9BtF,MAAMI,YACD8E,qBACPtC,KAAK3C,OAAO0D,MAAMC,sBAAaC,WAUzC2B,uBAAuB/F,QAASuE,QAASmB,eAC9B,cAAU,CAAC,CACdrB,WAAY,2CACZC,KAAM,CACFtE,QAASQ,KAAKR,QACdiG,WAAY1B,QACZ2B,iBAAkBR,WAEtB,GAMRD,yBAC2BN,IAAnBvB,OAAOC,SAAyBD,OAAOC,QAAQC,cAC/CqC,WAAWC,gCAAgCxC,OAAOC,QAAQC,aAAauC,oCAUtDhH,UACT,IAAIF,QAAQE,SACpByF"}
\ No newline at end of file
diff --git a/amd/build/todolist.min.js b/amd/build/todolist.min.js
new file mode 100644
index 0000000..4145682
--- /dev/null
+++ b/amd/build/todolist.min.js
@@ -0,0 +1,10 @@
+define("block_workflow/todolist",["exports","core/notification","core/ajax"],(function(_exports,_notification,_ajax){var obj;function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}
+/**
+ * JavaScript for the workflow to-do list.
+ *
+ * @module block_workflow/todolist
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.initTodolist=_exports.TodoList=void 0,_notification=(obj=_notification)&&obj.__esModule?obj:{default:obj};class TodoList{constructor(options){_defineProperty(this,"TODOLISTNAME","blocks_workflow_todolist"),_defineProperty(this,"STATEID","stateid"),_defineProperty(this,"CSS",{BLOCKTODOTASK:"block-workflow-todotask",BLOCKTODOID:"block-workflow-todoid"}),this.stateid=options.stateid}initializer(){document.querySelectorAll("a."+this.CSS.BLOCKTODOTASK).forEach((node=>{node.closest("li").onclick=event=>this.toggle(event,node),node.setAttribute("href","#")}))}toggle(event,node){event.preventDefault();const reg=new RegExp(this.CSS.BLOCKTODOID+"-(\\d{1,})"),check=!node.parentNode.classList.contains("completed");this.updateStepStateTaskState(this.stateid,node.getAttribute("id").match(reg)[1],check).then((function(result){result.error?_notification.default.exception(result.error):result.response?node.parentNode.classList.add("completed"):node.parentNode.classList.remove("completed")})).catch(_notification.default.exception)}updateStepStateTaskState(stateid,todoid,check){return(0,_ajax.call)([{methodname:"block_workflow_update_step_state_task_state",args:{stateid:stateid,todoid:todoid,check:check}}])[0]}}_exports.TodoList=TodoList;_exports.initTodolist=options=>{new TodoList(options).initializer()}}));
+
+//# sourceMappingURL=todolist.min.js.map
\ No newline at end of file
diff --git a/amd/build/todolist.min.js.map b/amd/build/todolist.min.js.map
new file mode 100644
index 0000000..d228e3a
--- /dev/null
+++ b/amd/build/todolist.min.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"todolist.min.js","sources":["../src/todolist.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\nimport Notification from 'core/notification';\nimport {call as fetchMany} from 'core/ajax';\n\n/**\n * JavaScript for the workflow to-do list.\n *\n * @module block_workflow/todolist\n * @copyright 2023 The Open University\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport class TodoList {\n TODOLISTNAME = 'blocks_workflow_todolist';\n STATEID = 'stateid';\n CSS = {\n BLOCKTODOTASK: 'block-workflow-todotask',\n BLOCKTODOID: 'block-workflow-todoid'\n };\n\n constructor(options) {\n this.stateid = options.stateid;\n }\n\n /**\n * Initial function.\n */\n initializer() {\n // Take each of the workflow tasks, remove the anchor, and change it to\n // call our update function\n document.querySelectorAll('a.' + this.CSS.BLOCKTODOTASK).forEach(node => {\n node.closest('li').onclick = event => this.toggle(event, node);\n node.setAttribute('href', '#');\n });\n }\n\n /**\n * Toggle checkbox.\n *\n * @param {Object} event The event object.\n * @param {Object} node HTML node object.\n */\n toggle(event, node) {\n event.preventDefault();\n // Expression to fetch ID\n const reg = new RegExp(this.CSS.BLOCKTODOID + \"-(\\\\d{1,})\");\n // We don't have a real checkbox, it is just image with different class. So we will check the status base on class.\n // When we click to the link with completed class, meaning we want to uncheck so the status should be false.\n // When we click to the link without the completed class, meaning we want to check so the status should be true.\n const check = !node.parentNode.classList.contains('completed');\n this.updateStepStateTaskState(this.stateid, node.getAttribute('id').match(reg)[1], check)\n .then(function(result) {\n if (result.error) {\n Notification.exception(result.error);\n return;\n }\n if (result.response) {\n node.parentNode.classList.add('completed');\n } else {\n node.parentNode.classList.remove('completed');\n }\n }).catch(Notification.exception);\n }\n\n /**\n * Update step_state to to\n *\n * @param {Number} stateid id of the current step_state\n * @param {Number} todoid id of the current to do.\n * @param {Boolean} check whether the current to is has been checked/uncheck.\n */\n updateStepStateTaskState(stateid, todoid, check) {\n return fetchMany([{\n methodname: 'block_workflow_update_step_state_task_state',\n args: {\n stateid: stateid,\n todoid: todoid,\n check: check\n },\n }])[0];\n }\n}\n\n/**\n * Handle to-do list action.\n *\n * @param {Object} options The settings.\n */\nexport const initTodolist = (options) => {\n const todo = new TodoList(options);\n todo.initializer();\n};\n"],"names":["TodoList","constructor","options","BLOCKTODOTASK","BLOCKTODOID","stateid","initializer","document","querySelectorAll","this","CSS","forEach","node","closest","onclick","event","toggle","setAttribute","preventDefault","reg","RegExp","check","parentNode","classList","contains","updateStepStateTaskState","getAttribute","match","then","result","error","exception","response","add","remove","catch","Notification","todoid","methodname","args"],"mappings":";;;;;;;sLAyBaA,SAQTC,YAAYC,6CAPG,2DACL,sCACJ,CACFC,cAAe,0BACfC,YAAa,+BAIRC,QAAUH,QAAQG,QAM3BC,cAGIC,SAASC,iBAAiB,KAAOC,KAAKC,IAAIP,eAAeQ,SAAQC,OAC7DA,KAAKC,QAAQ,MAAMC,QAAUC,OAASN,KAAKO,OAAOD,MAAOH,MACzDA,KAAKK,aAAa,OAAQ,QAUlCD,OAAOD,MAAOH,MACVG,MAAMG,uBAEAC,IAAM,IAAIC,OAAOX,KAAKC,IAAIN,YAAc,cAIxCiB,OAAST,KAAKU,WAAWC,UAAUC,SAAS,kBAC7CC,yBAAyBhB,KAAKJ,QAASO,KAAKc,aAAa,MAAMC,MAAMR,KAAK,GAAIE,OAClFO,MAAK,SAASC,QACPA,OAAOC,4BACMC,UAAUF,OAAOC,OAG9BD,OAAOG,SACPpB,KAAKU,WAAWC,UAAUU,IAAI,aAE9BrB,KAAKU,WAAWC,UAAUW,OAAO,gBAEtCC,MAAMC,sBAAaL,WAU1BN,yBAAyBpB,QAASgC,OAAQhB,cAC/B,cAAU,CAAC,CACdiB,WAAY,8CACZC,KAAM,CACFlC,QAASA,QACTgC,OAAQA,OACRhB,MAAOA,UAEX,qDASiBnB,UACZ,IAAIF,SAASE,SACrBI"}
\ No newline at end of file
diff --git a/amd/build/userinfo.min.js b/amd/build/userinfo.min.js
new file mode 100644
index 0000000..a1bd0aa
--- /dev/null
+++ b/amd/build/userinfo.min.js
@@ -0,0 +1,10 @@
+define("block_workflow/userinfo",["exports","core/modal_factory"],(function(_exports,_modal_factory){var obj;function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}
+/**
+ * User info functionality for a popup in workflow block.
+ *
+ * @module block_workflow/userinfo
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_modal_factory=(obj=_modal_factory)&&obj.__esModule?obj:{default:obj};class Popup{constructor(){_defineProperty(this,"CSS",{USERINFOCLASS:".userinfoclass"}),_defineProperty(this,"PARAMS",{id:"id",HEADER:"header",BODY:"body",STEPNO:"stepno"})}initializer(){document.querySelectorAll(this.CSS.USERINFOCLASS).forEach((node=>{const header=node.getAttribute(this.PARAMS.HEADER),body=node.getAttribute(this.PARAMS.BODY);node.onclick=event=>this.displayDialog(event,header,body)}))}async displayDialog(e,header,body){e.preventDefault();const modal=await _modal_factory.default.create({title:header,body:body,large:!0});modal.attachToDOM(),modal.getRoot()[0].querySelector(".modal-dialog").style.width="fit-content",modal.show()}}_exports.init=()=>{(new Popup).initializer()}}));
+
+//# sourceMappingURL=userinfo.min.js.map
\ No newline at end of file
diff --git a/amd/build/userinfo.min.js.map b/amd/build/userinfo.min.js.map
new file mode 100644
index 0000000..0641531
--- /dev/null
+++ b/amd/build/userinfo.min.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"userinfo.min.js","sources":["../src/userinfo.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\nimport ModalFactory from 'core/modal_factory';\n\n/**\n * User info functionality for a popup in workflow block.\n *\n * @module block_workflow/userinfo\n * @copyright 2023 The Open University\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nclass Popup {\n CSS = {\n USERINFOCLASS: '.userinfoclass'\n };\n\n PARAMS = {\n id: 'id',\n HEADER: 'header',\n BODY: 'body',\n STEPNO: 'stepno'\n };\n\n /**\n * Initial function.\n */\n initializer() {\n document.querySelectorAll(this.CSS.USERINFOCLASS).forEach(node => {\n const header = node.getAttribute(this.PARAMS.HEADER);\n const body = node.getAttribute(this.PARAMS.BODY);\n node.onclick = event => this.displayDialog(event, header, body);\n });\n }\n\n /**\n * Handle display modal.\n *\n * @param {Object} e The event object.\n * @param {String} header Title string.\n * @param {String} body Body data.\n */\n async displayDialog(e, header, body) {\n e.preventDefault();\n const modal = await ModalFactory.create({\n title: header,\n body: body,\n large: true,\n });\n modal.attachToDOM();\n modal.getRoot()[0].querySelector('.modal-dialog').style.width = 'fit-content';\n modal.show();\n }\n}\n\n/**\n * Handle userinfo action.\n */\nexport const init = () => {\n const popup = new Popup();\n popup.initializer();\n};\n"],"names":["Popup","USERINFOCLASS","id","HEADER","BODY","STEPNO","initializer","document","querySelectorAll","this","CSS","forEach","node","header","getAttribute","PARAMS","body","onclick","event","displayDialog","e","preventDefault","modal","ModalFactory","create","title","large","attachToDOM","getRoot","querySelector","style","width","show"],"mappings":";;;;;;;8JAwBMA,+CACI,CACFC,cAAe,iDAGV,CACLC,GAAI,KACJC,OAAQ,SACRC,KAAM,OACNC,OAAQ,WAMZC,cACIC,SAASC,iBAAiBC,KAAKC,IAAIT,eAAeU,SAAQC,aAChDC,OAASD,KAAKE,aAAaL,KAAKM,OAAOZ,QACvCa,KAAOJ,KAAKE,aAAaL,KAAKM,OAAOX,MAC3CQ,KAAKK,QAAUC,OAAST,KAAKU,cAAcD,MAAOL,OAAQG,6BAW9CI,EAAGP,OAAQG,MAC3BI,EAAEC,uBACIC,YAAcC,uBAAaC,OAAO,CACpCC,MAAOZ,OACPG,KAAMA,KACNU,OAAO,IAEXJ,MAAMK,cACNL,MAAMM,UAAU,GAAGC,cAAc,iBAAiBC,MAAMC,MAAQ,cAChET,MAAMU,sBAOM,MACF,IAAIhC,OACZM"}
\ No newline at end of file
diff --git a/amd/src/comments.js b/amd/src/comments.js
new file mode 100644
index 0000000..9b45b98
--- /dev/null
+++ b/amd/src/comments.js
@@ -0,0 +1,287 @@
+// 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 .
+
+import ModalFactory from 'core/modal_factory';
+import * as Str from 'core/str';
+import Notification from 'core/notification';
+import {TodoList} from 'block_workflow/todolist';
+import Fragment from 'core/fragment';
+import Templates from 'core/templates';
+import {call as fetchMany} from 'core/ajax';
+import Pending from 'core/pending';
+import {addIconToContainerRemoveOnCompletion} from 'core/loadingicon';
+import * as FormEvents from 'core_form/events';
+
+/**
+ * JavaScript to handle comment.
+ *
+ * @module block_workflow/comments
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class Comment {
+
+ CSS = {
+ BLOCKWORKFLOW: 'block_workflow',
+ BLOCKCOMMENTS: 'block_workflow_comments',
+ BLOCKCOMMBTN: 'block_workflow_editcommentbutton',
+ BLOCKFINISHBTN: 'block_workflow_finishstepbutton',
+ PANEL: 'block-workflow-panel',
+ CONTENT: 'content',
+ LIGHTBOX: 'loading-lightbox',
+ SUBMIT: 'wfk-submit',
+ };
+
+ constructor(options) {
+ this.editorid = options.editorid;
+ this.editorname = options.editorname;
+ this.stateid = options.stateid;
+ this.contextid = options.contextid;
+ }
+
+ /**
+ * Method that creates the comment modal.
+ *
+ * @returns {Promise} The modal promise (modal's body will be rendered later).
+ */
+ async buildCommentModal() {
+ return ModalFactory.create({type: ModalFactory.types.DEFAULT});
+ }
+
+ /**
+ * Initial function.
+ */
+ async initializer() {
+ // Setup and attach the modal to DOM.
+ this.modal = await this.buildCommentModal();
+ this.modal.attachToDOM();
+ this.modal.hide();
+ this.attachEvents();
+ }
+
+ /**
+ * Attach events to buttons.
+ */
+ attachEvents() {
+ // Attach event for comment button.
+ const commentButton = document.querySelector('.' + this.CSS.BLOCKCOMMBTN + ' button, .' +
+ this.CSS.BLOCKCOMMBTN + ' input[type=submit]');
+ if (commentButton) {
+ commentButton.onclick = event => this.show(event, false);
+ }
+ // Attach event for finish step button.
+ const finishButton = document.querySelector('.' + this.CSS.BLOCKFINISHBTN + ' button, .' +
+ this.CSS.BLOCKFINISHBTN + ' input[type=submit]');
+ if (finishButton) {
+ finishButton.onclick = event => this.show(event, true);
+ }
+ }
+
+ /**
+ * Show comment action.
+ *
+ * @param {Object} event Event object.
+ * @param {Boolean} finishStep Finish step flag.
+ */
+ async show(event, finishStep) {
+ event.preventDefault();
+ const [editCommentString, saveChangesString, finishString] = await Str.get_strings([
+ {key: 'editcomments', component: 'block_workflow'},
+ {key: 'savechanges', component: 'moodle'},
+ {key: 'finishstep', component: 'block_workflow'},
+ ]);
+
+ let inputLabel;
+
+ if (finishStep) {
+ this.modal.setTitle(finishString);
+ inputLabel = finishString;
+ } else {
+ inputLabel = saveChangesString;
+ this.modal.setTitle(editCommentString);
+ }
+
+ const fragment = Fragment.loadFragment('block_workflow', 'commentform', this.contextid, {inputLabel});
+ const pendingModalReady = new Pending('block_workflow/actions:show');
+ fragment.then(function(html, js) {
+ this.modal.getBody()[0].innerHTML = html;
+ Templates.runTemplateJS(js);
+ const body = this.modal.getBody()[0];
+ addIconToContainerRemoveOnCompletion(
+ this.modal.getBody()[0].querySelector('.' + this.CSS.PANEL), pendingModalReady
+ );
+ this.modal.getRoot()[0].querySelector('.modal-dialog').style.cssText = 'width: fit-content; max-width: 1280px;';
+ this.modal.getRoot()[0].querySelector('.modal-dialog').style.width = 'fit-content';
+ this.modal.show();
+ body.querySelector(`.${this.CSS.PANEL} .col-md-3`).classList.add('hidden', 'd-none');
+ const submitButton = body.querySelector(`button[name="${this.CSS.SUBMIT}"]`);
+ // Change position of the button.
+ submitButton.classList.add('ml-auto', 'mr-0');
+ if (finishStep) {
+ submitButton.onclick = this.finishStep.bind(this);
+ } else {
+ submitButton.onclick = this.save.bind(this);
+ }
+ const editorId = this.editorid;
+ // Fetch the comment and update the form
+ this.getStepStateComment(this.stateid).then(function(result) {
+ const editor = document.getElementById(editorId + 'editable');
+ // Atto specific.
+ if (editor) {
+ editor.innerHTML = result.response;
+ }
+ // Tiny specific.
+ // To make sure Tiny MCE has already loaded.
+ setTimeout(function() {
+ if (window.tinyMCE && window.tinyMCE.activeEditor) {
+ window.tinyMCE.activeEditor.setContent(result.response);
+ window.tinyMCE.activeEditor.save();
+ }
+ });
+ document.getElementById(editorId).value = result.response;
+ pendingModalReady.resolve();
+ }).catch(Notification.exception);
+ }.bind(this));
+ }
+
+ /**
+ * Get the current comment of the step_state.
+ *
+ * @param {Number} stateid
+ */
+ getStepStateComment(stateid) {
+ return fetchMany([{
+ methodname: 'block_workflow_get_step_state_comment',
+ args: {
+ stateid: stateid,
+ },
+ }])[0];
+ }
+
+ /**
+ * Handle finish step.
+ */
+ finishStep() {
+ const comment = document.getElementById(this.editorid).value;
+ const worklowBlock = document.querySelector('.' + this.CSS.BLOCKWORKFLOW + ' .' + this.CSS.CONTENT);
+ const modal = this.modal;
+ const commentCls = this;
+ this.updateFinishStep(this.stateid, comment, document.getElementsByName(this.editorname + '[format]')[0].value)
+ .then(function(result) {
+ if (result.response) {
+ // Update content
+ worklowBlock.innerHTML = result.response;
+ if (result.stateid) {
+ // Re-attach events to block buttons
+ commentCls.attachEvents();
+ // Reinit to-do events
+ const todo = new TodoList({stateid: result.stateid});
+ commentCls.stateid = result.stateid;
+ // We are on the next step
+ todo.initializer();
+ }
+ if (result.listworkflows) {
+ // Last step, available workflows are listed
+ const selectId = worklowBlock.querySelector('.singleselect form select').getAttribute('id');
+ // Reinit single_select event
+ // This is horrible, but the core JS we need is now inline in the template,
+ // so we have to copy it.
+ document.getElementById(selectId).onchange = function() {
+ if (this.selectedOptions[0].dataset.ignore === undefined) {
+ this.closest('form').submit();
+ }
+ };
+ }
+ }
+ modal.hide();
+ this.resetAutoSaveData();
+ }.bind(this)).catch(Notification.exception);
+ }
+
+ /**
+ * Finish the current step_state.
+ *
+ * @param {Number} stateid stateid id of the current step_state.
+ * @param {String} comment new comment of the finish step.
+ * @param {Number} format format of the editor.
+ */
+ updateFinishStep(stateid, comment, format) {
+ return fetchMany([{
+ methodname: 'block_workflow_finish_step',
+ args: {
+ stateid: this.stateid,
+ text: comment,
+ format: format
+ },
+ }])[0];
+ }
+
+ /**
+ * Handle save action.
+ */
+ async save() {
+ const comment = document.getElementById(this.editorid).value;
+ const commentsBlock = document.querySelector('.' + this.CSS.BLOCKWORKFLOW + ' .' + this.CSS.BLOCKCOMMENTS);
+ const noCommentString = await Str.get_string('nocomments', 'block_workflow');
+ const modal = this.modal;
+ this.updateStepStateComment(this.stateid, comment, document.getElementsByName(this.editorname + '[format]')[0].value)
+ .then(function(result) {
+ if (result.response) {
+ commentsBlock.innerHTML = result.response;
+ } else {
+ commentsBlock.innerText = noCommentString;
+ }
+ modal.hide();
+ this.resetAutoSaveData();
+ }.bind(this)).catch(Notification.exception);
+ }
+
+ /**
+ * Update the comment of the step_state.
+ *
+ * @param {Number} stateid id of the current step_state.
+ * @param {String} comment new comment of
+ * @param {Number} format format of the editor.
+ */
+ updateStepStateComment(stateid, comment, format) {
+ return fetchMany([{
+ methodname: 'block_workflow_update_step_state_comment',
+ args: {
+ stateid: this.stateid,
+ newcomment: comment,
+ newcommentformat: format
+ },
+ }])[0];
+ }
+
+ /**
+ * Reset auto-save data.
+ */
+ resetAutoSaveData() {
+ if (window.tinyMCE !== undefined && window.tinyMCE.activeEditor) {
+ FormEvents.notifyFormSubmittedByJavascript(window.tinyMCE.activeEditor.formElement);
+ }
+ }
+}
+
+/**
+ * Handle action with comments.
+ *
+ * @param {Object} options The comment settings.
+ */
+export const initComments = (options) => {
+ const comment = new Comment(options);
+ comment.initializer();
+};
diff --git a/amd/src/todolist.js b/amd/src/todolist.js
new file mode 100644
index 0000000..724ab82
--- /dev/null
+++ b/amd/src/todolist.js
@@ -0,0 +1,105 @@
+// 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 .
+
+import Notification from 'core/notification';
+import {call as fetchMany} from 'core/ajax';
+
+/**
+ * JavaScript for the workflow to-do list.
+ *
+ * @module block_workflow/todolist
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+export class TodoList {
+ TODOLISTNAME = 'blocks_workflow_todolist';
+ STATEID = 'stateid';
+ CSS = {
+ BLOCKTODOTASK: 'block-workflow-todotask',
+ BLOCKTODOID: 'block-workflow-todoid'
+ };
+
+ constructor(options) {
+ this.stateid = options.stateid;
+ }
+
+ /**
+ * Initial function.
+ */
+ initializer() {
+ // Take each of the workflow tasks, remove the anchor, and change it to
+ // call our update function
+ document.querySelectorAll('a.' + this.CSS.BLOCKTODOTASK).forEach(node => {
+ node.closest('li').onclick = event => this.toggle(event, node);
+ node.setAttribute('href', '#');
+ });
+ }
+
+ /**
+ * Toggle checkbox.
+ *
+ * @param {Object} event The event object.
+ * @param {Object} node HTML node object.
+ */
+ toggle(event, node) {
+ event.preventDefault();
+ // Expression to fetch ID
+ const reg = new RegExp(this.CSS.BLOCKTODOID + "-(\\d{1,})");
+ // We don't have a real checkbox, it is just image with different class. So we will check the status base on class.
+ // When we click to the link with completed class, meaning we want to uncheck so the status should be false.
+ // When we click to the link without the completed class, meaning we want to check so the status should be true.
+ const check = !node.parentNode.classList.contains('completed');
+ this.updateStepStateTaskState(this.stateid, node.getAttribute('id').match(reg)[1], check)
+ .then(function(result) {
+ if (result.error) {
+ Notification.exception(result.error);
+ return;
+ }
+ if (result.response) {
+ node.parentNode.classList.add('completed');
+ } else {
+ node.parentNode.classList.remove('completed');
+ }
+ }).catch(Notification.exception);
+ }
+
+ /**
+ * Update step_state to to
+ *
+ * @param {Number} stateid id of the current step_state
+ * @param {Number} todoid id of the current to do.
+ * @param {Boolean} check whether the current to is has been checked/uncheck.
+ */
+ updateStepStateTaskState(stateid, todoid, check) {
+ return fetchMany([{
+ methodname: 'block_workflow_update_step_state_task_state',
+ args: {
+ stateid: stateid,
+ todoid: todoid,
+ check: check
+ },
+ }])[0];
+ }
+}
+
+/**
+ * Handle to-do list action.
+ *
+ * @param {Object} options The settings.
+ */
+export const initTodolist = (options) => {
+ const todo = new TodoList(options);
+ todo.initializer();
+};
diff --git a/amd/src/userinfo.js b/amd/src/userinfo.js
new file mode 100644
index 0000000..ad146c2
--- /dev/null
+++ b/amd/src/userinfo.js
@@ -0,0 +1,74 @@
+// 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 .
+
+import ModalFactory from 'core/modal_factory';
+
+/**
+ * User info functionality for a popup in workflow block.
+ *
+ * @module block_workflow/userinfo
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class Popup {
+ CSS = {
+ USERINFOCLASS: '.userinfoclass'
+ };
+
+ PARAMS = {
+ id: 'id',
+ HEADER: 'header',
+ BODY: 'body',
+ STEPNO: 'stepno'
+ };
+
+ /**
+ * Initial function.
+ */
+ initializer() {
+ document.querySelectorAll(this.CSS.USERINFOCLASS).forEach(node => {
+ const header = node.getAttribute(this.PARAMS.HEADER);
+ const body = node.getAttribute(this.PARAMS.BODY);
+ node.onclick = event => this.displayDialog(event, header, body);
+ });
+ }
+
+ /**
+ * Handle display modal.
+ *
+ * @param {Object} e The event object.
+ * @param {String} header Title string.
+ * @param {String} body Body data.
+ */
+ async displayDialog(e, header, body) {
+ e.preventDefault();
+ const modal = await ModalFactory.create({
+ title: header,
+ body: body,
+ large: true,
+ });
+ modal.attachToDOM();
+ modal.getRoot()[0].querySelector('.modal-dialog').style.width = 'fit-content';
+ modal.show();
+ }
+}
+
+/**
+ * Handle userinfo action.
+ */
+export const init = () => {
+ const popup = new Popup();
+ popup.initializer();
+};
diff --git a/block_workflow.php b/block_workflow.php
index 4627750..e1730bb 100644
--- a/block_workflow.php
+++ b/block_workflow.php
@@ -28,7 +28,15 @@
require_once($CFG->dirroot . '/lib/form/editor.php');
+/**
+ * Class block_workflow
+ */
class block_workflow extends block_base {
+ /**
+ * Initializes the block settings and properties.
+ *
+ * @return void
+ */
public function init() {
global $CFG;
$this->title = get_string('workflow', 'block_workflow');
@@ -81,16 +89,14 @@ public function get_content() {
$this->page->requires->strings_for_js(['editcomments', 'nocomments', 'finishstep'], 'block_workflow');
$this->page->requires->strings_for_js(['savechanges'], 'moodle');
- // Initialise the YUI module.
- $arguments = array(
+ $arguments = [
'stateid' => $state->id,
- 'editorid' => 'wkf-comment-editor',
+ 'editorid' => 'id_wkf-comment-editor',
'editorname' => 'comment_editor',
- );
- $this->page->requires->yui_module('moodle-block_workflow-comments', 'M.blocks_workflow.init_comments',
- [$arguments]);
- $this->page->requires->yui_module('moodle-block_workflow-todolist', 'M.blocks_workflow.init_todolist',
- [['stateid' => $state->id]]);
+ 'contextid' => $this->instance->parentcontextid,
+ ];
+ $this->page->requires->js_call_amd('block_workflow/comments', 'initComments', [$arguments]);
+ $this->page->requires->js_call_amd('block_workflow/todolist', 'initTodolist', [['stateid' => $state->id]]);
// Display the block for this state.
$this->content->text = $renderer->block_display($state);
@@ -99,7 +105,7 @@ public function get_content() {
$previous = $workflows->load_context_workflows($this->instance->parentcontextid);
$canadd = has_capability('block/workflow:manage', $this->context);
- // If this is a module, retrieve it's name, otherwise try the pagelayout to confirm
+ // If this is a module, retrieve its name, otherwise try the pagelayout to confirm
// that this is a course.
if ($this->page->cm) {
$appliesto = $this->page->cm->modname;
@@ -132,7 +138,7 @@ public function instance_allow_multiple() {
* @return array An array of the applicable formats for the block
*/
public function applicable_formats() {
- return array('course' => true, 'mod' => true);
+ return ['course' => true, 'mod' => true];
}
/**
diff --git a/changes.md b/changes.md
index 3e93c11..09619ca 100644
--- a/changes.md
+++ b/changes.md
@@ -1,5 +1,25 @@
# Change log for the Workflow block
+## Changes in 2.4
+* This version works with Moodle 5.0.
+* Automation test failures are fixed.
+* Cherry-picked commits since february 2024 till now:
+ * Fix PHP8 deprecation errors (optional params before required ones)
+ * Behat: blocks/workflow (tt)
+ * blocks/workflow: Fix PHP 8.1 issues
+ * M4.2: fix uses of depreated cron_setup_user
+ * Workflow error when moving workflow on - and error reporting code is buggy
+ * YUI->AMD: Rewrite old JavaScript in block_workflow
+ * Behat: PHP8.2: fix block_/report_workflow failures
+ * Workflow block: convert use of ajax.php into moodle web services
+ * Workflow block: convert use of ajax.php into moodle web services
+ * Workflow/TinyEditor: incorrectly keeps the cached data when comment and finish step
+ * Moodle 4.5 merge - replace deprecated get_plugin_list
+ * Moodle 4.5 merge - fix miscellaneous Behat and PHPunit failures
+ * Theme: Technical debt - remove IE-specific rules
+ * Workflow: Enable logs to show whether a workflow email is sent
+* Upgrade the CI to support Moodle 5.0 (PHP 8.3), and update the branch to support branch MOODLE_405_STABLE, and MOODLE_500_STABLE.
+
## Changes in 2.3
* This version works with Moodle 4.0.
diff --git a/classes/command.php b/classes/command.php
index fd69eb8..d9c8ed1 100644
--- a/classes/command.php
+++ b/classes/command.php
@@ -104,7 +104,7 @@ public function get_validation_errors($args, $step, $state = null) {
public static function role_exists($rolename) {
global $DB;
- $role = $DB->get_record('role', array('shortname' => strtolower($rolename)));
+ $role = $DB->get_record('role', ['shortname' => strtolower($rolename)]);
return $role;
}
@@ -157,6 +157,14 @@ public function is_course($workflow) {
return ($workflow->appliesto == 'course');
}
+ /**
+ * Checks if the next word matches the required word.
+ *
+ * @param string $requiredword The word that is expected.
+ * @param string $actualword The word that is being checked.
+ * @param mixed $data Additional data used for the check.
+ * @return bool
+ */
protected function check_next_word_is($requiredword, $actualword, $data) {
if ($actualword != $requiredword) {
$data->errors[] = get_string('invalidsyntaxmissingx', 'block_workflow', $requiredword);
diff --git a/classes/command_assignrole.php b/classes/command_assignrole.php
index 550c641..89b2d4f 100644
--- a/classes/command_assignrole.php
+++ b/classes/command_assignrole.php
@@ -50,7 +50,7 @@ class block_workflow_command_assignrole extends block_workflow_command {
public function parse($args, $step, $state = null) {
// We'll return the components in an object.
$data = new stdClass();
- $data->errors = array();
+ $data->errors = [];
if ($state) {
$data->context = $state->context();
@@ -72,8 +72,8 @@ public function parse($args, $step, $state = null) {
}
// Check whether the specified roles exist and fill the list of target users.
- $data->roles = array();
- $data->users = array();
+ $data->roles = [];
+ $data->users = [];
// Check each role exists, and retrieve the data.
foreach ($line as $role) {
diff --git a/classes/command_email.php b/classes/command_email.php
index aba7068..4ddf6be 100644
--- a/classes/command_email.php
+++ b/classes/command_email.php
@@ -43,12 +43,12 @@ class block_workflow_command_email extends block_workflow_command {
*/
public function parse_args($args) {
$data = new stdClass();
- $data->errors = array();
+ $data->errors = [];
// Break down the line. It should be in the format:
// email to rolea roleb rolen
// with any number of role shortnames.
- $line = preg_split('/[\s+]/', $args);
+ $line = preg_split('/[\s+]/', $args ?? '');
// Grab the email name.
$data->emailname = array_shift($line);
@@ -106,7 +106,7 @@ public function parse($args, $step, $state = null) {
}
// Check whether the specified roles exist and fill the list of target users.
- $data->users = array();
+ $data->users = [];
foreach ($data->roles as $role) {
$thisrole = parent::require_role_exists($role, $data->errors);
if ($data->errors) {
@@ -173,7 +173,7 @@ public function execute($args, block_workflow_step_state $state) {
*/
foreach ($email->users as $user) {
$eventdata->userto = $user;
- self::message_send($eventdata);
+ self::message_send($state, $eventdata);
}
}
@@ -186,7 +186,7 @@ public function execute($args, block_workflow_step_state $state) {
*/
public function email($shortname, &$errors) {
global $DB;
- $email = $DB->get_record('block_workflow_emails', array('shortname' => $shortname));
+ $email = $DB->get_record('block_workflow_emails', ['shortname' => $shortname]);
if (!$email) {
$errors[] = get_string('invalidemailemail', 'block_workflow', $shortname);
return false;
@@ -279,7 +279,7 @@ private function email_params($email, $state) {
$string = str_replace('%%instructions%%', $instructions, $string);
// Replace %%tasks%%.
- $tasks = array();
+ $tasks = [];
foreach ($step->todos() as $todo) {
$tasks[] = format_string($todo->task);
}
@@ -302,7 +302,7 @@ private function email_params($email, $state) {
$format = FORMAT_HTML;
}
$string = str_replace('%%comment%%', format_text($comment, $format,
- array('context' => $email->context)), $string);
+ ['context' => $email->context]), $string);
// Re-assign the message.
$email->email->message = $string;
@@ -319,14 +319,13 @@ private function email_params($email, $state) {
*
* It is safe to call this function multiple times
*
- * @access public
+ * @param block_workflow_step_state $state The step-state with the data
* @param object $eventdata The message to send
- * @return void
*/
- public static function message_send($eventdata = null) {
- global $DB, $SITE;
+ public static function message_send(block_workflow_step_state $state, $eventdata = null) {
+ global $DB;
- static $mailqueue = array();
+ static $mailqueue = [];
if ($eventdata) {
$mailqueue[] = clone $eventdata;
@@ -336,8 +335,18 @@ public static function message_send($eventdata = null) {
// Only try to send if we're not in a transaction.
while ($eventdata = array_shift($mailqueue)) {
// Send each message in the array.
- if (!message_send($eventdata)) {
- throw new workflow_command_failed_exception(get_string('emailfailed', 'block_workflow'));
+ try {
+ if (!message_send($eventdata)) {
+ throw new block_workflow_exception(
+ get_string('emailfailed', 'block_workflow',
+ ['email' => $eventdata->userto->email, 'subject' => $eventdata->subject]));
+ } else {
+ $event = \block_workflow\event\email_sent_status::create_from_step_state($state);
+ $event->trigger();
+ }
+ } catch (Exception $e) {
+ $event = \block_workflow\event\email_sent_status::create_from_step_state($state, $e->getMessage());
+ $event->trigger();
}
}
}
diff --git a/classes/command_override.php b/classes/command_override.php
index 48d1782..8cd4ccf 100644
--- a/classes/command_override.php
+++ b/classes/command_override.php
@@ -33,9 +33,18 @@
*
*/
class block_workflow_command_override extends block_workflow_command {
+
+ /**
+ * Parses the provided arguments and processes the workflow step and state.
+ *
+ * @param array $args The arguments to be parsed.
+ * @param mixed $step The workflow step to be processed.
+ * @param mixed|null $state The current state of the workflow (optional).
+ * @return stdClass
+ */
public function parse($args, $step, $state = null) {
$data = new stdClass();
- $data->errors = array();
+ $data->errors = [];
if ($state) {
$data->context = $state->context();
@@ -118,6 +127,14 @@ public function parse($args, $step, $state = null) {
return $data;
}
+
+ /**
+ * Executes the command with the given arguments and state.
+ *
+ * @param array $args The arguments to be used for execution.
+ * @param mixed $state The current state to be processed.
+ * @return void
+ */
public function execute($args, $state) {
$data = $this->parse($args, $state->step(), $state);
assign_capability($data->capability, $data->permission, $data->role->id, $data->contextid, true);
diff --git a/classes/command_setactivitylinkedsetting.php b/classes/command_setactivitylinkedsetting.php
index 1f808c3..0b18e3c 100644
--- a/classes/command_setactivitylinkedsetting.php
+++ b/classes/command_setactivitylinkedsetting.php
@@ -47,12 +47,20 @@ class block_workflow_command_setactivitylinkedsetting extends block_workflow_com
/** @var string used to indicate that the script action is to set values. */
const CLEAR = 'clear';
+ /**
+ * Parses the given arguments and processes the workflow step.
+ *
+ * @param array $args Arguments to be parsed.
+ * @param int $step The workflow step identifier.
+ * @param mixed|null $state Optional state information.
+ * @return stdClass The result of the parsing operation.
+ */
public function parse($args, $step, $state = null) {
global $DB;
$dbman = $DB->get_manager();
$data = new stdClass();
- $data->errors = array();
+ $data->errors = [];
$workflow = $step->workflow();
@@ -106,7 +114,7 @@ public function parse($args, $step, $state = null) {
}
if ($data->action == self::SET) {
- $data->toset = array();
+ $data->toset = [];
while ($line) {
$column = array_shift($line);
if (!$dbman->field_exists($data->table, $column)) {
@@ -126,17 +134,24 @@ public function parse($args, $step, $state = null) {
return $data;
}
+ /**
+ * Executes the command to set the activity linked setting.
+ *
+ * @param mixed $args The arguments required for execution.
+ * @param mixed $state The current state or context for the command.
+ * @return void
+ */
public function execute($args, $state) {
global $DB;
$data = $this->parse($args, $state->step(), $state);
if ($data->action == self::CLEAR) {
- $DB->delete_records($data->table, array($data->fkcolumn => $data->cm->instance));
+ $DB->delete_records($data->table, [$data->fkcolumn => $data->cm->instance]);
return;
}
- $existingrow = $DB->get_record($data->table, array($data->fkcolumn => $data->cm->instance));
+ $existingrow = $DB->get_record($data->table, [$data->fkcolumn => $data->cm->instance]);
if ($existingrow) {
$row = new stdClass();
$row->id = $existingrow->id;
diff --git a/classes/command_setactivitysetting.php b/classes/command_setactivitysetting.php
index 5d5f98d..02e87fa 100644
--- a/classes/command_setactivitysetting.php
+++ b/classes/command_setactivitysetting.php
@@ -33,57 +33,14 @@
*
*/
class block_workflow_command_setactivitysetting extends block_workflow_command {
- public function parse($args, $step, $state = null) {
- global $DB;
- $data = new stdClass();
- $data->errors = array();
-
- $workflow = $step->workflow();
-
- // Check that this step workflow relatees to an activity.
- if (!parent::is_activity($workflow)) {
- $data->errors[] = get_string('notanactivity', 'block_workflow', 'setactivityvisibility');
- return $data;
- }
-
- if ($state) {
- $data->cm = get_coursemodule_from_id($workflow->appliesto, $state->context()->instanceid);
- }
-
- // We'll use the database_manager to check whether tables and fields exist.
- $dbman = $DB->get_manager();
-
- // Check that the $appliesto table exists.
- $data->table = $workflow->appliesto;
- if (!$dbman->table_exists($data->table)) {
- $data->errors[] = get_string('invalidappliestotable', 'block_workflow', $workflow->appliesto);
- return $data;
- }
-
- // Break down the line. It should be in the format:
- // column to value
- // where column is a column in the activity settings table.
- $line = preg_split('/[\s+]/', $args);
-
- // Get the column and check that it exists.
- $data->column = array_shift($line);
- if (!$dbman->field_exists($data->table, $data->column)) {
- $data->errors[] = get_string('invalidactivitysettingcolumn', 'block_workflow', $data->column);
- return $data;
- }
-
- // Shift off the 'to' component.
- $to = array_shift($line);
- if ($to !== 'to') {
- $data->errors[] = get_string('invalidsyntaxmissingto', 'block_workflow');
- return $data;
- }
-
- // What we'll be setting it to.
- $data->value = array_shift($line);
-
- return $data;
- }
+ /**
+ * Parses the provided arguments and processes them based on the given step and state.
+ *
+ * @param array $args The arguments to be parsed.
+ * @param mixed $step The step to be processed.
+ * @param mixed|null $state Optional. The current state, if any. Defaults to null.
+ * @return void
+ */
public function execute($args, $state) {
global $DB;
@@ -93,7 +50,7 @@ public function execute($args, $state) {
$column = $data->column;
$record->$column = $data->value;
- $existing = $DB->get_record($data->table, array('id' => $data->cm->instance));
+ $existing = $DB->get_record($data->table, ['id' => $data->cm->instance]);
$record->id = $existing->id;
$DB->update_record($data->table, $record);
}
diff --git a/classes/command_setactivityvisibility.php b/classes/command_setactivityvisibility.php
index c0b4ad9..8978d27 100644
--- a/classes/command_setactivityvisibility.php
+++ b/classes/command_setactivityvisibility.php
@@ -32,9 +32,17 @@
*
*/
class block_workflow_command_setactivityvisibility extends block_workflow_command {
+ /**
+ * Parses the provided arguments and processes them based on the given step and state.
+ *
+ * @param array $args The arguments to be parsed.
+ * @param object $step The step object associated with the workflow.
+ * @param object|null $state Optional. The current state object, if available.
+ * @return stdClass The result of the parsing process.
+ */
public function parse($args, $step, $state = null) {
$data = new stdClass();
- $data->errors = array();
+ $data->errors = [];
// Check that this step workflow relatees to an activity.
if (!parent::is_activity($step->workflow())) {
@@ -61,6 +69,14 @@ public function parse($args, $step, $state = null) {
return $data;
}
+
+ /**
+ * Executes the command to set activity visibility.
+ *
+ * @param array $args Arguments required for the command execution.
+ * @param mixed $state The current state or context in which the command is executed.
+ * @return void
+ */
public function execute($args, $state) {
global $CFG;
require_once($CFG->dirroot . '/course/lib.php');
diff --git a/classes/command_setcoursevisibility.php b/classes/command_setcoursevisibility.php
index b8ab312..57dec8b 100644
--- a/classes/command_setcoursevisibility.php
+++ b/classes/command_setcoursevisibility.php
@@ -32,9 +32,18 @@
*
*/
class block_workflow_command_setcoursevisibility extends block_workflow_command {
+
+ /**
+ * Parses the provided arguments to set the course visibility.
+ *
+ * @param string $args Arguments required for parsing the command.
+ * @param object $step The current step in the workflow process.
+ * @param ?object $state Optional state information for the workflow.
+ * @return stdClass The result of the parsing operation.
+ */
public function parse($args, $step, $state = null) {
$data = new stdClass();
- $data->errors = array();
+ $data->errors = [];
// Check that this step workflow relatees to an activity.
if (!parent::is_course($step->workflow())) {
@@ -57,6 +66,13 @@ public function parse($args, $step, $state = null) {
return $data;
}
+ /**
+ * Executes the command to set the course visibility.
+ *
+ * @param string $args Arguments required for the command execution.
+ * @param object $state Current state or context for the command.
+ * @return void
+ */
public function execute($args, $state) {
global $DB;
$data = $this->parse($args, $state->step(), $state);
diff --git a/classes/command_setgradeitemvisibility.php b/classes/command_setgradeitemvisibility.php
index 5b5d9ec..ff96818 100644
--- a/classes/command_setgradeitemvisibility.php
+++ b/classes/command_setgradeitemvisibility.php
@@ -39,9 +39,17 @@ class block_workflow_command_setgradeitemvisibility extends block_workflow_comma
/** @var int Constant for visible grade items */
const VISIBLE = 0;
- public function parse($args, $step, $state = null) {
+ /**
+ * Parses the given arguments to set the visibility of a grade item.
+ *
+ * @param array $args Arguments required for the command.
+ * @param object $step The current workflow step.
+ * @param object|null $state Optional state information.
+ * @return stdClass The result of the parsing operation.
+ */
+ public function parse($args, $step, $state = null): stdClass {
$data = new stdClass();
- $data->errors = array();
+ $data->errors = [];
// Check that this step workflow relates to an activity.
if (!parent::is_activity($step->workflow())) {
@@ -76,6 +84,13 @@ public function parse($args, $step, $state = null) {
return $data;
}
+ /**
+ * Executes the command to set the visibility of a grade item.
+ *
+ * @param mixed $args Arguments required to execute the command.
+ * @param mixed $state Current state or context for the command execution.
+ * @return void
+ */
public function execute($args, $state) {
global $CFG;
require_once($CFG->dirroot . '/lib/grade/grade_item.php');
@@ -84,8 +99,8 @@ public function execute($args, $state) {
return;
}
// Set grade_items visibility.
- $gradeitems = grade_item::fetch_all(array('courseid' => $data->cm->course, 'itemtype' => 'mod',
- 'itemmodule' => $data->cm->modname, 'iteminstance' => $data->cm->instance));
+ $gradeitems = grade_item::fetch_all(['courseid' => $data->cm->course, 'itemtype' => 'mod',
+ 'itemmodule' => $data->cm->modname, 'iteminstance' => $data->cm->instance]);
if ($gradeitems) {
foreach ($gradeitems as $gradeitem) {
if ($gradeitem->hidden === $data->visibility) {
diff --git a/classes/email.php b/classes/email.php
index 1b46ae7..35ed356 100644
--- a/classes/email.php
+++ b/classes/email.php
@@ -34,11 +34,22 @@
* @property-read string $subject The subject of the e-mail email
*/
class block_workflow_email {
+
+ /** @var int id from the database. */
public $id;
- public $message;
+
+ /** @var string identifier used to refer to this message. */
public $shortname;
+
+ /** @var string email subject. */
public $subject;
+ /** @var string text of the email. */
+ public $message;
+
+ /** @var int format of the message. One of the FORMAT_... constants. */
+ public $messageformat;
+
/**
* Constructor to obtain an e-mail template
*
@@ -60,13 +71,13 @@ public function __construct($emailid = null) {
* @param stdClass $email Database record to overload into the
* object instance
* @return The instantiated block_workflow_email object
- * @access private
*/
- private function _load($email) {
- $this->id = $email->id;
- $this->message = $email->message;
- $this->shortname = $email->shortname;
- $this->subject = $email->subject;
+ private function load($email) {
+ $this->id = $email->id;
+ $this->shortname = $email->shortname;
+ $this->subject = $email->subject;
+ $this->message = $email->message;
+ $this->messageformat = $email->messageformat;
return $this;
}
@@ -76,13 +87,13 @@ private function _load($email) {
* @return array The list of available settings
*/
public function expected_settings() {
- return array(
+ return [
'id',
'message',
'messageformat',
'shortname',
- 'subject'
- );
+ 'subject',
+ ];
}
/**
@@ -94,11 +105,11 @@ public function expected_settings() {
*/
public function load_email_id($id) {
global $DB;
- $email = $DB->get_record('block_workflow_emails', array('id' => $id));
+ $email = $DB->get_record('block_workflow_emails', ['id' => $id]);
if (!$email) {
throw new block_workflow_invalid_email_exception(get_string('invalidid', 'block_workflow'));
}
- return $this->_load($email);
+ return $this->load($email);
}
/**
@@ -109,11 +120,11 @@ public function load_email_id($id) {
*/
public function load_email_shortname($shortname) {
global $DB;
- $email = $DB->get_record('block_workflow_emails', array('shortname' => $shortname));
+ $email = $DB->get_record('block_workflow_emails', ['shortname' => $shortname]);
if (!$email) {
return false;
}
- return $this->_load($email);
+ return $this->load($email);
}
/**
@@ -165,8 +176,8 @@ public static function load_emails() {
FROM {block_workflow_emails} emails
ORDER BY shortname ASC
";
- $params = array('email1' => '%email%', 'email2' => '%email%', 'email3' => '%email%',
- 'to1' => '%to%', 'to2' => '%to%', 'to3' => '%to%');
+ $params = ['email1' => '%email%', 'email2' => '%email%', 'email3' => '%email%',
+ 'to1' => '%to%', 'to2' => '%to%', 'to3' => '%to%'];
return $DB->get_records_sql($sql, $params);
}
@@ -188,7 +199,7 @@ public function create($email) {
}
// Check whether this shortname is already in use.
- if ($DB->get_record('block_workflow_emails', array('shortname' => $email->shortname))) {
+ if ($DB->get_record('block_workflow_emails', ['shortname' => $email->shortname])) {
$transaction->rollback(new block_workflow_invalid_email_exception('shortnameinuse', 'block_workflow'));
}
@@ -239,7 +250,7 @@ public function update($data) {
// Check whether this shortname is already in use.
if (isset($data->shortname) &&
- ($id = $DB->get_field('block_workflow_emails', 'id', array('shortname' => $data->shortname)))) {
+ ($id = $DB->get_field('block_workflow_emails', 'id', ['shortname' => $data->shortname]))) {
if ($id != $data->id) {
$transaction->rollback(new block_workflow_invalid_email_exception('shortnameinuse', 'block_workflow'));
}
@@ -301,7 +312,7 @@ public function delete() {
// First check that we can delete this.
$this->require_deletable();
- $DB->delete_records('block_workflow_emails', array('id' => $this->id));
+ $DB->delete_records('block_workflow_emails', ['id' => $this->id]);
}
/**
@@ -321,22 +332,22 @@ public function used_count() {
$sql = "SELECT activescripts.onactivescript AS script
FROM {block_workflow_steps} activescripts
WHERE " . $DB->sql_like('activescripts.onactivescript', '?', false);
- $activescripts = $DB->get_records_sql($sql, array('%email%' . $this->shortname . '%to%'));
- $count += $this->_used_count($activescripts);
+ $activescripts = $DB->get_records_sql($sql, ['%email%' . $this->shortname . '%to%']);
+ $count += $this->handle_used_count($activescripts);
// Count the uses in the extranotifyscripts.
$sql = "SELECT extranotifyscripts.onextranotifyscript AS script
FROM {block_workflow_steps} extranotifyscripts
WHERE " . $DB->sql_like('extranotifyscripts.onextranotifyscript', '?', false);
- $extranotifyscripts = $DB->get_records_sql($sql, array('%email%' . $this->shortname . '%to%'));
- $count += $this->_used_count($extranotifyscripts);
+ $extranotifyscripts = $DB->get_records_sql($sql, ['%email%' . $this->shortname . '%to%']);
+ $count += $this->handle_used_count($extranotifyscripts);
// Count the uses in the completescripts.
$sql = "SELECT completescripts.oncompletescript AS script
FROM {block_workflow_steps} completescripts
WHERE " . $DB->sql_like('completescripts.oncompletescript', '?', false);
- $completescripts = $DB->get_records_sql($sql, array('%email%' . $this->shortname . '%to%'));
- $count += $this->_used_count($completescripts);
+ $completescripts = $DB->get_records_sql($sql, ['%email%' . $this->shortname . '%to%']);
+ $count += $this->handle_used_count($completescripts);
// Return the tital usage count.
return $count;
@@ -348,7 +359,7 @@ public function used_count() {
* @param array $scripts An array of stdClass objects with a script value
* @return integer The number of times the template is in use
*/
- private function _used_count($scripts) {
+ private function handle_used_count($scripts) {
// Keep track of the count.
$count = 0;
diff --git a/classes/event/email_sent_status.php b/classes/event/email_sent_status.php
new file mode 100644
index 0000000..d0fec86
--- /dev/null
+++ b/classes/event/email_sent_status.php
@@ -0,0 +1,152 @@
+.
+
+namespace block_workflow\event;
+
+/**
+ * This event is triggered when we want to sent an email in workflow.
+ *
+ * @property-read array $other {
+ * Extra information about the event.
+ *
+ * - int stepid: The ID of the step which has its status changed.
+ * - int stepstateid: The ID of the this state-change.
+ * - int workflowid: The ID of the workflow this step is part of.
+ * - int timestamp: The timestamp of when the state-change occurred
+ * (same timestamp as written to the state_change table)
+ * - string stepname: The name of the step which has its status changed.
+ * - string workflowname: The name of the workflow this step is part of.
+ * - string error the error message when the email is not sent.
+ *
+ * @package block_workflow
+ * @copyright 2025 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Class representing a user in the system.
+ */
+class email_sent_status extends \core\event\base {
+
+ /**
+ * Init method.
+ *
+ * @return void
+ */
+ protected function init() {
+ $this->data['objecttable'] = 'block_workflow_steps';
+ $this->data['crud'] = 'r';
+ $this->data['edulevel'] = self::LEVEL_OTHER;
+ }
+
+ /**
+ * Convenience factory-method to create an event from a step_state object.
+ *
+ * @param \block_workflow_step_state $stepstate The step-state with the data
+ * to create the event from.
+ * @param string|null $error the error message when the email is not sent.
+ * @return \core\event\base
+ */
+ public static function create_from_step_state(\block_workflow_step_state $stepstate, ?string $error = null) {
+ return self::create([
+ 'context' => $stepstate->context(),
+ 'objectid' => $stepstate->stepid,
+ 'other' => [
+ 'stepid' => $stepstate->stepid,
+ 'stepstateid' => $stepstate->id,
+ 'workflowid' => $stepstate->step()->workflowid,
+ 'timestamp' => $stepstate->timemodified,
+ 'stepname' => $stepstate->step()->name,
+ 'workflowname' => $stepstate->step()->workflow()->name,
+ 'error' => $error,
+ ],
+ ]);
+ }
+
+ /**
+ * Returns localised general event name.
+ *
+ * @return string
+ */
+ public static function get_name() {
+ return get_string('eventworkflownotification', 'block_workflow');
+ }
+
+ /**
+ * Returns non-localised event description with id's for admin use only.
+ * (Note: These texts are not stored in the database, but read every
+ * time the log is shown, so they must be backwards compatible).
+ *
+ * @return string
+ */
+ public function get_description() {
+ if (!$this->other['error']) {
+ return "The email was successfully sent to user with id '$this->userid' in " .
+ "'" . $this->other['stepname'] . "'" . " (id = " . $this->other['stepid'] . ").";
+ } else {
+ return "The email to user with id '$this->userid' failed in " .
+ "'" . $this->other['stepname'] . "'" . " (id = " . $this->other['stepid'] . ")." .
+ ' Error: ' . $this->other['error'];
+ }
+
+ }
+
+ /**
+ * Returns a Moodle URL where the event can be observed afterwards.
+ * Can be null, if no valid location is present.
+ *
+ * @return null|\moodle_url
+ */
+ public function get_url() {
+ return new \moodle_url('/blocks/workflow/overview.php',
+ ['contextid' => $this->contextid, 'workflowid' => $this->other['workflowid']]);
+ }
+
+ /**
+ * Custom validation.
+ *
+ * Here we check that the extra custom fields for this events
+ * (described in the class phpdoc comment) were actually given as
+ * parameters to the event when it was triggered.
+ */
+ protected function validate_data() {
+ parent::validate_data();
+
+ if (!isset($this->other['stepid'])) {
+ throw new \coding_exception('The \'stepid\' value must be set in \'other\' of the event.');
+ }
+
+ if (!isset($this->other['stepstateid'])) {
+ throw new \coding_exception('The \'stepstateid\' value must be set in \'other\' of the event.');
+ }
+
+ if (!isset($this->other['workflowid'])) {
+ throw new \coding_exception('The \'workflowid\' value must be set in \'other\' of the event.');
+ }
+
+ if (!isset($this->other['timestamp'])) {
+ throw new \coding_exception('The \'timestamp\' value must be set in \'other\' of the event.');
+ }
+
+ if (!isset($this->other['stepname'])) {
+ throw new \coding_exception('The \'stepname\' value must be set in \'other\' of the event.');
+ }
+
+ if (!isset($this->other['workflowname'])) {
+ throw new \coding_exception('The \'workflowname\' value must be set in \'other\' of the event.');
+ }
+ }
+}
diff --git a/classes/event/step_aborted.php b/classes/event/step_aborted.php
index 4cf06d5..1815dc4 100644
--- a/classes/event/step_aborted.php
+++ b/classes/event/step_aborted.php
@@ -41,6 +41,11 @@
*/
class step_aborted extends \core\event\base {
+ /**
+ * Init method.
+ *
+ * @return void
+ */
protected function init() {
$this->data['objecttable'] = 'block_workflow_steps';
$this->data['crud'] = 'u';
@@ -64,8 +69,8 @@ public static function create_from_step_state(\block_workflow_step_state $stepst
'workflowid' => $stepstate->step()->workflowid,
'timestamp' => $stepstate->timemodified,
'stepname' => $stepstate->step()->name,
- 'workflowname' => $stepstate->step()->workflow()->name
- ]
+ 'workflowname' => $stepstate->step()->workflow()->name,
+ ],
]);
}
diff --git a/classes/event/step_activated.php b/classes/event/step_activated.php
index 9e5ead0..882a726 100644
--- a/classes/event/step_activated.php
+++ b/classes/event/step_activated.php
@@ -42,6 +42,11 @@
*/
class step_activated extends \core\event\base {
+ /**
+ * Init method.
+ *
+ * @return void
+ */
protected function init() {
$this->data['objecttable'] = 'block_workflow_steps';
$this->data['crud'] = 'u';
@@ -68,8 +73,8 @@ public static function create_from_step_state(\block_workflow_step_state $stepst
'timestamp' => $stepstate->timemodified,
'stepname' => $stepstate->step()->name,
'workflowname' => $stepstate->step()->workflow()->name,
- 'initial' => $initial
- ]
+ 'initial' => $initial,
+ ],
]);
}
diff --git a/classes/event/step_completed.php b/classes/event/step_completed.php
index fe20973..9563216 100644
--- a/classes/event/step_completed.php
+++ b/classes/event/step_completed.php
@@ -41,6 +41,11 @@
*/
class step_completed extends \core\event\base {
+ /**
+ * Init method.
+ *
+ * @return void
+ */
protected function init() {
$this->data['objecttable'] = 'block_workflow_steps';
$this->data['crud'] = 'u';
@@ -63,8 +68,8 @@ public static function create_from_step_state(\block_workflow_step_state $stepst
'workflowid' => $stepstate->step()->workflowid,
'timestamp' => $stepstate->timemodified,
'stepname' => $stepstate->step()->name,
- 'workflowname' => $stepstate->step()->workflow()->name
- ]
+ 'workflowname' => $stepstate->step()->workflow()->name,
+ ],
]);
}
diff --git a/classes/event/step_extra_notification_processed.php b/classes/event/step_extra_notification_processed.php
index dc9729e..305a804 100644
--- a/classes/event/step_extra_notification_processed.php
+++ b/classes/event/step_extra_notification_processed.php
@@ -43,6 +43,11 @@
*/
class step_extra_notification_processed extends \core\event\base {
+ /**
+ * Init method.
+ *
+ * @return void
+ */
protected function init() {
$this->data['objecttable'] = 'block_workflow_steps';
$this->data['crud'] = 'u';
@@ -65,8 +70,8 @@ public static function create_from_step_state(\block_workflow_step_state $stepst
'workflowid' => $stepstate->step()->workflowid,
'timestamp' => $stepstate->timemodified,
'stepname' => $stepstate->step()->name,
- 'workflowname' => $stepstate->step()->workflow()->name
- ]
+ 'workflowname' => $stepstate->step()->workflow()->name,
+ ],
]);
}
diff --git a/classes/event/todo_triggered.php b/classes/event/todo_triggered.php
index 0876f7e..004bf32 100644
--- a/classes/event/todo_triggered.php
+++ b/classes/event/todo_triggered.php
@@ -43,6 +43,11 @@
*/
class todo_triggered extends \core\event\base {
+ /**
+ * Init method.
+ *
+ * @return void
+ */
protected function init() {
$this->data['objecttable'] = 'block_workflow_step_todos';
$this->data['crud'] = 'u';
@@ -70,8 +75,8 @@ public static function create_from_step_state(\block_workflow_step_state $stepst
'completed' => $completed,
'stepname' => $stepstate->step()->name,
'todoname' => $todo->task,
- 'workflowname' => $stepstate->step()->workflow()->name
- ]
+ 'workflowname' => $stepstate->step()->workflow()->name,
+ ],
]);
}
diff --git a/classes/external/external_api_base.php b/classes/external/external_api_base.php
new file mode 100644
index 0000000..70ef352
--- /dev/null
+++ b/classes/external/external_api_base.php
@@ -0,0 +1,54 @@
+.
+
+namespace block_workflow\external;
+
+use core_external\external_api;
+use core_external\external_function_parameters;
+use block_workflow_step_state;
+use block_workflow_ajax_exception;
+
+defined('MOODLE_INTERNAL') || die();
+global $CFG;
+require_once($CFG->dirroot . '/blocks/workflow/locallib.php');
+
+/**
+ * Overriding the api base class for common functions.
+ *
+ * @package block_workflow
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+abstract class external_api_base extends external_api {
+
+ /**
+ * Handle security check when we call the webservice.
+ *
+ * @param array $params
+ * @param external_function_parameters $decription
+ * @return array [$state, $validatedparams] the current state and the validated params.
+ */
+ public static function handle_security_check(array $params, external_function_parameters $decription): array {
+ $validatedparams = self::validate_parameters($decription, $params);
+ $state = new block_workflow_step_state($validatedparams['stateid']);
+ if (!block_workflow_can_make_changes($state)) {
+ throw new block_workflow_ajax_exception(get_string('notallowedtodothisstep', 'block_workflow'));
+ }
+ [$context, $course, $cm] = get_context_info_array($state->contextid);
+ self::validate_context($context);
+ return [$state, $validatedparams];
+ }
+}
diff --git a/classes/external/finish_step.php b/classes/external/finish_step.php
new file mode 100644
index 0000000..a5c5053
--- /dev/null
+++ b/classes/external/finish_step.php
@@ -0,0 +1,97 @@
+.
+
+namespace block_workflow\external;
+
+use core_external\external_function_parameters;
+use core_external\external_value;
+use core_external\external_single_structure;
+use block_workflow_workflow;
+
+/**
+ * Finish step webservice.
+ *
+ * @package block_workflow
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class finish_step extends external_api_base {
+
+ /**
+ * Returns description of method parameters
+ *
+ * @return external_function_parameters
+ */
+ public static function execute_parameters(): external_function_parameters {
+ return new external_function_parameters([
+ 'stateid' => new external_value(PARAM_INT, 'The ID of the step_state to load', VALUE_REQUIRED),
+ 'text' => new external_value(PARAM_RAW, 'The text of the new comment', VALUE_REQUIRED),
+ 'format' => new external_value(PARAM_INT, 'The format of the new comment', VALUE_REQUIRED),
+ ]);
+ }
+
+ /**
+ * Finish the step.
+ *
+ * @param int $stateid the id of the current state
+ * @param string $text The text of the new comment
+ * @param int $format The format of the new comment
+ * @return array of The next state or false if there is none
+ */
+ public static function execute(int $stateid, string $text, int $format): array {
+ global $PAGE;
+ [$state, $params] = self::handle_security_check(['stateid' => $stateid, 'text' => $text, 'format' => $format],
+ self::execute_parameters());
+ $renderer = $PAGE->get_renderer('block_workflow');
+
+ // Retrieve the next step.
+ $newstate = $state->finish_step($params['text'], $params['format']);
+ $canview = ($newstate) ? has_capability('block/workflow:view', $newstate->context()) : false;
+
+ if ($newstate && ($canview || block_workflow_can_make_changes($newstate))) {
+ // There is a next possible state, and the current user may view and/or work on it.
+ $result['response'] = $renderer->block_display($newstate, true);
+ $result['stateid'] = $newstate->id;
+ } else if ($newstate) {
+ // There is a new step, but this user can't view it, and can't work on it ...
+ $result['response'] = $renderer->block_display_step_complete_confirmation();
+ } else {
+ // Last step has been reached, if permitted retrieve the list of workflows.
+ $workflows = new block_workflow_workflow();
+ $previous = $workflows->load_context_workflows($state->contextid);
+ $canadd = has_capability('block/workflow:manage', $state->context());
+ $appliesto = $state->step()->workflow()->appliesto;
+ $addableworkflows = block_workflow_workflow::available_workflows($appliesto);
+ $result['listworkflows'] = $canadd && $addableworkflows;
+ $result['response'] = $renderer->block_display_no_more_steps(
+ $state->contextid, $canadd, $addableworkflows, $previous);
+ }
+ return $result;
+ }
+
+ /**
+ * Describe the return structure of the external service.
+ *
+ * @return external_single_structure
+ */
+ public static function execute_returns(): external_single_structure {
+ return new external_single_structure([
+ 'response' => new external_value(PARAM_RAW),
+ 'stateid' => new external_value(PARAM_INT, '', VALUE_OPTIONAL),
+ 'listworkflows' => new external_value(PARAM_BOOL, '', VALUE_OPTIONAL),
+ ]);
+ }
+}
diff --git a/classes/external/get_step_state_comment.php b/classes/external/get_step_state_comment.php
new file mode 100644
index 0000000..f8216d3
--- /dev/null
+++ b/classes/external/get_step_state_comment.php
@@ -0,0 +1,67 @@
+.
+
+namespace block_workflow\external;
+
+use core_external\external_function_parameters;
+use core_external\external_single_structure;
+use core_external\external_value;
+use core_external\util;
+
+/**
+ * Get step_state comment web service
+ *
+ * @package block_workflow
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class get_step_state_comment extends external_api_base {
+
+ /**
+ * Returns description of method parameters
+ *
+ * @return external_function_parameters
+ */
+ public static function execute_parameters(): external_function_parameters {
+ return new external_function_parameters([
+ 'stateid' => new external_value(PARAM_INT, 'The ID of the step_state to load', VALUE_REQUIRED),
+ ]);
+ }
+
+ /**
+ * Get comment from stateid
+ *
+ * @param int $stateid the id of the current state
+ * @return array of newly created comment.
+ */
+ public static function execute(int $stateid): array {
+ // Now security checks.
+ [$state, $params] = self::handle_security_check(['stateid' => $stateid], self::execute_parameters());
+ $result['response'] = util::format_text($state->comment, FORMAT_HTML, $state->contextid)[0];
+ return $result;
+ }
+
+ /**
+ * Describe the return structure of the external service.
+ *
+ * @return external_single_structure
+ */
+ public static function execute_returns(): external_single_structure {
+ return new external_single_structure([
+ 'response' => new external_value(PARAM_RAW),
+ ]);
+ }
+}
diff --git a/classes/external/update_step_state_comment.php b/classes/external/update_step_state_comment.php
new file mode 100644
index 0000000..fcbf0ea
--- /dev/null
+++ b/classes/external/update_step_state_comment.php
@@ -0,0 +1,71 @@
+.
+
+namespace block_workflow\external;
+
+use core_external\external_function_parameters;
+use core_external\external_value;
+use core_external\external_single_structure;
+
+/**
+ * Save/update the comment for the currently loaded step_state
+ *
+ * @package block_workflow
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class update_step_state_comment extends external_api_base {
+
+ /**
+ * Returns description of method parameters
+ *
+ * @return external_function_parameters
+ */
+ public static function execute_parameters(): external_function_parameters {
+ return new external_function_parameters([
+ 'stateid' => new external_value(PARAM_INT, 'The ID of the step_state to load', VALUE_REQUIRED),
+ 'newcomment' => new external_value(PARAM_RAW, 'The text of the new comment', VALUE_REQUIRED),
+ 'newcommentformat' => new external_value(PARAM_INT, 'The format of the new comment', VALUE_REQUIRED),
+ ]);
+ }
+
+ /**
+ * Update the comment for the currently loaded step_state
+ *
+ * @param int $stateid the id of the current state
+ * @param string $newcomment The text of the new comment
+ * @param int $newcommentformat The format of the new comment
+ * @return array of newly created comment
+ */
+ public static function execute(int $stateid, string $newcomment, int $newcommentformat): array {
+ [$state, $params] = self::handle_security_check(['stateid' => $stateid, 'newcomment' => $newcomment,
+ 'newcommentformat' => $newcommentformat], self::execute_parameters());
+ $state->update_comment($params['newcomment'], $params['newcommentformat']);
+ $result['response'] = shorten_text($newcomment, BLOCK_WORKFLOW_MAX_COMMENT_LENGTH);
+ return $result;
+ }
+
+ /**
+ * Describe the return structure of the external service.
+ *
+ * @return external_single_structure
+ */
+ public static function execute_returns(): external_single_structure {
+ return new external_single_structure([
+ 'response' => new external_value(PARAM_RAW),
+ ]);
+ }
+}
diff --git a/classes/external/update_step_state_task_state.php b/classes/external/update_step_state_task_state.php
new file mode 100644
index 0000000..d680c96
--- /dev/null
+++ b/classes/external/update_step_state_task_state.php
@@ -0,0 +1,69 @@
+.
+
+namespace block_workflow\external;
+
+use core_external\external_function_parameters;
+use core_external\external_single_structure;
+use core_external\external_value;
+
+/**
+ * Update step_state done webservice.
+ *
+ * @package block_workflow
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class update_step_state_task_state extends external_api_base {
+
+ /**
+ * Returns description of method parameters
+ *
+ * @return external_function_parameters
+ */
+ public static function execute_parameters(): external_function_parameters {
+ return new external_function_parameters([
+ 'stateid' => new external_value(PARAM_INT, 'The ID of the step_state to load', VALUE_REQUIRED),
+ 'todoid' => new external_value(PARAM_INT, 'The ID of the task', VALUE_REQUIRED),
+ 'check' => new external_value(PARAM_BOOL, 'The todo being check/uncheck', VALUE_REQUIRED),
+ ]);
+ }
+
+ /**
+ * Toggle the completed status of a task for a step state
+ *
+ * @param int $stateid the id of the current state
+ * @param int $todoid The ID of the task
+ * @return array of the new state of the task
+ */
+ public static function execute(int $stateid, int $todoid, bool $check): array {
+ [$state, $params] = self::handle_security_check(['stateid' => $stateid, 'todoid' => $todoid, 'check' => $check],
+ self::execute_parameters());
+ $result['response'] = $state->todo_toggle($params['todoid'], $params['check']);
+ return $result;
+ }
+
+ /**
+ * Describe the return structure of the external service.
+ *
+ * @return external_single_structure
+ */
+ public static function execute_returns(): external_single_structure {
+ return new external_single_structure([
+ 'response' => new external_value(PARAM_BOOL),
+ ]);
+ }
+}
diff --git a/classes/local/forms/comment_form.php b/classes/local/forms/comment_form.php
new file mode 100644
index 0000000..6cc7540
--- /dev/null
+++ b/classes/local/forms/comment_form.php
@@ -0,0 +1,47 @@
+.
+
+namespace block_workflow\local\forms;
+
+// Make sure this isn't being directly accessed.
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->libdir . '/formslib.php');
+
+/**
+ * Block workflow comment form.
+ *
+ * @package block_workflow
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class comment_form extends \moodleform {
+
+ #[\Override]
+ protected function definition() {
+ $mform = $this->_form;
+ $editoroptions = [
+ 'maxfiles' => 0,
+ 'autosave' => false,
+ ];
+ // Tiny need the pre-fix 'id_'.
+ $mform->addElement('editor', 'comment_editor',
+ get_string('commentlabel', 'block_workflow'),
+ ['id' => 'id_wkf-comment-editor'], $editoroptions);
+ $mform->setType('commentext', PARAM_RAW);
+ $mform->addElement("button", 'wfk-submit', $this->_customdata['inputLabel']);
+ }
+}
diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php
index 54808aa..e79a7d1 100644
--- a/classes/privacy/provider.php
+++ b/classes/privacy/provider.php
@@ -24,11 +24,11 @@
namespace block_workflow\privacy;
-use \core_privacy\local\request\approved_contextlist;
-use \core_privacy\local\request\contextlist;
-use \core_privacy\local\request\writer;
-use \core_privacy\local\request\helper;
-use \core_privacy\local\metadata\collection;
+use core_privacy\local\request\approved_contextlist;
+use core_privacy\local\request\contextlist;
+use core_privacy\local\request\writer;
+use core_privacy\local\request\helper;
+use core_privacy\local\metadata\collection;
use core_privacy\local\request\approved_userlist;
use core_privacy\local\request\userlist;
@@ -52,7 +52,7 @@ class provider implements
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
- public static function get_metadata(collection $collection) : collection {
+ public static function get_metadata(collection $collection): collection {
// The 'block_workflow_state_changes' table stores the state change by user.
$collection->add_database_table('block_workflow_state_changes', [
'userid' => 'privacy:metadata:block_workflow_state_changes:userid',
@@ -160,7 +160,7 @@ public static function export_user_data(approved_contextlist $contextlist) {
ORDER BY step.id ASC";
$params = [
'stepstatecontextid' => $context->id,
- 'statechangesuserid' => $user->id
+ 'statechangesuserid' => $user->id,
];
$rs = $DB->get_recordset_sql($sql, $params);
@@ -172,7 +172,7 @@ public static function export_user_data(approved_contextlist $contextlist) {
'description' => $rec->description,
'stepname' => $rec->stepname,
'userid' => self::you_or_somebody_else($rec->userid, $user),
- 'newstate' => $rec->newstate
+ 'newstate' => $rec->newstate,
];
if (empty($contextdata->statechangedata)) {
@@ -196,7 +196,7 @@ public static function export_user_data(approved_contextlist $contextlist) {
$params = [
'statescontextid' => $context->id,
- 'doneuserid' => $user->id
+ 'doneuserid' => $user->id,
];
$rs = $DB->get_recordset_sql($sql, $params);
@@ -206,7 +206,7 @@ public static function export_user_data(approved_contextlist $contextlist) {
$donedata = [
'stepname' => $rec->stepname,
'taskdone' => $rec->taskdone,
- 'userid' => self::you_or_somebody_else($rec->userid, $user)
+ 'userid' => self::you_or_somebody_else($rec->userid, $user),
];
if (empty($contextdata->tododonedata)) {
@@ -265,7 +265,7 @@ public static function delete_data_for_all_users_in_context(\context $context) {
$params = [
'statescontextid' => $context->id,
- 'adminuserid' => get_admin()->id
+ 'adminuserid' => get_admin()->id,
];
// Keep all the data but anonymise with the admin user id.
@@ -320,7 +320,7 @@ protected static function delete_user_data($context, $userid) {
$params = [
'statescontextid' => $context->id,
'userid' => $userid,
- 'adminuserid' => get_admin()->id
+ 'adminuserid' => get_admin()->id,
];
// Delete block_workflow_todo_done owned by user.
diff --git a/classes/step.php b/classes/step.php
index 61b973a..6f9e8a8 100644
--- a/classes/step.php
+++ b/classes/step.php
@@ -45,27 +45,105 @@
* @property-read string $onextranotifyscript The script for processing which email notification should be sent.
*/
class block_workflow_step {
+ /**
+ * Number of days before the quiz starts.
+ */
const DAYS_BEFORE_QUIZ = -10;
+
+ /**
+ * Number of days after the quiz ends.
+ */
const DAYS_AFTER_QUIZ = 10;
+
+ /**
+ * Number of days before the course starts.
+ */
const DAYS_BEFORE_COURSE = -120;
+
+ /**
+ * Number of days after the course ends.
+ */
const DAYS_AFTER_COURSE = 30;
- private $step = null;
- private $workflow = null;
- private $todos = null;
+ /**
+ * @var mixed|null $step The current step of the workflow. Defaults to null.
+ */
+ private $step;
+
+ /**
+ * @var mixed|null $workflow The workflow associated with the step. Defaults to null.
+ */
+ private $workflow;
+
+ /**
+ * @var mixed|null $todos The list of tasks or actions to be completed in this step. Defaults to null.
+ */
+ private $todos;
+ /**
+ * @var int $id The unique identifier for the step.
+ */
public $id;
+
+ /**
+ * @var int $workflowid The ID of the workflow to which this step belongs.
+ */
public $workflowid;
+
+ /**
+ * @var int $stepno The step number in the workflow sequence.
+ */
public $stepno;
+
+ /**
+ * @var string $name The name of the step.
+ */
public $name;
+
+ /**
+ * @var string $instructions The instructions for completing the step.
+ */
public $instructions;
+
+ /**
+ * @var int $instructionsformat The format of the instructions (e.g., plain text, HTML).
+ */
public $instructionsformat;
+
+ /**
+ * @var string|null $onactivescript The script to execute when the step becomes active. Defaults to null.
+ */
public $onactivescript;
+
+ /**
+ * @var string|null $oncompletescript The script to execute when the step is completed. Defaults to null.
+ */
public $oncompletescript;
+
+ /**
+ * @var bool $autofinish Whether the step should automatically finish. Defaults to false.
+ */
public $autofinish;
+
+ /**
+ * @var int|null $autofinishoffset The time offset (in seconds) for automatically finishing the step. Defaults to null.
+ */
public $autofinishoffset;
+
+ /**
+ * @var string|null $extranotify Additional notification settings for the step. Defaults to null.
+ */
public $extranotify;
+
+ /**
+ * @var int|null $extranotifyoffset The time offset (in seconds) for sending extra notifications. Defaults to null.
+ */
public $extranotifyoffset;
+
+
+ /**
+ * @var mixed $onextranotifyscript Holds the extra notification script associated with the workflow step.
+ */
public $onextranotifyscript;
/**
@@ -89,9 +167,8 @@ public function __construct($stepid = null) {
* @param stdClass $step Database record to overload into the
* object instance
* @return The instantiated block_workflow_step object
- * @access private
*/
- private function _load($step) {
+ private function load($step) {
$this->id = $step->id;
$this->workflowid = $step->workflowid;
$this->stepno = $step->stepno;
@@ -115,7 +192,7 @@ private function _load($step) {
*/
public static function make($stepdata) {
$step = new block_workflow_step();
- $step->_load($stepdata);
+ $step->load($stepdata);
return $step;
}
@@ -125,7 +202,7 @@ public static function make($stepdata) {
* @return array The list of available settings
*/
public function expected_settings() {
- return array(
+ return [
'id',
'workflowid',
'stepno',
@@ -138,8 +215,8 @@ public function expected_settings() {
'autofinishoffset',
'extranotify',
'extranotifyoffset',
- 'onextranotifyscript'
- );
+ 'onextranotifyscript',
+ ];
}
/**
@@ -151,11 +228,11 @@ public function expected_settings() {
*/
public function load_step($stepid) {
global $DB;
- $step = $DB->get_record('block_workflow_steps', array('id' => $stepid));
+ $step = $DB->get_record('block_workflow_steps', ['id' => $stepid]);
if (!$step) {
throw new block_workflow_invalid_step_exception(get_string('noactiveworkflow', 'block_workflow'));
}
- return $this->_load($step);
+ return $this->load($step);
}
/**
@@ -169,11 +246,11 @@ public function load_step($stepid) {
public function load_workflow_stepno($workflowid, $stepno) {
global $DB;
$step = $DB->get_record('block_workflow_steps',
- array('workflowid' => $workflowid, 'stepno' => $stepno));
+ ['workflowid' => $workflowid, 'stepno' => $stepno]);
if (!$step) {
throw new block_workflow_invalid_step_exception(get_string('invalidworkflowstepno', 'block_workflow'));
}
- return $this->_load($step);
+ return $this->load($step);
}
/**
@@ -266,7 +343,7 @@ public function create_step($step, $beforeafter = 0) {
} else {
// Retrieve the stepno from the final step for this workflow.
$sql = 'SELECT stepno FROM {block_workflow_steps} WHERE workflowid = ? ORDER BY stepno DESC LIMIT 1';
- $step->stepno = $DB->get_field_sql($sql, array($step->workflowid));
+ $step->stepno = $DB->get_field_sql($sql, [$step->workflowid]);
if ($step->stepno) {
// If there's already a step on this workflow, add to that step number.
@@ -335,7 +412,6 @@ public function create_step($step, $beforeafter = 0) {
* no workflowid is specified, the step is placed within the same
* workflow as the source
* @return The newly created block_workflow_step object
- * @static
*/
public static function clone_step($srcid, $workflowid = null) {
global $DB;
@@ -400,7 +476,7 @@ public function delete() {
$transaction = $DB->start_delegated_transaction();
// Retrieve a list of the step_states.
- $states = $DB->get_records('block_workflow_step_states', array('stepid' => $this->id), null, 'id');
+ $states = $DB->get_records('block_workflow_step_states', ['stepid' => $this->id], null, 'id');
$statelist = array_map(function ($a) {
return $a->id;
}, $states);
@@ -412,7 +488,7 @@ public function delete() {
$DB->delete_records_list('block_workflow_todo_done', 'stepstateid', $statelist);
// Remove the states.
- $DB->delete_records('block_workflow_step_states', array('stepid' => $this->id));
+ $DB->delete_records('block_workflow_step_states', ['stepid' => $this->id]);
// Update the atengobacktostep setting for the workflow if required.
$workflow = $this->workflow();
@@ -422,7 +498,7 @@ public function delete() {
}
// Remove the step.
- $DB->delete_records('block_workflow_steps', array('id' => $this->id));
+ $DB->delete_records('block_workflow_steps', ['id' => $this->id]);
// Now that the step has been removed, renumber the remaining step numbers.
$workflow->renumber_steps();
@@ -547,7 +623,7 @@ public function set_workflow($workflowid) {
public static function is_step_in_use($stepid) {
global $DB;
return $DB->count_records('block_workflow_step_states',
- array('stepid' => $stepid, 'state' => BLOCK_WORKFLOW_STATE_ACTIVE));
+ ['stepid' => $stepid, 'state' => BLOCK_WORKFLOW_STATE_ACTIVE]);
}
/**
@@ -614,7 +690,7 @@ public function load_active_step($contextid) {
LEFT JOIN {block_workflow_steps} steps ON steps.id = state.stepid
WHERE state.contextid = ? AND state.state = ?';
- $step = $DB->get_record_sql($sql, array($contextid, BLOCK_WORKFLOW_STATE_ACTIVE));
+ $step = $DB->get_record_sql($sql, [$contextid, BLOCK_WORKFLOW_STATE_ACTIVE]);
if (!$step) {
throw new block_workflow_not_assigned_exception(get_string('noactiveworkflow', 'block_workflow'));
}
@@ -635,11 +711,11 @@ public function load_active_step($contextid) {
public static function parse_script($script) {
// Our return place-holder.
$return = new stdClass();
- $return->errors = array();
- $return->commands = array();
+ $return->errors = [];
+ $return->commands = [];
// Break the script into lines.
- $lines = preg_split('~[\r\n]+~', $script, null, PREG_SPLIT_NO_EMPTY);
+ $lines = preg_split('~[\r\n]+~', $script, -1, PREG_SPLIT_NO_EMPTY);
foreach ($lines as $line) {
$c = new stdClass();
@@ -780,7 +856,7 @@ public function process_script(block_workflow_step_state $state, $script) {
// This is a workaround for a limitation of the message_send system.
// This must be called outside of a transaction.
- block_workflow_command_email::message_send();
+ block_workflow_command_email::message_send($state);
}
/**
@@ -799,7 +875,7 @@ public function get_next_step() {
// Determine the stepid of the next step.
$stepid = $DB->get_field('block_workflow_steps', 'id',
- array('workflowid' => $this->workflowid, 'stepno' => ($this->stepno + 1)));
+ ['workflowid' => $this->workflowid, 'stepno' => ($this->stepno + 1)]);
if ($stepid) {
// If there is another step, return that step object.
@@ -914,7 +990,7 @@ public function roles($stepid = null) {
WHERE d.stepid = ?
ORDER BY r.shortname ASC';
- return role_fix_names($DB->get_records_sql($sql, array($stepid)));
+ return role_fix_names($DB->get_records_sql($sql, [$stepid]));
}
/**
@@ -927,8 +1003,8 @@ public function roles($stepid = null) {
*/
public function toggle_role($roleid) {
global $DB;
- if ($DB->get_record('block_workflow_step_doers', array('stepid' => $this->id, 'roleid' => $roleid))) {
- return $DB->delete_records('block_workflow_step_doers', array('roleid' => $roleid, 'stepid' => $this->id));
+ if ($DB->get_record('block_workflow_step_doers', ['stepid' => $this->id, 'roleid' => $roleid])) {
+ return $DB->delete_records('block_workflow_step_doers', ['roleid' => $roleid, 'stepid' => $this->id]);
} else {
$role = new stdClass();
$role->stepid = $this->id;
@@ -937,20 +1013,32 @@ public function toggle_role($roleid) {
}
}
+ /**
+ * Formats the instructions for the given context.
+ *
+ * @param context $context The context in which to format the instructions.
+ * @return string The formatted instructions.
+ */
public function format_instructions($context) {
- $replaces = array();
+ $replaces = [];
if ($context->contextlevel == CONTEXT_MODULE) {
$replaces['%%cmid%%'] = $context->instanceid;
}
$instructions = str_replace(array_keys($replaces), array_values($replaces), $this->instructions);
return format_text($instructions, $this->instructionsformat,
- array('noclean' => true, 'context' => $context));
+ ['noclean' => true, 'context' => $context]);
}
+ /**
+ * Returns the available autofinish options for the specified application context.
+ *
+ * @param mixed $appliesto The context or entity to which the autofinish options apply.
+ * @return array List of autofinish options.
+ */
public static function get_autofinish_options($appliesto) {
global $CFG, $DB;
- $options = array();
+ $options = [];
$options[''] = get_string('donotautomaticallyfinish', 'block_workflow');
if ($appliesto === 'course') {
// The string is stored in the database in the following format.
@@ -985,7 +1073,7 @@ public static function get_autofinish_options($appliesto) {
$days = self::get_list_of_days(0, 0);
}
- return array($options, $days);
+ return [$options, $days];
}
/**
@@ -1001,7 +1089,7 @@ public static function get_autofinish_options($appliesto) {
* @return object $days, array of strings
*/
private static function get_list_of_days($daysbefore, $dayafter) {
- $days = array();
+ $days = [];
$secondsinday = 24 * 60 * 60;
for ($count = $daysbefore; $count <= $dayafter; $count++) {
if ($count < 0) {
diff --git a/classes/step_state.php b/classes/step_state.php
index 6b64651..56150b5 100644
--- a/classes/step_state.php
+++ b/classes/step_state.php
@@ -41,17 +41,53 @@
* @property-read int $commentformat The format of the comment field
*/
class block_workflow_step_state {
+ /**
+ * @var ?int $step The current step of the workflow. Null if not set.
+ */
private $step = null;
+ /**
+ * @var ?array $todos The list of tasks or actions associated with the step. Null if not set.
+ */
private $todos = null;
+ /**
+ * @var int $id The unique identifier for the step state.
+ */
public $id;
+ /**
+ * @var int $stepid The ID of the workflow step associated with this state.
+ */
public $stepid;
+ /**
+ * @var int $contextid The context ID where this workflow step state is applied.
+ */
public $contextid;
+ /**
+ * @var string $state The current state of the workflow step (e.g., 'inprogress', 'completed').
+ */
public $state;
+ /**
+ * @var int $timemodified The timestamp of the last modification to this step state.
+ */
public $timemodified;
+ /**
+ * @var ?string $comment Optional comment associated with the step state.
+ */
public $comment;
+ /**
+ * @var int The format of the comment (e.g., plain text, HTML).
+ */
public $commentformat;
+ /**
+ * @var ?string occasionally, so that it can be used in messges, we need
+ * to store the comment from the previous step as well. (A bit hacky, but ...).
+ */
+ public $previouscomment = null;
+
+ /** @var ?int format of $previouscomment, if present. */
+ public $previouscommentformat = null;
+
/**
* Constructor to obtain a step_state
*
@@ -73,9 +109,8 @@ public function __construct($stateid = null) {
* @param stdClass $state Database record to overload into the
* object instance
* @return The instantiated block_workflow_step_state object
- * @access private
*/
- private function _load($state) {
+ private function load($state) {
$this->id = $state->id;
$this->stepid = $state->stepid;
$this->contextid = $state->contextid;
@@ -96,11 +131,11 @@ private function _load($state) {
*/
public function load_state($stateid) {
global $DB;
- $state = $DB->get_record('block_workflow_step_states', array('id' => $stateid));
+ $state = $DB->get_record('block_workflow_step_states', ['id' => $stateid]);
if (!$state) {
throw new block_workflow_exception(get_string('invalidstate', 'block_workflow'));
}
- return $this->_load($state);
+ return $this->load($state);
}
/**
@@ -111,12 +146,12 @@ public function load_state($stateid) {
*/
public function load_active_state($contextid) {
global $DB;
- $state = $DB->get_record('block_workflow_step_states', array(
- 'contextid' => $contextid, 'state' => BLOCK_WORKFLOW_STATE_ACTIVE));
+ $state = $DB->get_record('block_workflow_step_states',
+ ['contextid' => $contextid, 'state' => BLOCK_WORKFLOW_STATE_ACTIVE]);
if (!$state) {
return false;
}
- return $this->_load($state);
+ return $this->load($state);
}
/**
@@ -145,12 +180,11 @@ public function require_active_state($contextid) {
*/
public function load_context_step($contextid, $stepid) {
global $DB;
- $state = $DB->get_record('block_workflow_step_states', array(
- 'contextid' => $contextid, 'stepid' => $stepid));
+ $state = $DB->get_record('block_workflow_step_states', ['contextid' => $contextid, 'stepid' => $stepid]);
if (!$state) {
throw new block_workflow_not_assigned_exception(get_string('invalidstate', 'block_workflow'));
}
- return $this->_load($state);
+ return $this->load($state);
}
/**
@@ -233,7 +267,7 @@ public function change_status($newstatus) {
switch ($this->state) {
case BLOCK_WORKFLOW_STATE_ABORTED:
case BLOCK_WORKFLOW_STATE_COMPLETED:
- role_unassign_all(array('component' => 'block_workflow', 'itemid' => $this->id));
+ role_unassign_all(['component' => 'block_workflow', 'itemid' => $this->id]);
break;
default:
break;
@@ -273,7 +307,7 @@ public function change_status($newstatus) {
// This is a workaround for a limitation of the message_send system.
// This must be called outside of a transaction.
- block_workflow_command_email::message_send();
+ block_workflow_command_email::message_send($this);
// Return the updated step_state object.
return $this->load_state($this->id);
@@ -287,7 +321,7 @@ public function change_status($newstatus) {
* @return mixed The next state or false if there is none
*/
public function finish_step($newcomment, $newcommentformat) {
- global $DB, $USER;
+ global $DB;
$transaction = $DB->start_delegated_transaction();
// Update the comment.
@@ -316,7 +350,7 @@ public function finish_step($newcomment, $newcommentformat) {
$nextstate = new block_workflow_step_state($newstate->id);
}
- $nextstate->previouscomment = $this->comment; // Hack alert!
+ $nextstate->previouscomment = $this->comment;
$nextstate->previouscommentformat = $this->commentformat;
$nextstate->change_status(BLOCK_WORKFLOW_STATE_ACTIVE);
}
@@ -325,7 +359,7 @@ public function finish_step($newcomment, $newcommentformat) {
// This is a workaround for a limitation of the message_send system.
// This must be called outside of a transaction.
- block_workflow_command_email::message_send();
+ block_workflow_command_email::message_send($nextstep ? $nextstate : $this);
// Return the new state.
if ($nextstep) {
@@ -364,7 +398,7 @@ public function jump_to_step($contextid = null, $newstepid = null) {
// This is a workaround for a limitation of the message_send system.
// This must be called outside of a transaction.
- block_workflow_command_email::message_send();
+ block_workflow_command_email::message_send($state);
return;
}
@@ -400,7 +434,7 @@ public function jump_to_step($contextid = null, $newstepid = null) {
// This is a workaround for a limitation of the message_send system.
// This must be called outside of a transaction.
- block_workflow_command_email::message_send();
+ block_workflow_command_email::message_send($nextstate);
// Return a reference to the new state.
return $nextstate;
@@ -421,30 +455,39 @@ public function todos() {
LEFT JOIN {block_workflow_todo_done} done ON done.steptodoid = todos.id AND done.stepstateid = ?
WHERE todos.stepid = ? AND todos.obsolete = 0
ORDER BY todos.id';
- $this->todos = $DB->get_records_sql($sql, array($this->id, $this->stepid));
+ $this->todos = $DB->get_records_sql($sql, [$this->id, $this->stepid]);
}
return $this->todos;
}
/**
* Toggle the completed status of a task for a step state
- * @param int $todoid The ID of the task
+ *
+ * @param int $todoid The ID of the task
+ * @param bool whether user check/uncheck the link.
* @return boolean The new state of the task
*/
- public function todo_toggle($todoid) {
+ public function todo_toggle(int $todoid, bool $check): bool {
global $DB, $USER;
$transaction = $DB->start_delegated_transaction();
// Try and pick up the current task.
- $todo = $DB->get_record('block_workflow_todo_done', array('stepstateid' => $this->id, 'steptodoid' => $todoid));
-
+ $todo = $DB->get_record('block_workflow_todo_done', ['stepstateid' => $this->id, 'steptodoid' => $todoid]);
+ // Has completed to do and user want to completed it. Do nothing.
+ if ($todo && $check) {
+ return true;
+ }
+ // Don't have to do and user want to uncheck it.
+ if (!$check && !$todo) {
+ return false;
+ }
// Trigger an event for the toggled completed status of this to-do.
$event = \block_workflow\event\todo_triggered::create_from_step_state($this, $todoid, !$todo);
$event->trigger();
- if ($todo) {
+ if (!$check) {
// Remove the current record. There is no past history at present.
- $DB->delete_records('block_workflow_todo_done', array('id' => $todo->id));
+ $DB->delete_records('block_workflow_todo_done', ['id' => $todo->id]);
$transaction->allow_commit();
return false;
} else {
@@ -473,7 +516,7 @@ public static function state_changes($stateid) {
INNER JOIN {user} u ON u.id = changes.userid
WHERE changes.stepstateid = ?
ORDER BY changes.timestamp DESC';
- return $DB->get_records_sql($sql, array($stateid));
+ return $DB->get_records_sql($sql, [$stateid]);
}
/**
@@ -492,7 +535,7 @@ public function get_all_users_and_their_roles($roles, $context) {
list ($sortorder, $notused) = users_order_by_sql('u');
$roleinfo = role_get_names($context);
- $rolenames = array();
+ $rolenames = [];
foreach ($roleinfo as $role) {
$rolenames[$role->shortname] = $role->localname;
}
@@ -507,11 +550,11 @@ public function get_all_users_and_their_roles($roles, $context) {
$userroles = $DB->get_recordset_sql($sql, array_merge($fieldssql->params, $params));
- $users = array();
+ $users = [];
foreach ($userroles as $userrole) {
if (!array_key_exists($userrole->id, $users)) {
$users[$userrole->id] = $userrole;
- $users[$userrole->id]->roles = array($rolenames[$userrole->shortname]);
+ $users[$userrole->id]->roles = [$rolenames[$userrole->shortname]];
} else {
$users[$userrole->id]->roles[] = $rolenames[$userrole->shortname];
}
diff --git a/classes/task/finish_step_automatically.php b/classes/task/finish_step_automatically.php
index 1ee5836..a467e51 100644
--- a/classes/task/finish_step_automatically.php
+++ b/classes/task/finish_step_automatically.php
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+namespace block_workflow\task;
+
/**
* A scheduled task for workflow automatic step finisher.
*
@@ -21,9 +23,6 @@
* @copyright 2015 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-
-namespace block_workflow\task;
-
class finish_step_automatically extends \core\task\scheduled_task {
/**
@@ -35,6 +34,11 @@ public function get_name() {
return get_string('crontaskautostepfinisher', 'block_workflow');
}
+ /**
+ * Executes the task to finish a workflow step automatically.
+ *
+ * @return void
+ */
public function execute() {
global $CFG, $DB;
diff --git a/classes/task/send_extra_notification.php b/classes/task/send_extra_notification.php
index c23cbc6..dbbc0df 100644
--- a/classes/task/send_extra_notification.php
+++ b/classes/task/send_extra_notification.php
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+namespace block_workflow\task;
+
/**
* A scheduled task for workflow extra notify.
*
@@ -21,9 +23,6 @@
* @copyright 2015 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-
-namespace block_workflow\task;
-
class send_extra_notification extends \core\task\scheduled_task {
/**
@@ -35,6 +34,11 @@ public function get_name() {
return get_string('crontaskextranotify', 'block_workflow');
}
+ /**
+ * Execution function.
+ *
+ * @return void
+ */
public function execute() {
global $CFG, $DB;
diff --git a/classes/todo.php b/classes/todo.php
index 180f0c4..657bc29 100644
--- a/classes/todo.php
+++ b/classes/todo.php
@@ -34,11 +34,25 @@
* @property-read int $obsolete The visibility of this workflow
*/
class block_workflow_todo {
+ /**
+ * @var int $id This is the unique identifier for the todo item.
+ */
public $id;
+ /**
+ * @var int $stepid The identifier of the associated step.
+ */
public $stepid;
+ /**
+ * @var string $task The description or name of the task.
+ */
public $task;
+ /**
+ * @var bool $obsolete Indicates whether the task is obsolete.
+ */
public $obsolete;
-
+ /**
+ * @var object|null $step The associated step object, or null if not set.
+ */
private $step = null;
/**
@@ -62,9 +76,8 @@ public function __construct($id = null) {
* @param stdClass $todo Database record to overload into the
* object instance
* @return The instantiated block_workflow_todo object
- * @access private
*/
- private function _load($todo) {
+ private function load($todo) {
$this->id = $todo->id;
$this->stepid = $todo->stepid;
$this->task = $todo->task;
@@ -78,12 +91,12 @@ private function _load($todo) {
* @return array The list of available settings
*/
public function expected_settings() {
- return array(
+ return [
'id',
'stepid',
'task',
- 'obsolete'
- );
+ 'obsolete',
+ ];
}
/**
@@ -95,11 +108,11 @@ public function expected_settings() {
*/
public function load_by_id($id) {
global $DB;
- $todo = $DB->get_record('block_workflow_step_todos', array('id' => $id));
+ $todo = $DB->get_record('block_workflow_step_todos', ['id' => $id]);
if (!$todo) {
throw new block_workflow_invalid_todo_exception(get_string('invalidtodo', 'block_workflow'));
}
- return $this->_load($todo);
+ return $this->load($todo);
}
/**
@@ -206,10 +219,10 @@ public function delete_todo() {
$transaction = $DB->start_delegated_transaction();
// First remove any todo_done records.
- $DB->delete_records('block_workflow_todo_done', array('steptodoid' => $this->id));
+ $DB->delete_records('block_workflow_todo_done', ['steptodoid' => $this->id]);
// Then remove the actual todo.
- $DB->delete_records('block_workflow_step_todos', array('id' => $this->id));
+ $DB->delete_records('block_workflow_step_todos', ['id' => $this->id]);
$transaction->allow_commit();
}
@@ -226,7 +239,6 @@ public function delete_todo() {
* no stepid is specified, the todo is placed within the same
* step as the source
* @return The newly created block_workflow_todo object
- * @static
*/
public static function clone_todo($srcid, $stepid = null) {
global $DB;
diff --git a/classes/workflow.php b/classes/workflow.php
index d3a4e67..b29050e 100644
--- a/classes/workflow.php
+++ b/classes/workflow.php
@@ -22,6 +22,10 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+defined('MOODLE_INTERNAL') || die();
+
+require_once(dirname(__FILE__) . '/../locallib.php');
+
/**
* Workflow class
*
@@ -41,13 +45,28 @@
*/
class block_workflow_workflow {
+ /** @var int Workflow ID */
public $id;
+
+ /** @var string Short name of the workflow */
public $shortname;
+
+ /** @var string Name of the workflow */
public $name;
+
+ /** @var string Description of the workflow */
public $description;
+
+ /** @var int Format of the description (e.g., FORMAT_HTML) */
public $descriptionformat;
+
+ /** @var string Context or entity this workflow applies to */
public $appliesto;
+
+ /** @var int|null Step to go back to at the end, or null if not applicable */
public $atendgobacktostep;
+
+ /** @var int Indicates if the workflow is obsolete (1 = obsolete, 0 = active) */
public $obsolete;
/**
@@ -71,9 +90,8 @@ public function __construct($workflowid = null) {
* @param stdClass $workflow Database record to overload into the
* object instance
* @return The instantiated block_workflow_workflow object
- * @access private
*/
- private function _load($workflow) {
+ private function load($workflow) {
$this->id = $workflow->id;
$this->shortname = $workflow->shortname;
$this->name = $workflow->name;
@@ -91,15 +109,16 @@ private function _load($workflow) {
* @return array The list of available settings
*/
public function expected_settings() {
- return array('id',
+ return [
+ 'id',
'shortname',
'name',
'description',
'descriptionformat',
'appliesto',
'atendgobacktostep',
- 'obsolete'
- );
+ 'obsolete',
+ ];
}
/**
@@ -111,11 +130,11 @@ public function expected_settings() {
*/
public function load_workflow($workflowid) {
global $DB;
- $workflow = $DB->get_record('block_workflow_workflows', array('id' => $workflowid));
+ $workflow = $DB->get_record('block_workflow_workflows', ['id' => $workflowid]);
if (!$workflow) {
throw new block_workflow_invalid_workflow_exception(get_string('invalidworkflow', 'block_workflow'));
}
- return $this->_load($workflow);
+ return $this->load($workflow);
}
/**
@@ -127,11 +146,11 @@ public function load_workflow($workflowid) {
*/
public function load_workflow_from_shortname($shortname) {
global $DB;
- $workflow = $DB->get_record('block_workflow_workflows', array('shortname' => $shortname));
+ $workflow = $DB->get_record('block_workflow_workflows', ['shortname' => $shortname]);
if (!$workflow) {
throw new block_workflow_invalid_workflow_exception(get_string('invalidworkflow', 'block_workflow'));
}
- return $this->_load($workflow);
+ return $this->load($workflow);
}
/**
@@ -151,7 +170,7 @@ public function load_context_workflows($contextid) {
WHERE states.contextid = ?
GROUP BY workflows.id
ORDER BY MAX(states.timemodified) DESC";
- $workflows = $DB->get_records_sql($sql, array($contextid));
+ $workflows = $DB->get_records_sql($sql, [$contextid]);
return $workflows;
}
@@ -176,13 +195,13 @@ public function create_workflow($workflow, $createstep = true, $makenamesunique
}
// Check whether this shortname is already in use.
- if ($DB->get_record('block_workflow_workflows', array('shortname' => $workflow->shortname))) {
+ if ($DB->get_record('block_workflow_workflows', ['shortname' => $workflow->shortname])) {
if ($makenamesunique) {
// Create new name by adding a digit and incrementing it if
// name already has digit at the end.
$shortnameclean = preg_replace('/\d+$/', '', $workflow->shortname);
$sql = 'SELECT shortname FROM {block_workflow_workflows} WHERE shortname LIKE ? ORDER BY shortname DESC LIMIT 1';
- $lastshortname = $DB->get_record_sql($sql, array($shortnameclean."%"));
+ $lastshortname = $DB->get_record_sql($sql, [$shortnameclean."%"]);
if (preg_match('/\d+$/', $lastshortname->shortname)) {
$workflow->shortname = $lastshortname->shortname;
$workflow->shortname++;
@@ -200,16 +219,21 @@ public function create_workflow($workflow, $createstep = true, $makenamesunique
}
// Check whether this name is already in use.
- if ($DB->get_record('block_workflow_workflows', array('name' => $workflow->name))) {
+ if ($DB->get_record('block_workflow_workflows', ['name' => $workflow->name])) {
if ($makenamesunique) {
// Create new name by adding a digit and incrementing it if
// name already has digit at the end.
$nameclean = preg_replace('/\d+$/', '', $workflow->name);
$sql = 'SELECT name FROM {block_workflow_workflows} WHERE name LIKE ? ORDER BY name DESC LIMIT 1';
- $lastname = $DB->get_record_sql($sql, array($nameclean."%"));
+ $lastname = $DB->get_record_sql($sql, [$nameclean."%"]);
if (preg_match('/\d+$/', $lastname->name)) {
$workflow->name = $lastname->name;
- $workflow->name++;
+ // Safe increment of trailing number (preserves leading zeros).
+ // E.g: workflow01 becomes workflow02, workflow99 becomes workflow100.
+ $workflow->name = preg_replace_callback('/(\d+)$/', function ($m) {
+ $num = (int) $m[1] + 1;
+ return str_pad((string) $num, strlen($m[1]), '0', STR_PAD_LEFT);
+ }, $workflow->name);
} else {
$workflow->name .= '1';
}
@@ -295,7 +319,6 @@ public function create_workflow($workflow, $createstep = true, $makenamesunique
* @param Object $data An object containing any data to override
* @return The newly created block_workflow_workflow object
* @throws block_workflow_invalid_workflow_exception if the supplied shortname is already in use
- * @static
*/
public static function clone_workflow($srcid, $data) {
global $DB;
@@ -321,7 +344,7 @@ public static function clone_workflow($srcid, $data) {
$dst = (object) array_merge((array) $src, (array) $data);
// Check whether this shortname is already in use.
- if ($DB->get_record('block_workflow_workflows', array('shortname' => $dst->shortname))) {
+ if ($DB->get_record('block_workflow_workflows', ['shortname' => $dst->shortname])) {
$transaction->rollback(new block_workflow_invalid_workflow_exception('shortnameinuse', 'block_workflow'));
}
@@ -371,32 +394,30 @@ public function delete() {
$this->require_deletable();
// First remove any steps and their associated doers and todos.
- $steps = $DB->get_records('block_workflow_step_states', array('id' => $this->id), null, 'id');
+ $steps = $DB->get_records('block_workflow_step_states', ['id' => $this->id], null, 'id');
$steplist = array_map(function ($a) {
return $a->id;
}, $steps);
$DB->delete_records_list('block_workflow_step_doers', 'stepid', $steplist);
$DB->delete_records_list('block_workflow_step_todos', 'stepid', $steplist);
- $DB->delete_records('block_workflow_steps', array('workflowid' => $this->id));
+ $DB->delete_records('block_workflow_steps', ['workflowid' => $this->id]);
// Finally, remove the workflow itself.
- $DB->delete_records('block_workflow_workflows', array('id' => $this->id));
+ $DB->delete_records('block_workflow_workflows', ['id' => $this->id]);
$transaction->allow_commit();
}
/**
- * Return an array of available workflows
+ * Return an array of available workflows.
*
- * @param String for The context in which the workflow is for
- * @return array of stdClass objects as returned by the database
- * abstraction layer
+ * @param string $for type of context the workflows should apply to.
+ * @return stdClass[] of stdClass objects representing workflows.
*/
- public static function available_workflows($for) {
+ public static function available_workflows(string $for): array {
global $DB;
- $workflows = $DB->get_records('block_workflow_workflows',
- array('appliesto' => $for, 'obsolete' => 0), 'name');
- return $workflows;
+ return $DB->get_records('block_workflow_workflows',
+ ['appliesto' => $for, 'obsolete' => 0], 'name');
}
/**
@@ -432,7 +453,7 @@ public function add_to_context($contextid) {
// Check whether this workflow has been previously assigned to this context.
$existingstate = $DB->get_record('block_workflow_step_states',
- array('stepid' => $step->id, 'contextid' => $contextid));
+ ['stepid' => $step->id, 'contextid' => $contextid]);
if ($existingstate) {
$state->id = $existingstate->id;
$DB->update_record('block_workflow_step_states', $state);
@@ -465,7 +486,7 @@ public function add_to_context($contextid) {
// This is a workaround for a limitation of the message_send system.
// This must be called outside of a transaction.
- block_workflow_command_email::message_send();
+ block_workflow_command_email::message_send($state);
return $state;
}
@@ -515,7 +536,7 @@ public function remove_workflow($contextid) {
$DB->delete_records_list('block_workflow_todo_done', 'stepstateid', $statelist);
// Remove the states.
- $DB->delete_records('block_workflow_step_states', array('contextid' => $contextid));
+ $DB->delete_records('block_workflow_step_states', ['contextid' => $contextid]);
// These are all of the required steps for removing a workflow from a context, so commit.
$transaction->allow_commit();
@@ -539,7 +560,7 @@ public function atendgobacktostep($atendgobacktostep = null) {
// Check that we've been given a valid step to loop back to.
if ($atendgobacktostep && !$DB->get_record('block_workflow_steps',
- array('workflowid' => $this->id, 'stepno' => $atendgobacktostep))) {
+ ['workflowid' => $this->id, 'stepno' => $atendgobacktostep])) {
$transaction->rollback(new block_workflow_invalid_workflow_exception('invalidstepno', 'block_workflow'));
}
@@ -649,7 +670,7 @@ public static function in_use_by($id, $activeonly = false) {
if ($activeonly) {
$sql .= " AND st.state IN ('active')";
}
- return $DB->count_records_sql($sql, array($id));
+ return $DB->count_records_sql($sql, [$id]);
}
/**
@@ -675,13 +696,13 @@ public function renumber_steps($from = null, $moveup = 0) {
FROM {block_workflow_steps}
WHERE workflowid = ? AND stepno > ?
ORDER BY stepno ASC';
- $steps = $DB->get_records_sql($sql, array($this->id, $from));
+ $steps = $DB->get_records_sql($sql, [$this->id, $from]);
// Check whether the steps are incorrectly ordered in any way.
$sql = 'SELECT COUNT(stepno) AS count, MAX(stepno) AS max, MIN(stepno) AS min
FROM {block_workflow_steps}
WHERE workflowid = ?';
- $checksteps = $DB->get_record_sql($sql, array($this->id));
+ $checksteps = $DB->get_record_sql($sql, [$this->id]);
if (($checksteps->count != $checksteps->max) || ($checksteps->min != 0)) {
$topstep = $checksteps->max + 1;
@@ -718,7 +739,7 @@ public function steps() {
// Retrieve all of the steps for this workflowid, in order of their
// ascending stepno.
- $steps = $DB->get_records('block_workflow_steps', array('workflowid' => $this->id), 'stepno ASC');
+ $steps = $DB->get_records('block_workflow_steps', ['workflowid' => $this->id], 'stepno ASC');
return $steps;
}
@@ -794,7 +815,7 @@ public function step_states($contextid) {
ORDER BY steps.stepno";
- $steps = $DB->get_records_sql($sql, array('contextid' => $contextid, 'workflowid' => $this->id));
+ $steps = $DB->get_records_sql($sql, ['contextid' => $contextid, 'workflowid' => $this->id]);
return $steps;
}
@@ -817,7 +838,7 @@ public function update($data) {
// Check whether this shortname is already in use.
if (isset($data->shortname) &&
- ($id = $DB->get_field('block_workflow_workflows', 'id', array('shortname' => $data->shortname)))) {
+ ($id = $DB->get_field('block_workflow_workflows', 'id', ['shortname' => $data->shortname]))) {
if ($id != $data->id) {
$transaction->rollback(new block_workflow_invalid_workflow_exception('shortnameinuse', 'block_workflow'));
}
diff --git a/clone.php b/clone.php
index 556dfc3..5aaeb82 100644
--- a/clone.php
+++ b/clone.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once(dirname(__FILE__) . '/clone_form.php');
@@ -43,7 +44,7 @@
// Set page and return urls.
$returnurl = new moodle_url('/blocks/workflow/manage.php');
-$PAGE->set_url('/blocks/workflow/clone.php', array('workflowid' => $workflowid));
+$PAGE->set_url('/blocks/workflow/clone.php', ['workflowid' => $workflowid]);
// Page settings.
$title = get_string('cloneworkflowname', 'block_workflow', $workflow->name);
@@ -71,7 +72,7 @@
$workflow = block_workflow_workflow::clone_workflow($workflowid, $data);
// Redirect to the newly created workflow.
- redirect(new moodle_url('/blocks/workflow/editsteps.php', array('workflowid' => $workflow->id)));
+ redirect(new moodle_url('/blocks/workflow/editsteps.php', ['workflowid' => $workflow->id]));
}
// Set the clone workflow form defaults.
@@ -82,7 +83,7 @@
$data->description = $workflow->description;
$data->descriptionformat = $workflow->descriptionformat;
$data->appliesto = block_workflow_appliesto($workflow->appliesto);
-$data = file_prepare_standard_editor($data, 'description', array('noclean' => true));
+$data = file_prepare_standard_editor($data, 'description', ['noclean' => true]);
$cloneform->set_data($data);
diff --git a/clone_form.php b/clone_form.php
index 5a20b01..f6d2ae2 100644
--- a/clone_form.php
+++ b/clone_form.php
@@ -28,20 +28,27 @@
require_once($CFG->libdir . '/formslib.php');
+/**
+ * Form class for cloning a workflow in Moodle.
+ *
+ * This class extends the moodleform base class.
+ */
class clone_workflow extends moodleform {
+
+ #[\Override]
protected function definition() {
$mform = $this->_form;
$mform->addElement('header', 'general', get_string('cloneworkflow', 'block_workflow'));
// Shortname.
- $mform->addElement('text', 'shortname', get_string('shortname', 'block_workflow'), array('size' => 80, 'maxlength' => 255));
+ $mform->addElement('text', 'shortname', get_string('shortname', 'block_workflow'), ['size' => 80, 'maxlength' => 255]);
$mform->setType('shortname', PARAM_TEXT);
$mform->addRule('shortname', null, 'required', null, 'client');
$mform->addRule('shortname', null, 'maxlength', 255);
// Name.
- $mform->addElement('text', 'name', get_string('name', 'block_workflow'), array('size' => 80, 'maxlength' => 255));
+ $mform->addElement('text', 'name', get_string('name', 'block_workflow'), ['size' => 80, 'maxlength' => 255]);
$mform->setType('name', PARAM_TEXT);
$mform->addRule('name', null, 'required', null, 'client');
$mform->addRule('name', null, 'maxlength', 255);
@@ -61,6 +68,7 @@ protected function definition() {
$this->add_action_buttons(true, get_string('clone', 'block_workflow'));
}
+ #[\Override]
public function validation($data, $files) {
$errors = parent::validation($data, $files);
diff --git a/db/access.php b/db/access.php
index 4adc429..c628fc3 100644
--- a/db/access.php
+++ b/db/access.php
@@ -24,59 +24,59 @@
defined('MOODLE_INTERNAL') || die();
-$capabilities = array(
+$capabilities = [
- 'block/workflow:addinstance' => array(
+ 'block/workflow:addinstance' => [
'riskbitmask' => RISK_SPAM | RISK_XSS,
'captype' => 'write',
'contextlevel' => CONTEXT_BLOCK,
- 'archetypes' => array(
+ 'archetypes' => [
'editingteacher' => CAP_ALLOW,
- 'manager' => CAP_ALLOW
- ),
+ 'manager' => CAP_ALLOW,
+ ],
- 'clonepermissionsfrom' => 'moodle/site:manageblocks'
- ),
+ 'clonepermissionsfrom' => 'moodle/site:manageblocks',
+ ],
// Allows access to, and use of the workflow definition.
// By default given to manager.
- 'block/workflow:editdefinitions' => array(
+ 'block/workflow:editdefinitions' => [
'captype' => 'write',
'contextlevel' => CONTEXT_SYSTEM,
- 'archetypes' => array(
+ 'archetypes' => [
'manager' => CAP_ALLOW,
- )
- ),
+ ],
+ ],
// Allows users to see the workflow block.
// By default given to manager and editingteacher.
- 'block/workflow:view' => array(
+ 'block/workflow:view' => [
'captype' => 'read',
'contextlevel' => CONTEXT_COURSE,
- 'archetypes' => array(
+ 'archetypes' => [
'manager' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
- )
- ),
+ ],
+ ],
// Allows use of the 'Jump to step' button.
// By default given to manager.
- 'block/workflow:manage' => array(
+ 'block/workflow:manage' => [
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
- 'archetypes' => array(
+ 'archetypes' => [
'manager' => CAP_ALLOW,
- )
- ),
+ ],
+ ],
// Allows use of the 'Finish step' button.
// By default given to manager.
- 'block/workflow:dostep' => array(
+ 'block/workflow:dostep' => [
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
- 'archetypes' => array(
+ 'archetypes' => [
'manager' => CAP_ALLOW,
- )
- )
-);
+ ],
+ ],
+];
diff --git a/db/messages.php b/db/messages.php
index 2e73bef..51b0fa2 100644
--- a/db/messages.php
+++ b/db/messages.php
@@ -24,7 +24,7 @@
defined('MOODLE_INTERNAL') || die();
-$messageproviders = array (
+$messageproviders = [
// Notification message provider.
- 'notification' => array (),
-);
+ 'notification' => [],
+];
diff --git a/db/services.php b/db/services.php
new file mode 100644
index 0000000..f4e3163
--- /dev/null
+++ b/db/services.php
@@ -0,0 +1,56 @@
+.
+
+/**
+ * Workflow block external functions and service definitions.
+ *
+ * @package block_workflow
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die;
+
+$functions = [
+ 'block_workflow_get_step_state_comment' => [
+ 'classname' => 'block_workflow\\external\\get_step_state_comment',
+ 'methodname' => 'execute',
+ 'description' => 'Get comment from the current state',
+ 'type' => 'read',
+ 'ajax' => true,
+ ],
+ 'block_workflow_update_step_state_comment' => [
+ 'classname' => 'block_workflow\\external\\update_step_state_comment',
+ 'methodname' => 'execute',
+ 'description' => 'Create/update comment from the current state',
+ 'type' => 'write',
+ 'ajax' => true,
+ ],
+ 'block_workflow_finish_step' => [
+ 'classname' => 'block_workflow\\external\\finish_step',
+ 'methodname' => 'execute',
+ 'description' => 'Mark a step as finished',
+ 'type' => 'write',
+ 'ajax' => true,
+ ],
+ 'block_workflow_update_step_state_task_state' => [
+ 'classname' => 'block_workflow\\external\\update_step_state_task_state',
+ 'methodname' => 'execute',
+ 'description' => 'Update the completed status of a task for a step state',
+ 'type' => 'write',
+ 'ajax' => true,
+ ],
+];
diff --git a/db/tasks.php b/db/tasks.php
index 873e9f6..3aeee03 100644
--- a/db/tasks.php
+++ b/db/tasks.php
@@ -26,25 +26,25 @@
defined('MOODLE_INTERNAL') || die();
-$tasks = array(
+$tasks = [
// Run once a day after 05:01 AM.
- array(
+ [
'classname' => 'block_workflow\task\send_extra_notification',
'blocking' => 0,
'minute' => '1',
'hour' => '5',
'day' => '*',
'month' => '*',
- 'dayofweek' => '*'
- ),
+ 'dayofweek' => '*',
+ ],
// Run once a day after 01:01 AM.
- array(
+ [
'classname' => 'block_workflow\task\finish_step_automatically',
'blocking' => 0,
'minute' => '1',
'hour' => '1',
'day' => '*',
'month' => '*',
- 'dayofweek' => '*'
- )
-);
+ 'dayofweek' => '*',
+ ],
+];
diff --git a/db/upgrade.php b/db/upgrade.php
index de69d9f..87bb722 100644
--- a/db/upgrade.php
+++ b/db/upgrade.php
@@ -22,6 +22,16 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+/**
+ * Handles the upgrade process for the block_workflow plugin.
+ *
+ * This function is called automatically during the upgrade process
+ * when the version in version.php is higher than the currently installed version.
+ * It applies any necessary database schema changes or data migrations.
+ *
+ * @param int $oldversion The version number of the currently installed plugin.
+ * @return bool True on success, false on failure.
+ */
function xmldb_block_workflow_upgrade($oldversion) {
global $DB, $CFG;
@@ -67,7 +77,7 @@ function xmldb_block_workflow_upgrade($oldversion) {
$dbman->add_field($table, $field);
if ($CFG->texteditors !== 'textarea') {
$rs = $DB->get_recordset('block_workflow_emails',
- array('messageformat' => FORMAT_MOODLE), '', 'id,message,messageformat');
+ ['messageformat' => FORMAT_MOODLE], '', 'id,message,messageformat');
foreach ($rs as $b) {
$b->message = text_to_html($b->message, false, false, true);
$b->messageformat = FORMAT_HTML;
@@ -83,14 +93,14 @@ function xmldb_block_workflow_upgrade($oldversion) {
// Replace 'course:startdate' with 'course;startdate'.
if ($oldversion < 2013072200) {
$sql = "UPDATE {block_workflow_steps} SET autofinish = :new WHERE autofinish = :old";
- $DB->execute($sql, array('new' => 'course;startdate', 'old' => 'course:startdate'));
+ $DB->execute($sql, ['new' => 'course;startdate', 'old' => 'course:startdate']);
upgrade_block_savepoint(true, 2013072200, 'workflow');
}
// Fix broken autofinish values.
if ($oldversion < 2014030500) {
$DB->set_field_select('block_workflow_steps', 'autofinish', null,
- 'autofinish IN (?, ?)', array('', 'donotautomaticallyfinish'));
+ 'autofinish IN (?, ?)', ['', 'donotautomaticallyfinish']);
upgrade_block_savepoint(true, 2014030500, 'workflow');
}
@@ -129,7 +139,7 @@ function xmldb_block_workflow_upgrade($oldversion) {
// Define key roleid (foreign) to be added to block_workflow_step_doers.
$table = new xmldb_table('block_workflow_step_doers');
- $key = new xmldb_key('roleid', XMLDB_KEY_FOREIGN, array('roleid'), 'role', array('id'));
+ $key = new xmldb_key('roleid', XMLDB_KEY_FOREIGN, ['roleid'], 'role', ['id']);
// Launch add key roleid.
$dbman->add_key($table, $key);
diff --git a/delete.php b/delete.php
index 10ed06e..f2d3800 100644
--- a/delete.php
+++ b/delete.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once($CFG->libdir . '/adminlib.php');
@@ -44,11 +45,11 @@
// The confirmation strings.
$confirmstr = get_string('deleteworkflowcheck', 'block_workflow', $workflow->name);
-$confirmurl = new moodle_url('/blocks/workflow/delete.php', array('workflowid' => $workflowid, 'confirm' => 1));
+$confirmurl = new moodle_url('/blocks/workflow/delete.php', ['workflowid' => $workflowid, 'confirm' => 1]);
$returnurl = new moodle_url('/blocks/workflow/manage.php');
// Set page url.
-$PAGE->set_url('/blocks/workflow/delete.php', array('workflowid' => $workflowid));
+$PAGE->set_url('/blocks/workflow/delete.php', ['workflowid' => $workflowid]);
// Set the heading and page title.
$title = get_string('confirmworkflowdeletetitle', 'block_workflow', $workflow->shortname);
diff --git a/deleteemail.php b/deleteemail.php
index 5f6e8dc..f840fae 100644
--- a/deleteemail.php
+++ b/deleteemail.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once($CFG->libdir . '/adminlib.php');
@@ -44,11 +45,11 @@
// The confirmation strings.
$confirmstr = get_string('deleteemailcheck', 'block_workflow', $email->shortname);
-$confirmurl = new moodle_url('/blocks/workflow/deleteemail.php', array('emailid' => $emailid, 'confirm' => 1));
+$confirmurl = new moodle_url('/blocks/workflow/deleteemail.php', ['emailid' => $emailid, 'confirm' => 1]);
$returnurl = new moodle_url('/blocks/workflow/manage.php');
// Set the page and return urls.
-$PAGE->set_url('/blocks/workflow/deleteemail.php', array('emaild' => $emailid));
+$PAGE->set_url('/blocks/workflow/deleteemail.php', ['emaild' => $emailid]);
// Set the heading and page title.
$title = get_string('confirmemaildeletetitle', 'block_workflow', $email->shortname);
diff --git a/deletestep.php b/deletestep.php
index 7c2169a..7d2f628 100644
--- a/deletestep.php
+++ b/deletestep.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once($CFG->libdir . '/adminlib.php');
@@ -44,11 +45,11 @@
// The confirmation strings.
$confirmstr = get_string('deletestepcheck', 'block_workflow', $step->name);
-$confirmurl = new moodle_url('/blocks/workflow/deletestep.php', array('stepid' => $stepid, 'confirm' => 1));
-$returnurl = new moodle_url('/blocks/workflow/editsteps.php', array('workflowid' => $step->workflowid));
+$confirmurl = new moodle_url('/blocks/workflow/deletestep.php', ['stepid' => $stepid, 'confirm' => 1]);
+$returnurl = new moodle_url('/blocks/workflow/editsteps.php', ['workflowid' => $step->workflowid]);
// Set page url.
-$PAGE->set_url('/blocks/workflow/deletestep.php', array('stepid' => $stepid));
+$PAGE->set_url('/blocks/workflow/deletestep.php', ['stepid' => $stepid]);
// Set the heading and page title.
$title = get_string('confirmstepdeletetitle', 'block_workflow', $step->name);
diff --git a/deletetask.php b/deletetask.php
index 9d9e096..075b9ba 100644
--- a/deletetask.php
+++ b/deletetask.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once($CFG->libdir . '/adminlib.php');
@@ -40,11 +41,11 @@
// Load the todo.
$todo = new block_workflow_todo($id);
-$returnurl = new moodle_url('/blocks/workflow/editstep.php', array('stepid' => $todo->stepid));
+$returnurl = new moodle_url('/blocks/workflow/editstep.php', ['stepid' => $todo->stepid]);
$workflow = $todo->step()->workflow();
// Generate the confirmation message.
-$strparams = array('stepname' => $todo->step()->name, 'taskname' => $todo->task);
+$strparams = ['stepname' => $todo->step()->name, 'taskname' => $todo->task];
// Set the heading and page title.
$title = get_string('deletetasktitle', 'block_workflow', $strparams);
@@ -59,11 +60,11 @@
// Generate the confirmation button.
$confirmurl = new moodle_url('/blocks/workflow/deletetask.php',
- array('id' => $todo->id, 'confirm' => 1));
+ ['id' => $todo->id, 'confirm' => 1]);
$confirmbutton = new single_button($confirmurl, get_string('confirm'), 'post');
// Set page url.
-$PAGE->set_url('/blocks/workflow/deletetask.php', array('id' => $id));
+$PAGE->set_url('/blocks/workflow/deletetask.php', ['id' => $id]);
// If confirmatation has already been received, then process.
if ($confirm) {
diff --git a/edit_workflow_form.php b/edit_workflow_form.php
index 6524309..1774c0a 100644
--- a/edit_workflow_form.php
+++ b/edit_workflow_form.php
@@ -14,20 +14,23 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
-/**
- * Workflow edit form
- *
- * @package block_workflow
- * @copyright 2011 Lancaster University Network Services Limited
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
require_once(dirname(__FILE__) . '/locallib.php');
require_once($CFG->libdir . '/formslib.php');
+/**
+ * Form definition for editing a workflow in the Moodle block_workflow plugin.
+ *
+ * This class extends moodleform to provide fields and validation for editing workflows.
+ *
+ * @package block_workflow
+ * @copyright 2025 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
class edit_workflow extends moodleform {
+
+ #[\Override]
protected function definition() {
$mform = $this->_form;
@@ -35,13 +38,13 @@ protected function definition() {
// Workflow base data.
$mform->addElement('text', 'shortname', get_string('shortname', 'block_workflow'),
- array('size' => 80, 'maxlength' => 255));
+ ['size' => 80, 'maxlength' => 255]);
$mform->setType('shortname', PARAM_TEXT);
$mform->addRule('shortname', null, 'required', null, 'client');
$mform->addRule('shortname', null, 'maxlength', 255);
$mform->addElement('text', 'name', get_string('name', 'block_workflow'),
- array('size' => 80, 'maxlength' => 255));
+ ['size' => 80, 'maxlength' => 255]);
$mform->setType('name', PARAM_TEXT);
$mform->addRule('name', null, 'required', null, 'client');
$mform->addRule('name', null, 'maxlength', 255);
@@ -60,7 +63,7 @@ protected function definition() {
}
// When reaching the end of the workflow, go back to.
- $steplist = array();
+ $steplist = [];
$steplist[null] = get_string('atendfinishworkflow', 'block_workflow');
$finalstep = null;
foreach ($this->_customdata['steps'] as $step) {
@@ -75,7 +78,7 @@ protected function definition() {
}
// The current status of this workflow.
- $enabledoptions = array();
+ $enabledoptions = [];
$enabledoptions['0'] = get_string('enabled', 'block_workflow');
$enabledoptions['1'] = get_string('disabled', 'block_workflow');
$mform->addElement('select', 'obsolete', get_string('status', 'block_workflow'), $enabledoptions);
@@ -87,6 +90,7 @@ protected function definition() {
$this->add_action_buttons();
}
+ #[\Override]
public function validation($data, $files) {
$errors = parent::validation($data, $files);
diff --git a/editcomment.php b/editcomment.php
index cba251b..ca0227d 100644
--- a/editcomment.php
+++ b/editcomment.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once(dirname(__FILE__) . '/editcomment_form.php');
@@ -47,12 +48,12 @@
block_workflow_can_make_changes($state);
// Set the page URL.
-$PAGE->set_url('/blocks/workflow/editcomment.php', array('stateid' => $stateid));
+$PAGE->set_url('/blocks/workflow/editcomment.php', ['stateid' => $stateid]);
$PAGE->set_pagelayout('standard');
$PAGE->set_course($course);
// Set the heading and page title.
-$tparams = array('stepname' => $state->step()->name, 'contextname' => $context->get_context_name());
+$tparams = ['stepname' => $state->step()->name, 'contextname' => $context->get_context_name()];
$title = get_string('editingcommentfor', 'block_workflow', $tparams);
$PAGE->set_heading($title);
$PAGE->set_title($title);
@@ -63,7 +64,7 @@
$PAGE->navbar->add($state->step()->name);
// Moodle form to update the state comment.
-$mform = new state_editcomment(null, array('state' => $state));
+$mform = new state_editcomment(null, ['state' => $state]);
// Grab a returnurl which relates to the context.
$returnurl = $context->get_url();
@@ -85,7 +86,7 @@
$data->workflowname = $state->step()->workflow()->name;
$data->stepname = $state->step()->name;
$data->instructions = $state->step()->instructions;
-$data = file_prepare_standard_editor($data, 'comment', array());
+$data = file_prepare_standard_editor($data, 'comment', []);
$mform->set_data($data);
diff --git a/editcomment_form.php b/editcomment_form.php
index 730db44..effc66d 100644
--- a/editcomment_form.php
+++ b/editcomment_form.php
@@ -14,6 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
+
+require_once(dirname(__FILE__) . '/locallib.php');
+require_once($CFG->libdir . '/formslib.php');
+
/**
* Form for comments.
*
@@ -21,13 +26,9 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-
-defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
-
-require_once(dirname(__FILE__) . '/locallib.php');
-require_once($CFG->libdir . '/formslib.php');
-
class state_editcomment extends moodleform {
+
+ #[\Override]
protected function definition() {
$mform = $this->_form;
$state = $this->_customdata['state'];
diff --git a/editemail.php b/editemail.php
index 977c06b..d73eef4 100644
--- a/editemail.php
+++ b/editemail.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once(dirname(__FILE__) . '/editemail_form.php');
@@ -86,13 +87,15 @@
}
// Set the form defaults.
- $email->emailid = $email->id;
- $message = $email->message;
- $email->message = array();
- $email->message['text'] = $message;
- $email->message['format'] = FORMAT_HTML;
-
- $emailform->set_data($email);
+$toform = new stdClass();
+$toform->emailid = $email->id;
+$toform->shortname = $email->shortname;
+$toform->subject = $email->subject;
+$toform->message = [
+ 'text' => $email->message,
+ 'format' => $email->messageformat,
+];
+$emailform->set_data($toform);
// Grab the renderer.
$renderer = $PAGE->get_renderer('block_workflow');
diff --git a/editemail_form.php b/editemail_form.php
index 58342b6..7f3cbd4 100644
--- a/editemail_form.php
+++ b/editemail_form.php
@@ -14,20 +14,24 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
-/**
- * Email edit form
- *
- * @package block_workflow
- * @copyright 2011 Lancaster University Network Services Limited
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
require_once(dirname(__FILE__) . '/locallib.php');
require_once($CFG->libdir . '/formslib.php');
+/**
+ * Form definition for editing email settings in the workflow block.
+ *
+ * This class extends moodleform to provide a form for editing email-related
+ * configuration within the Moodle workflow block.
+ *
+ * @package block_workflow
+ * @copyright 2025 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
class email_edit extends moodleform {
+
+ #[\Override]
protected function definition() {
$mform = $this->_form;
$mform->addElement('header', 'general', get_string('emailsettings', 'block_workflow'));
@@ -56,6 +60,7 @@ protected function definition() {
$this->add_action_buttons();
}
+ #[\Override]
public function validation($data, $files) {
$errors = parent::validation($data, $files);
diff --git a/editsettings.php b/editsettings.php
index 8924ae3..a04897e 100644
--- a/editsettings.php
+++ b/editsettings.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once(dirname(__FILE__) . '/edit_workflow_form.php');
@@ -42,13 +43,13 @@
$workflow = new block_workflow_workflow();
// Attempt to the set page/return url initially.
-$returnurl = new moodle_url('/blocks/workflow/editsteps.php', array('workflowid' => $workflowid));
+$returnurl = new moodle_url('/blocks/workflow/editsteps.php', ['workflowid' => $workflowid]);
if ($workflowid) {
// If we've been given an existing workflow.
$workflow->load_workflow($workflowid);
$title = get_string('editworkflow', 'block_workflow', $workflow->name);
- $PAGE->set_url('/blocks/workflow/editsettings.php', array('workflowid' => $workflowid));
+ $PAGE->set_url('/blocks/workflow/editsettings.php', ['workflowid' => $workflowid]);
} else {
// We're creating a new workflow.
$title = get_string('createworkflow', 'block_workflow');
@@ -68,7 +69,7 @@
}
// Moodle form to create/edit workflow.
-$customdata = array('steps' => $workflow->steps(), 'is_deletable' => $workflow->is_deletable());
+$customdata = ['steps' => $workflow->steps(), 'is_deletable' => $workflow->is_deletable()];
$editform = new edit_workflow(null, $customdata);
if ($editform->is_cancelled()) {
@@ -108,7 +109,7 @@
}
// Redirect to the editsteps page.
- redirect(new moodle_url('/blocks/workflow/editsteps.php', array('workflowid' => $workflow->id)));
+ redirect(new moodle_url('/blocks/workflow/editsteps.php', ['workflowid' => $workflow->id]));
}
$data = new stdClass();
@@ -123,7 +124,7 @@
$data->obsolete = $workflow->obsolete;
$data->appliesto = $workflow->appliesto;
$data->atendgobacktostep = $workflow->atendgobacktostep;
- $data = file_prepare_standard_editor($data, 'description', array('noclean' => true));
+ $data = file_prepare_standard_editor($data, 'description', ['noclean' => true]);
$editform->set_data($data);
}
diff --git a/editstep.php b/editstep.php
index 3d51a73..43218b9 100644
--- a/editstep.php
+++ b/editstep.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once(dirname(__FILE__) . '/editstep_form.php');
@@ -41,26 +42,26 @@
if ($stepid) {
// If we've been given an existing workflow.
$step = new block_workflow_step($stepid);
- $returnurl = new moodle_url('/blocks/workflow/editsteps.php', array('workflowid' => $step->workflowid));
+ $returnurl = new moodle_url('/blocks/workflow/editsteps.php', ['workflowid' => $step->workflowid]);
$todos = $step->todos(false);
$doers = $step->roles();
$roles = block_workflow_contextlevel_roles($step->workflow()->context());
$title = get_string('editstepname', 'block_workflow', $step->name);
- $PAGE->set_url('/blocks/workflow/editstep.php', array('stepid' => $stepid));
+ $PAGE->set_url('/blocks/workflow/editstep.php', ['stepid' => $stepid]);
// Add the breadcrumbs.
$PAGE->navbar->add($step->workflow()->name, $returnurl);
$PAGE->navbar->add(get_string('editstep', 'block_workflow'));
- $appliesto = $DB->get_field('block_workflow_workflows', 'appliesto', array('id' => $step->workflowid));
+ $appliesto = $DB->get_field('block_workflow_workflows', 'appliesto', ['id' => $step->workflowid]);
} else {
// We're creating a new step.
$workflowid = required_param('workflowid', PARAM_INT);
$workflow = new block_workflow_workflow($workflowid);
- $returnurl = new moodle_url('/blocks/workflow/editsteps.php', array('workflowid' => $workflowid));
+ $returnurl = new moodle_url('/blocks/workflow/editsteps.php', ['workflowid' => $workflowid]);
$title = get_string('createstepname', 'block_workflow', $workflow->name);
$beforeafter = optional_param('beforeafter', 0, PARAM_INT);
- $PAGE->set_url('/blocks/workflow/editstep.php', array('workflowid' => $workflowid));
+ $PAGE->set_url('/blocks/workflow/editstep.php', ['workflowid' => $workflowid]);
// Add the breadcrumbs.
$PAGE->navbar->add($workflow->name, $returnurl);
@@ -74,7 +75,7 @@
$PAGE->set_heading($title);
// Moodle form to create/edit step.
-$stepedit = new step_edit('editstep.php', array('appliesto' => $appliesto));
+$stepedit = new step_edit('editstep.php', ['appliesto' => $appliesto]);
if ($stepedit->is_cancelled()) {
// Form was cancelled.
@@ -128,7 +129,7 @@
$data->extranotify = $step->extranotify;
$data->extranotifyoffset = $step->extranotifyoffset;
$data->onextranotifyscript = $step->onextranotifyscript;
- $data = file_prepare_standard_editor($data, 'instructions', array('noclean' => true));
+ $data = file_prepare_standard_editor($data, 'instructions', ['noclean' => true]);
$stepedit->set_data($data);
} else {
// Otherwise, this is a new step belonging to $workflowid.
diff --git a/editstep_form.php b/editstep_form.php
index 5da154e..49d3952 100644
--- a/editstep_form.php
+++ b/editstep_form.php
@@ -14,21 +14,24 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
-/**
- * Form for editing steps
- *
- * @package block_workflow
- * @copyright 2011 Lancaster University Network Services Limited
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
require_once(dirname(__FILE__) . '/locallib.php');
require_once($CFG->libdir . '/formslib.php');
+/**
+ * Form definition for editing a workflow step in the Moodle block_workflow plugin.
+ *
+ * This class extends the moodleform base class to provide fields and validation
+ * for creating or editing workflow steps within the workflow block.
+ *
+ * @package block_workflow
+ * @copyright 2025 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
class step_edit extends moodleform {
+ #[\Override]
protected function definition() {
global $DB;
$mform = $this->_form;
@@ -47,7 +50,7 @@ protected function definition() {
$mform->addRule('instructions_editor', null, 'required', null, 'client');
// Scripts.
- $scriptoptions = array('cols' => 80, 'rows' => 8);
+ $scriptoptions = ['cols' => 80, 'rows' => 8];
// IDs.
$mform->addElement('hidden', 'stepid');
@@ -92,7 +95,7 @@ protected function definition() {
$options[''] = get_string('donotautomaticallyfinish', 'block_workflow');
$mform->addElement('textarea', 'oncompletescript', get_string('oncompletescript', 'block_workflow'), $scriptoptions);
$mform->setType('oncompletescript', PARAM_RAW);
- $autofinish = array();
+ $autofinish = [];
$autofinish[] = $mform->createElement('select', 'autofinishoffset', null, $days);
$autofinish[] = $mform->createElement('select', 'autofinish', null, $options);
$mform->addGroup($autofinish, null, get_string('automaticallyfinish', 'block_workflow'), ' ', true);
@@ -101,7 +104,7 @@ protected function definition() {
$mform->disabledIf('autofinishoffset', 'autofinish', 'eq', '');
// We disable the autofinish functionality for modules other than quiz or external quiz.
- $autofinshallowed = array('course', 'quiz', 'externalquiz');
+ $autofinshallowed = ['course', 'quiz', 'externalquiz'];
if (!in_array($this->_customdata['appliesto'], $autofinshallowed)) {
// We use disbaleIf function without dependency and conditions, because
// other modules apart from 'quiz and 'externalquiz' do not support the functionality.
@@ -112,6 +115,7 @@ protected function definition() {
$this->add_action_buttons();
}
+ #[\Override]
public function validation($data, $files) {
$errors = parent::validation($data, $files);
diff --git a/editsteps.php b/editsteps.php
index ae4fe4a..97da607 100644
--- a/editsteps.php
+++ b/editsteps.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once($CFG->libdir . '/adminlib.php');
@@ -41,7 +42,7 @@
$workflow = new block_workflow_workflow($workflowid);
// Set the returnurl as we'll use this in a few places.
-$returnurl = new moodle_url('/blocks/workflow/editsteps.php', array('workflowid' => $workflowid));
+$returnurl = new moodle_url('/blocks/workflow/editsteps.php', ['workflowid' => $workflowid]);
// Set various page settings.
$title = get_string('editworkflow', 'block_workflow', $workflow->name);
diff --git a/edittask.php b/edittask.php
index 18b88a5..13447ef 100644
--- a/edittask.php
+++ b/edittask.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once(dirname(__FILE__) . '/edittask_form.php');
@@ -40,15 +41,15 @@
if ($taskid) {
// An existing task was specified.
$task->load_by_id($taskid);
- $returnurl = new moodle_url('/blocks/workflow/editstep.php', array('stepid' => $task->stepid));
+ $returnurl = new moodle_url('/blocks/workflow/editstep.php', ['stepid' => $task->stepid]);
$PAGE->set_title(get_string('edittask', 'block_workflow', $task->task));
- $PAGE->set_url('/blocks/workflow/edittask.php', array('taskid' => $taskid));
+ $PAGE->set_url('/blocks/workflow/edittask.php', ['taskid' => $taskid]);
$data = (object) $task;
} else {
// Creating a new task. We require the stepid.
$stepid = required_param('stepid', PARAM_INT);
$step = new block_workflow_step($stepid);
- $returnurl = new moodle_url('/blocks/workflow/editstep.php', array('stepid' => $step->id));
+ $returnurl = new moodle_url('/blocks/workflow/editstep.php', ['stepid' => $step->id]);
$PAGE->set_title(get_string('createtask', 'block_workflow', $step->name));
$PAGE->set_url('/blocks/workflow/edittask.php');
$data = new stdClass();
diff --git a/edittask_form.php b/edittask_form.php
index 454ddfa..7a705cf 100644
--- a/edittask_form.php
+++ b/edittask_form.php
@@ -26,7 +26,14 @@
require_once($CFG->libdir . '/formslib.php');
+/**
+ * Form definition for editing a workflow task in the Moodle block_workflow plugin.
+ *
+ * This class extends the moodleform base class to provide fields and validation
+ * for editing or creating workflow tasks within the workflow block.
+ */
class task_edit extends moodleform {
+ #[\Override]
protected function definition() {
$mform = $this->_form;
$mform->addElement('text', 'task', get_string('task', 'block_workflow'));
diff --git a/export.php b/export.php
index 9664fa9..0ec8a53 100644
--- a/export.php
+++ b/export.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once($CFG->libdir . '/filelib.php');
@@ -58,7 +59,7 @@
// Create a list of the workflow's steps.
// We need to store any used templates here.
-$templatelist = array();
+$templatelist = [];
foreach ($workflow->steps() as $step) {
// Load the object as we'll need to call some of it's functions.
$step = new block_workflow_step($step->id);
@@ -90,7 +91,7 @@
// As we loop through each step, we need to check each script for use
// of e-mail emails and retrieve those for later inclusion.
- $commands = array();
+ $commands = [];
$script = block_workflow_step::parse_script($step->onactivescript);
$commands = array_merge($commands, $script->commands);
@@ -107,7 +108,7 @@
$d = $class->parse($c->arguments, $step);
// And retrieve the template.
- $errors = array();
+ $errors = [];
$t = $class->email($d->emailname, $errors);
$templatelist[$d->emailname] = $t;
}
@@ -143,5 +144,5 @@
* @return string The checked and (potentially) modified text
*/
function check_output_text($raw) {
- return htmlspecialchars($raw, ENT_NOQUOTES, 'UTF-8');
+ return htmlspecialchars($raw ?? '', ENT_NOQUOTES, 'UTF-8');
}
diff --git a/finishstep.php b/finishstep.php
index 8a9c6ae..30b2206 100644
--- a/finishstep.php
+++ b/finishstep.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once(dirname(__FILE__) . '/finishstep_form.php');
@@ -47,12 +48,12 @@
block_workflow_can_make_changes($state);
// Set the page URL.
-$PAGE->set_url('/blocks/workflow/finishstep.php', array('stateid' => $stateid));
+$PAGE->set_url('/blocks/workflow/finishstep.php', ['stateid' => $stateid]);
$PAGE->set_pagelayout('standard');
$PAGE->set_course($course);
// Set the heading and page title.
-$tparams = array('stepname' => $state->step()->name, 'contextname' => $context->get_context_name());
+$tparams = ['stepname' => $state->step()->name, 'contextname' => $context->get_context_name()];
$title = get_string('finishstepfor', 'block_workflow', $tparams);
$PAGE->set_heading($title);
$PAGE->set_title($title);
@@ -63,7 +64,7 @@
$PAGE->navbar->add($state->step()->name);
// Moodle form to update the state comment.
-$mform = new state_finishtask(null, array('state' => $state));
+$mform = new state_finishtask(null, ['state' => $state]);
// Grab a returnurl which relates to the context.
$returnurl = $context->get_url();
@@ -85,7 +86,7 @@
$data->workflowname = $state->step()->workflow()->name;
$data->stepname = $state->step()->name;
$data->instructions = $state->step()->instructions;
-$data = file_prepare_standard_editor($data, 'comment', array());
+$data = file_prepare_standard_editor($data, 'comment', []);
$mform->set_data($data);
diff --git a/finishstep_form.php b/finishstep_form.php
index d268e72..05df667 100644
--- a/finishstep_form.php
+++ b/finishstep_form.php
@@ -14,20 +14,23 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
-/**
- * Form for task finishing
- *
- * @package block_workflow
- * @copyright 2011 Lancaster University Network Services Limited
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
require_once(dirname(__FILE__) . '/locallib.php');
require_once($CFG->libdir . '/formslib.php');
+/**
+ * Form class for finishing a workflow step in the Moodle block_workflow plugin.
+ *
+ * This class defines the form used to complete a workflow step.
+ *
+ * @package block_workflow
+ * @copyright 2025 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
class state_finishtask extends moodleform {
+
+ #[\Override]
protected function definition() {
$mform = $this->_form;
$state = $this->_customdata['state'];
diff --git a/import.php b/import.php
index 719f77a..8af46b7 100644
--- a/import.php
+++ b/import.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once(dirname(__FILE__) . '/import_form.php');
@@ -105,7 +106,7 @@
$workflow = $workflow->create_workflow($workflowx, false, true);
// Check whether the steps are incorrectly ordered and sort them.
- $steporder = array();
+ $steporder = [];
foreach ($xml->steps->step as $importedstep) {
$attributes = $importedstep->attributes();
$stepno = (string)$attributes['no'];
@@ -200,7 +201,7 @@
$transaction->allow_commit();
// Redirect.
- redirect(new moodle_url('/blocks/workflow/editsteps.php', array('workflowid' => $workflow->id)),
+ redirect(new moodle_url('/blocks/workflow/editsteps.php', ['workflowid' => $workflow->id]),
$extramessage . get_string('importsuccess', 'block_workflow'), 10);
}
diff --git a/import_form.php b/import_form.php
index 3d7b425..98c7b67 100644
--- a/import_form.php
+++ b/import_form.php
@@ -27,14 +27,19 @@
require_once(dirname(__FILE__) . '/locallib.php');
require_once($CFG->libdir . '/formslib.php');
+/**
+ * Class import_workflow
+ */
class import_workflow extends moodleform {
+
+ #[\Override]
protected function definition() {
$mform = $this->_form;
$mform->addElement('header', 'general', get_string('workflowimport', 'block_workflow'));
$mform->addElement('filepicker', 'importfile', get_string('importfile', 'block_workflow'),
- null, array('accepted_type' => '*.xml'));
+ null, ['accepted_type' => '*.xml']);
$mform->addRule('importfile', null, 'required', null, 'client');
$this->add_action_buttons(true, get_string('importworkflow', 'block_workflow'));
diff --git a/jumptostep.php b/jumptostep.php
index b50e32e..42fedee 100644
--- a/jumptostep.php
+++ b/jumptostep.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
@@ -55,12 +56,12 @@
$step = new block_workflow_step($stepid);
// Set the page URL.
-$PAGE->set_url('/blocks/workflow/jumptostep.php', array('contextid' => $contextid, 'stepid' => $stepid));
+$PAGE->set_url('/blocks/workflow/jumptostep.php', ['contextid' => $contextid, 'stepid' => $stepid]);
$PAGE->set_pagelayout('standard');
$PAGE->set_course($course);
// Set the heading and page title.
-$tparams = array('stepname' => $step->name, 'contextname' => $context->get_context_name());
+$tparams = ['stepname' => $step->name, 'contextname' => $context->get_context_name()];
$title = get_string('jumptostepon', 'block_workflow', $tparams);
$PAGE->set_heading($title);
$PAGE->set_title($title);
@@ -86,7 +87,7 @@
}
// Generate the confirmation message.
-$strparams = array();
+$strparams = [];
$strparams['fromstep'] = $state->step()->name;
$strparams['tostep'] = $step->name;
$strparams['workflowon'] = $context->get_context_name();
@@ -97,7 +98,7 @@
// Generate the confirmation button.
$confirmurl = new moodle_url('/blocks/workflow/jumptostep.php',
- array('contextid' => $contextid, 'stepid' => $stepid, 'confirm' => 1));
+ ['contextid' => $contextid, 'stepid' => $stepid, 'confirm' => 1]);
$confirmbutton = new single_button($confirmurl, get_string('confirm'), 'post');
echo $OUTPUT->header();
diff --git a/lang/en/block_workflow.php b/lang/en/block_workflow.php
index 26e7a8a..14c8603 100644
--- a/lang/en/block_workflow.php
+++ b/lang/en/block_workflow.php
@@ -23,13 +23,9 @@
*/
// Core strings.
-$string['workflow:addinstance'] = 'Add a new workflow block';
-$string['pluginname'] = 'Workflows';
-$string['workflow'] = 'Workflow';
-
$string['activetasktitle'] = 'Currently active task';
-$string['addaworkflow'] = 'Add a workflow';
$string['addanotherworkflow'] = 'Add another workflow';
+$string['addaworkflow'] = 'Add a workflow';
$string['addemail'] = 'Add email template';
$string['addroletostep'] = 'Add role to step';
$string['addstep'] = 'Add an additional step to this workflow';
@@ -66,11 +62,11 @@
$string['confirmstepdeletetitle'] = 'Delete step \'{$a}\'?';
$string['confirmworkflowdeletetitle'] = 'Delete workflow \'{$a}\'?';
$string['contexthasactiveworkflow'] = 'This context already has an active workflow.';
+$string['coursestartdate'] = 'the course start date';
$string['coursestudentclose'] = 'the course is closed to students';
$string['coursestudentopen'] = 'the course is opened to students';
$string['coursetutorclose'] = 'the course is closed to tutors';
$string['coursetutoropen'] = 'the course is opened to tutors';
-$string['coursestartdate'] = 'the course start date';
$string['create'] = 'Create';
$string['createemail'] = 'Create new email template';
$string['createstep'] = 'Create step';
@@ -82,12 +78,12 @@
$string['crontaskautostepfinisher'] = 'Workflow step finisher';
$string['crontaskextranotify'] = 'Workflow step extra notify';
$string['currentlyinuseby'] = 'This workflow is currently in use by';
+$string['dayafter'] = '{$a} day after';
+$string['dayas'] = 'same day as';
+$string['daybefore'] = '{$a} day before';
$string['days'] = 'Days';
-$string['dayas'] = 'same day as';
-$string['dayafter'] = '{$a} day after';
$string['daysafter'] = '{$a} days after';
-$string['daybefore'] = '{$a} day before';
$string['daysbefore'] = '{$a} days before';
$string['defaultonactivescript'] = '# You may place a set of actions to complete when marking this step active here';
$string['defaultoncompletescript'] = '# You may place a set of actions to complete when marking this step finished here';
@@ -129,6 +125,7 @@
$string['editworkflow'] = 'Editing workflow \'{$a}\'';
$string['editworkflowinstructions'] = 'Edit workflow instructions';
$string['emaildescription'] = 'E-mail templates may be used by the various scripts in a workflow step';
+$string['emailfailed'] = 'Failed send email \'{$a->subject}\' to {$a->email}';
$string['emailfrom'] = '{$a} workflow system';
$string['emaillist'] = 'Email email templates';
$string['emailmessage'] = 'Message';
@@ -161,14 +158,16 @@
$string['eventstepaborted'] = 'Step aborted';
$string['eventstepactivated'] = 'Step activated';
$string['eventstepcompleted'] = 'Step completed';
-$string['eventtodotriggered'] = 'Todo triggered';
$string['eventstepextranotification'] = 'Step extra notification processed';
+$string['eventtodotriggered'] = 'Todo triggered';
+$string['eventworkflownotification'] = 'Workflow notification';
$string['export'] = 'Export';
$string['exportworkflow'] = 'Export workflow';
$string['finish'] = 'Finish';
$string['finishstep'] = 'Finish step';
$string['finishstepautomatically'] = 'This step was automatically finished by workflow system at {$a}.';
+
$string['finishstepfor'] = 'Finish step \'{$a->stepname}\' on {$a->contextname}';
$string['finishstepinstructions'] = 'You are about to mark this step as complete, and move to the next step in the workflow. A summary of the step is shown below -- you may wish to update the comment below.';
$string['format_html'] = 'html';
@@ -180,8 +179,11 @@
$string['hidetask'] = 'Disable task';
$string['importfile'] = 'File';
+
$string['importsuccess'] = 'Importing was successful. You will be redirected to workflow editing page shortly.';
+
$string['importworkflow'] = 'Import workflow';
+
$string['instructions'] = 'Instructions';
$string['inuseby'] = 'It is currently in use in {$a} locations.';
$string['invalidactivitysettingcolumn'] = 'The column specified ({$a}) does not exist.';
@@ -223,6 +225,7 @@
$string['jumpstep'] = 'Jump to step';
$string['jumptostep'] = 'Jump to step';
$string['jumptostepcheck'] = 'Are you sure you wish to jump from step \'{$a->fromstep}\' to step \'{$a->tostep}\' for the workflow on {$a->workflowon}?';
+
$string['jumptostepcommentaddition'] = '
[Note: the workflow just jumped from step \'{$a->fromstep}\'. This comment may seem out-of-context.]
{$a->comment}';
$string['jumptostepon'] = 'Jump to step \'{$a->stepname}\' on {$a->contextname}';
$string['jumptosteptitle'] = 'Jump to step \'{$a->tostep}\' for \'{$a->workflowon}\' confirmation';
@@ -231,7 +234,9 @@
$string['managedescription'] = 'On this page you can create end edit workflows and the email templates that they use.';
$string['manageemails'] = 'Manage email templates';
+
$string['manageworkflows'] = 'Manage workflows';
+
$string['messageprovider:notification'] = 'Workflow notifications and alerts';
$string['missingfield'] = 'The required field is missing: {$a}';
$string['movedown'] = 'Move down';
@@ -240,6 +245,7 @@
$string['name'] = 'Name';
$string['nameinuse'] = 'The name specified is already in use. Names must be unique';
$string['nameshortname'] = '{$a->name} ({$a->shortname})';
+
$string['noactiveworkflow'] = 'There is currently no active workflow.';
$string['nocomment'] = 'No comment yet...';
$string['nocomments'] = 'No comments have been made about this step yet';
@@ -267,23 +273,21 @@
$string['overviewtitle'] = 'Overview of {$a->workflowname} workflow on {$a->contexttitle}';
$string['percentcomplete'] = '{$a}% complete';
+$string['pluginname'] = 'Workflows';
+$string['privacy:metadata'] = 'The Calendar block only displays existing calendar data.';
-// GDPR.
$string['privacy:metadata:block_workflow_state_changes'] = 'Changes to states.';
-$string['privacy:metadata:block_workflow_state_changes:userid'] = 'The user who caused the state change.';
$string['privacy:metadata:block_workflow_state_changes:newstate'] = 'The state that this step changed to.';
-
+$string['privacy:metadata:block_workflow_state_changes:userid'] = 'The user who caused the state change.';
$string['privacy:metadata:block_workflow_todo_done'] = 'Changes to each step in the workflow.';
-$string['privacy:metadata:block_workflow_todo_done:userid'] = 'The user who caused the state change.';
-$string['privacy:metadata:block_workflow_todo_done:steptodoid'] = 'The todo step that user changed to.';
-$string['privacy:metadata'] = 'The Calendar block only displays existing calendar data.';
-$string['privacy_you'] = 'You';
+$string['privacy:metadata:block_workflow_todo_done:steptodoid'] = 'The todo step that user changed to.';
+$string['privacy:metadata:block_workflow_todo_done:userid'] = 'The user who caused the state change.';
$string['privacy_somebodyelse'] = 'Somebody else';
-// End GDPR.
+$string['privacy_you'] = 'You';
-$string['quizopendate'] = 'the quiz open date';
$string['quizclosedate'] = 'the quiz close date';
+$string['quizopendate'] = 'the quiz open date';
$string['remove'] = 'Remove';
$string['removerolefromstep'] = 'Remove role from step';
@@ -346,14 +350,16 @@
$string['vieweditemail'] = 'View/Edit email';
$string['vieweditworkflow'] = 'View/Edit workflow';
+$string['workflow'] = 'Workflow';
+$string['workflow:addinstance'] = 'Add a new workflow block';
$string['workflow:dostep'] = 'Permission to perform a step';
$string['workflow:editdefinitions'] = 'Permission to edit workflow details';
$string['workflow:manage'] = 'Permission to manage workflows';
$string['workflow:view'] = 'Permission to view workflow information';
$string['workflowactive'] = 'This workflow is currently enabled (disable it). ';
-$string['workflowalreadyset'] = 'A workflow has already been set for this step. Steps cannot be reassigned to a different workflow';
$string['workflowalreadyassigned'] = 'A workflow is already assigned to this context. Only one workflow may be assigned to any one context at a time.';
+$string['workflowalreadyset'] = 'A workflow has already been set for this step. Steps cannot be reassigned to a different workflow';
$string['workflowimport'] = 'Workflow importing';
$string['workflowinformation'] = 'Workflow information';
$string['workflowlist'] = 'Workflows';
diff --git a/lib.php b/lib.php
new file mode 100644
index 0000000..1924815
--- /dev/null
+++ b/lib.php
@@ -0,0 +1,39 @@
+.
+
+/**
+ * Library for block workflow
+ *
+ * All the core Moodle functions, neeeded to allow the module to work
+ * integrated in Moodle should be placed here.
+ *
+ * @package block_workflow
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+use block_workflow\local\forms\comment_form;
+
+/**
+ * Function to get comment form fragment.
+ *
+ * @param array $args Arguments for form.
+ * @return string HTML content.
+ */
+function block_workflow_output_fragment_commentform(array $args): string {
+ $mform = new comment_form(null, ['inputLabel' => $args['inputLabel']]);
+ return html_writer::div($mform->render(), 'block-workflow-panel');
+}
diff --git a/locallib.php b/locallib.php
index c384e72..d0316c0 100644
--- a/locallib.php
+++ b/locallib.php
@@ -90,10 +90,10 @@ function block_workflow_load_workflows() {
*/
function block_workflow_appliesto_list() {
// Applies to should contain courses ...
- $return = array('course' => get_string('course'));
+ $return = ['course' => get_string('course')];
// ... and any installed modules.
- $mods = get_plugin_list('mod');
+ $mods = core_component::get_plugin_list('mod');
foreach ($mods as $name => $path) {
$return[$name] = get_string('pluginname', 'mod_' . $name);
}
@@ -138,7 +138,7 @@ function block_workflow_contextlevel_roles($contextlevel) {
WHERE cl.contextlevel = ?
ORDER BY roles.sortorder ASC
";
- return role_fix_names($DB->get_records_sql($sql, array($contextlevel)));
+ return role_fix_names($DB->get_records_sql($sql, [$contextlevel]));
}
/**
@@ -152,7 +152,7 @@ function block_workflow_contextlevel_roles($contextlevel) {
* @return array Containing a list of default properties
*/
function block_workflow_editor_options() {
- $options = array();
+ $options = [];
// Disallow files.
$options['maxfiles'] = 0;
@@ -195,10 +195,10 @@ function block_workflow_editor_format($type) {
* @return int The editor format
*/
function block_workflow_convert_editor_format($format) {
- $knownformats = array(
+ $knownformats = [
get_string('format_html', 'block_workflow') => FORMAT_HTML,
get_string('format_plain', 'block_workflow') => FORMAT_PLAIN,
- );
+ ];
if (isset($knownformats[$format])) {
return $knownformats[$format];
} else {
@@ -218,7 +218,7 @@ function block_workflow_convert_editor_format($format) {
function block_workflow_can_make_changes($state) {
global $USER;
- static $canmakechanges = array();
+ static $canmakechanges = [];
$context = $state->context();
@@ -270,9 +270,9 @@ function block_workflow_get_active_steps_with_fields_not_null($stepoptions) {
AND (ctx.contextlevel = :coursecotext OR ctx.contextlevel = :modulecontext)
ORDER BY state.id ASC";
- $options = array('state' => BLOCK_WORKFLOW_STATE_ACTIVE,
+ $options = ['state' => BLOCK_WORKFLOW_STATE_ACTIVE,
'coursecotext' => CONTEXT_COURSE,
- 'modulecontext' => CONTEXT_MODULE);
+ 'modulecontext' => CONTEXT_MODULE];
return $DB->get_records_sql($sql, $options);
}
@@ -296,15 +296,15 @@ function block_workflow_get_offset_time($courseshortname, $courseid, $moduleid,
SELECT MIN($dbfield)
FROM $table
WHERE vle_course_short_name = ?
- ", array($courseshortname));
+ ", [$courseshortname]);
$timestamp = 0;
if ($date) {
$timestamp = strtotime($date);
}
} else if ($dbtable === 'course') {
- $timestamp = $DB->get_field('course', $dbfield, array('id' => $courseid));
+ $timestamp = $DB->get_field('course', $dbfield, ['id' => $courseid]);
} else {
- $timestamp = $DB->get_field($dbtable, $dbfield, array('id' => $moduleid));
+ $timestamp = $DB->get_field($dbtable, $dbfield, ['id' => $moduleid]);
}
if ($timestamp) {
return $timestamp + $offset;
@@ -318,7 +318,7 @@ function block_workflow_get_offset_time($courseshortname, $courseid, $moduleid,
* @return void
*/
function block_workflow_send_extra_notification() {
- $options = array('extranotify', 'extranotifyoffset', 'onextranotifyscript');
+ $options = ['extranotify', 'extranotifyoffset', 'onextranotifyscript'];
$activesteps = block_workflow_get_active_steps_with_fields_not_null($options);
if (!$activesteps) {
@@ -343,7 +343,7 @@ function block_workflow_send_extra_notification() {
}
// Cron setup user.
- cron_setup_user();
+ \core\cron::setup_user();
}
} catch (Exception $e) {
block_workflow_report_scheduled_task_error('send extra notifications', $e, $activestep);
@@ -356,7 +356,7 @@ function block_workflow_send_extra_notification() {
* @return void
*/
function block_workflow_autofinish_steps() {
- $options = array('autofinish', 'autofinishoffset', null);
+ $options = ['autofinish', 'autofinishoffset', null];
$activesteps = block_workflow_get_active_steps_with_fields_not_null($options);
if (!$activesteps) {
@@ -379,7 +379,7 @@ function block_workflow_autofinish_steps() {
$state->finish_step($newcomment, FORMAT_HTML);
// Cron setup user.
- cron_setup_user();
+ \core\cron::setup_user();
}
} catch (Exception $e) {
block_workflow_report_scheduled_task_error(
diff --git a/manage.php b/manage.php
index addc713..7575cd5 100644
--- a/manage.php
+++ b/manage.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once($CFG->libdir . '/adminlib.php');
diff --git a/movestep.php b/movestep.php
index 915ad16..08393ae 100644
--- a/movestep.php
+++ b/movestep.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
@@ -39,10 +40,10 @@
$PAGE->set_context(context_system::instance());
$PAGE->set_pagelayout('standard');
-$PAGE->set_url('/blocks/workflow/movestep.php', array('stepid' => $stepid, 'direction' => $direction));
+$PAGE->set_url('/blocks/workflow/movestep.php', ['stepid' => $stepid, 'direction' => $direction]);
// Grab the retrieve.
-$returnurl = new moodle_url('/blocks/workflow/editsteps.php', array('workflowid' => $step->workflowid));
+$returnurl = new moodle_url('/blocks/workflow/editsteps.php', ['workflowid' => $step->workflowid]);
// Work out what we'll be waspping with.
$stepno = $step->stepno;
diff --git a/overview.php b/overview.php
index 4426e23..b7c428f 100644
--- a/overview.php
+++ b/overview.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
@@ -44,14 +45,14 @@
require_capability('block/workflow:view', $PAGE->context);
// Set the page URL.
-$PAGE->set_url('/blocks/workflow/overview.php', array('contextid' => $contextid, 'workflowid' => $workflowid));
+$PAGE->set_url('/blocks/workflow/overview.php', ['contextid' => $contextid, 'workflowid' => $workflowid]);
$PAGE->set_pagelayout('standard');
$PAGE->set_course($course);
// Grab the workflow and states.
$workflow = new block_workflow_workflow($workflowid);
$stepstates = $workflow->step_states($contextid, $workflowid);
-$tparams = array('contexttitle' => $context->get_context_name(), 'workflowname' => $workflow->name);
+$tparams = ['contexttitle' => $context->get_context_name(), 'workflowname' => $workflow->name];
// Check that this workflow is assigned to this context.
$statelist = array_filter($stepstates, function ($a) {
diff --git a/removeworkflow.php b/removeworkflow.php
index b07a9fb..992ce53 100644
--- a/removeworkflow.php
+++ b/removeworkflow.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once($CFG->libdir . '/adminlib.php');
@@ -48,11 +49,11 @@
// Set various page options.
$PAGE->set_pagelayout('standard');
$PAGE->set_course($course);
-$PAGE->set_url('/blocks/workflow/removeworkflow.php', array('workflowid' => $workflowid, 'contextid' => $contextid));
+$PAGE->set_url('/blocks/workflow/removeworkflow.php', ['workflowid' => $workflowid, 'contextid' => $contextid]);
// Grab the workflow.
$workflow = new block_workflow_workflow($workflowid);
-$tparams = array('workflowname' => $workflow->name, 'contexttitle' => $context->get_context_name());
+$tparams = ['workflowname' => $workflow->name, 'contexttitle' => $context->get_context_name()];
// Check that this workflow is assigned to this context.
$stepstates = $workflow->step_states($contextid);
@@ -77,9 +78,9 @@
// The confirmation strings.
$confirmstr = get_string('removeworkflowcheck', 'block_workflow', $tparams);
$confirmurl = new moodle_url('/blocks/workflow/removeworkflow.php',
- array('workflowid' => $workflowid, 'contextid' => $contextid, 'confirm' => 1));
+ ['workflowid' => $workflowid, 'contextid' => $contextid, 'confirm' => 1]);
$returnurl = new moodle_url('/blocks/workflow/overview.php',
- array('workflowid' => $workflowid, 'contextid' => $contextid));
+ ['workflowid' => $workflowid, 'contextid' => $contextid]);
if ($confirm) {
// Confirm the session key to stop CSRF.
diff --git a/renderer.php b/renderer.php
index 7ab6409..3e55ff5 100644
--- a/renderer.php
+++ b/renderer.php
@@ -36,10 +36,11 @@ class block_workflow_renderer extends plugin_renderer_base {
/**
* Render the block for the specified state
*
- * @param object $state The block_workflow_step_state to render for
- * @return string The rendered content
+ * @param object $state The block_workflow_step_state to render for
+ * @param bool $renderforajax are we rendering this for an ajx request? (Default false: display directly in the block.)
+ * @return string The rendered HTML content
*/
- public function block_display(block_workflow_step_state $state, $ajax = false) {
+ public function block_display(block_workflow_step_state $state, $renderforajax = false) {
global $USER;
$canmakechanges = block_workflow_can_make_changes($state);
@@ -57,7 +58,7 @@ public function block_display(block_workflow_step_state $state, $ajax = false) {
$output .= html_writer::tag('h3', get_string('tobecompletedby', 'block_workflow'));
$who = '';
- $whoelse = array();
+ $whoelse = [];
// Got through the list.
foreach ($roles as $role) {
@@ -88,7 +89,7 @@ public function block_display(block_workflow_step_state $state, $ajax = false) {
$output .= html_writer::tag('span', $who);
$output .= $this->get_popup_button($roles, $context);
- $this->page->requires->yui_module('moodle-block_workflow-userinfo', 'M.block_workflow.userinfo.init');
+ $this->page->requires->js_call_amd('block_workflow/userinfo', 'init');
}
// Instructions.
@@ -98,9 +99,9 @@ public function block_display(block_workflow_step_state $state, $ajax = false) {
// Comments.
$output .= html_writer::tag('h3', get_string('comments', 'block_workflow'));
- $commentsblock = html_writer::start_tag('div', array('class' => 'block_workflow_comments'));
+ $commentsblock = html_writer::start_tag('div', ['class' => 'block_workflow_comments']);
$commenttext = shorten_text(format_text($state->comment, $state->commentformat,
- array('context' => $state->context())), BLOCK_WORKFLOW_MAX_COMMENT_LENGTH);
+ ['context' => $state->context()]), BLOCK_WORKFLOW_MAX_COMMENT_LENGTH);
if ($commenttext) {
$commentsblock .= $commenttext;
} else {
@@ -112,7 +113,7 @@ public function block_display(block_workflow_step_state $state, $ajax = false) {
// To-do list overview.
if ($todos = $state->todos()) {
$output .= html_writer::tag('h3', get_string('todolisttitle', 'block_workflow'));
- $list = html_writer::start_tag('ul', array('class' => 'block_workflow_todolist'));
+ $list = html_writer::start_tag('ul', ['class' => 'block_workflow_todolist']);
foreach ($state->todos() as $todo) {
$list .= $this->block_display_todo_item($todo, $state->id, $canmakechanges);
}
@@ -123,40 +124,25 @@ public function block_display(block_workflow_step_state $state, $ajax = false) {
if ($canmakechanges) {
// Edit comments.
$url = new moodle_url('/blocks/workflow/editcomment.php',
- array('stateid' => $state->id));
+ ['stateid' => $state->id]);
$editbutton = new single_button($url, get_string('editcomments', 'block_workflow'), 'get');
$editbutton->class = 'singlebutton block_workflow_editcommentbutton';
$output .= html_writer::tag('div', $this->output->render($editbutton));
- if (!$ajax) {
- // Output the contents of the edit comment dialogue, hidden.
- // Prepare editor.
- $editor = new MoodleQuickForm_editor('comment_editor', get_string('commentlabel', 'block_workflow'),
- array('id' => 'wkf-comment-editor'), block_workflow_editor_options());
- $editor->setValue(array('text' => $state->comment));
-
- $output .= '
-
-
' .
+ if (!$renderforajax) {
+
+ $output .= '
+
' .
$this->pix_icon('i/loading', get_string('loading', 'admin'), 'moodle',
- array('class' => 'loading-icon')) . '
+ ['class' => 'loading-icon']) . '
';
}
// Finish step.
$url = new moodle_url('/blocks/workflow/finishstep.php',
- array('stateid' => $state->id));
+ ['stateid' => $state->id]);
$finishbutton = new single_button($url, get_string('finishstep', 'block_workflow'), 'get');
$finishbutton->class = 'singlebutton block_workflow_finishstepbutton';
@@ -175,8 +161,8 @@ public function block_display(block_workflow_step_state $state, $ajax = false) {
* @return string HTML of the button.
*/
public function workflow_overview_button($contextid, $workflowid) {
- $url = new moodle_url('/blocks/workflow/overview.php', array(
- 'contextid' => $contextid, 'workflowid' => $workflowid));
+ $url = new moodle_url('/blocks/workflow/overview.php', [
+ 'contextid' => $contextid, 'workflowid' => $workflowid]);
$overviewbutton = new single_button($url,
get_string('workflowoverview', 'block_workflow'), 'get');
return html_writer::tag('div', $this->output->render($overviewbutton));
@@ -192,7 +178,7 @@ public function workflow_overview_button($contextid, $workflowid) {
*/
public function block_display_todo_item($todo, $stateid, $editable) {
global $CFG;
- $todoattribs = array();
+ $todoattribs = [];
// The contents of the list item.
$text = format_string($todo->task);
@@ -206,9 +192,9 @@ public function block_display_todo_item($todo, $stateid, $editable) {
// Generate the URL and Link.
$returnurl = str_replace($CFG->wwwroot, '', $this->page->url->out(false));
$url = new moodle_url('/blocks/workflow/toggletaskdone.php',
- array('sesskey' => sesskey(), 'stateid' => $stateid, 'todoid' => $todo->id, 'returnurl' => $returnurl));
+ ['sesskey' => sesskey(), 'stateid' => $stateid, 'todoid' => $todo->id, 'returnurl' => $returnurl]);
$li = html_writer::tag('li', html_writer::link($url, $text,
- array('class' => 'block-workflow-todotask', 'id' => 'block-workflow-todoid-' . $todo->id)),
+ ['class' => 'block-workflow-todotask', 'id' => 'block-workflow-todoid-' . $todo->id]),
$todoattribs);
} else {
$li = html_writer::tag('li', $text, $todoattribs);
@@ -227,7 +213,7 @@ public function block_display_todo_item($todo, $stateid, $editable) {
* @return string the HTML to output.
*/
public function block_display_no_more_steps($parentcontextid,
- $canadd, array $addableworkflows, array $previous = null) {
+ $canadd, array $addableworkflows, ?array $previous = null) {
$output = '';
if ($previous) {
@@ -247,9 +233,9 @@ public function block_display_no_more_steps($parentcontextid,
if ($addableworkflows) {
$url = new moodle_url('/blocks/workflow/addworkflow.php',
- array('sesskey' => sesskey(), 'contextid' => $parentcontextid));
+ ['sesskey' => sesskey(), 'contextid' => $parentcontextid]);
- $addoptions = array();
+ $addoptions = [];
foreach ($addableworkflows as $wf) {
$addoptions[$wf->id] = $wf->name;
}
@@ -314,9 +300,9 @@ protected function list_workflows($workflows) {
// Display the current workflows.
$table = new html_table();
$table->attributes['class'] = '';
- $table->head = array();
- $table->colclasses = array();
- $table->data = array();
+ $table->head = [];
+ $table->colclasses = [];
+ $table->data = [];
$table->head[] = get_string('shortname', 'block_workflow');
$table->head[] = get_string('name', 'block_workflow');
$table->head[] = get_string('appliesto', 'block_workflow');
@@ -331,25 +317,29 @@ protected function list_workflows($workflows) {
// Create a new workflow.
$emptycell = new html_table_cell();
$emptycell->colspan = 3;
- $actions = array();
- $add = html_writer::empty_tag('img', array('src' => $this->output->image_url('t/add'),
- 'class' => 'iconsmall',
- 'title' => get_string('createworkflow', 'block_workflow'),
- 'alt' => get_string('createworkflow', 'block_workflow')
- ));
+ $actions = [];
+ $add = html_writer::empty_tag('img',
+ [
+ 'src' => $this->output->image_url('t/add'),
+ 'class' => 'iconsmall icon',
+ 'title' => get_string('createworkflow', 'block_workflow'),
+ 'alt' => get_string('createworkflow', 'block_workflow'),
+ ]);
$url = new moodle_url('/blocks/workflow/editsettings.php');
$actions[] = html_writer::link($url, $add);
- $add = html_writer::empty_tag('img', array('src' => $this->output->image_url('t/restore'),
- 'class' => 'iconsmall',
- 'title' => get_string('importworkflow', 'block_workflow'),
- 'alt' => get_string('importworkflow', 'block_workflow')
- ));
+ $add = html_writer::empty_tag('img',
+ [
+ 'src' => $this->output->image_url('t/restore'),
+ 'class' => 'iconsmall icon',
+ 'title' => get_string('importworkflow', 'block_workflow'),
+ 'alt' => get_string('importworkflow', 'block_workflow'),
+ ]);
$url = new moodle_url('/blocks/workflow/import.php');
$actions[] = html_writer::link($url, $add);
$addimportcell = new html_table_cell(implode(' ', $actions));
$addimportcell->attributes['class'] = 'mdl-align';
- $row = new html_table_row(array($emptycell, $addimportcell));
+ $row = new html_table_row([$emptycell, $addimportcell]);
$table->data[] = $row;
$output .= html_writer::table($table);
return $output;
@@ -382,71 +372,71 @@ protected function workflow_row(stdClass $workflow) {
$row->cells[] = $cell;
// View/Edit steps.
- $url = new moodle_url('/blocks/workflow/editsteps.php', array('workflowid' => $workflow->id));
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array(
+ $url = new moodle_url('/blocks/workflow/editsteps.php', ['workflowid' => $workflow->id]);
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/edit'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('vieweditworkflow', 'block_workflow'),
- 'alt' => get_string('vieweditworkflow', 'block_workflow')
- )));
+ 'alt' => get_string('vieweditworkflow', 'block_workflow'),
+ ]));
// Export workflow.
- $url = new moodle_url('/blocks/workflow/export.php', array('sesskey' => sesskey(), 'workflowid' => $workflow->id));
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array(
+ $url = new moodle_url('/blocks/workflow/export.php', ['sesskey' => sesskey(), 'workflowid' => $workflow->id]);
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/backup'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('exportworkflow', 'block_workflow'),
- 'alt' => get_string('exportworkflow', 'block_workflow')
- )));
+ 'alt' => get_string('exportworkflow', 'block_workflow'),
+ ]));
// Clone workflow.
- $url = new moodle_url('/blocks/workflow/clone.php', array('workflowid' => $workflow->id));
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array(
+ $url = new moodle_url('/blocks/workflow/clone.php', ['workflowid' => $workflow->id]);
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/copy'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('cloneworkflow', 'block_workflow'),
- 'alt' => get_string('cloneworkflow', 'block_workflow')
- )));
+ 'alt' => get_string('cloneworkflow', 'block_workflow'),
+ ]));
// Disable/Enable workflow.
$cell = new html_table_cell();
if ($workflow->obsolete == BLOCK_WORKFLOW_ENABLED) {
$url = new moodle_url('/blocks/workflow/toggleworkflowobsolete.php',
- array('sesskey' => sesskey(), 'workflowid' => $workflow->id));
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array(
+ ['sesskey' => sesskey(), 'workflowid' => $workflow->id]);
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/hide'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('disableworkflow', 'block_workflow'),
- 'alt' => get_string('disableworkflow', 'block_workflow')
- )));
+ 'alt' => get_string('disableworkflow', 'block_workflow'),
+ ]));
} else {
$url = new moodle_url('/blocks/workflow/toggleworkflowobsolete.php',
- array('sesskey' => sesskey(), 'workflowid' => $workflow->id));
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array(
+ ['sesskey' => sesskey(), 'workflowid' => $workflow->id]);
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/show'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('enableworkflow', 'block_workflow'),
- 'alt' => get_string('enableworkflow', 'block_workflow')
- )));
+ 'alt' => get_string('enableworkflow', 'block_workflow'),
+ ]));
}
// Remove workflow.
if ($workflow->is_deletable) {
- $url = new moodle_url('/blocks/workflow/delete.php', array('workflowid' => $workflow->id));
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array(
+ $url = new moodle_url('/blocks/workflow/delete.php', ['workflowid' => $workflow->id]);
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/delete'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('removeworkflow', 'block_workflow'),
- 'alt' => get_string('removeworkflow', 'block_workflow')
- )));
+ 'alt' => get_string('removeworkflow', 'block_workflow'),
+ ]));
} else {
$a = block_workflow_workflow::in_use_by($workflow->id);
- $actions[] = html_writer::empty_tag('img', array(
+ $actions[] = html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/delete'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('cannotdeleteworkflowinuseby', 'block_workflow', $a),
- 'alt' => get_string('removeworkflow', 'block_workflow')
- ));
+ 'alt' => get_string('removeworkflow', 'block_workflow'),
+ ]);
}
$cell = new html_table_cell(implode(' ', $actions));
@@ -480,15 +470,17 @@ protected function list_emails(array $emails) {
// Create a new email.
$emptycell = new html_table_cell();
$emptycell->colspan = 2;
- $add = html_writer::empty_tag('img', array('src' => $this->output->image_url('t/add'),
- 'class' => 'iconsmall',
- 'title' => get_string('addemail', 'block_workflow'),
- 'alt' => get_string('addemail', 'block_workflow')
- ));
+ $add = html_writer::empty_tag('img',
+ [
+ 'src' => $this->output->image_url('t/add'),
+ 'class' => 'iconsmall icon',
+ 'title' => get_string('addemail', 'block_workflow'),
+ 'alt' => get_string('addemail', 'block_workflow'),
+ ]);
$url = new moodle_url('/blocks/workflow/editemail.php');
$addnewcell = new html_table_cell(html_writer::link($url, $add));
$addnewcell->attributes['class'] = 'mdl-align';
- $row = new html_table_row(array($emptycell, $addnewcell));
+ $row = new html_table_row([$emptycell, $addnewcell]);
$table->data[] = $row;
$output .= html_writer::table($table);
@@ -516,30 +508,30 @@ protected function email_row(stdClass $email) {
$row->cells[] = $cell;
// View/Edit steps.
- $url = new moodle_url('/blocks/workflow/editemail.php', array('emailid' => $email->id));
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array(
+ $url = new moodle_url('/blocks/workflow/editemail.php', ['emailid' => $email->id]);
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/edit'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('vieweditemail', 'block_workflow'),
'alt' => get_string('vieweditemail', 'block_workflow'),
- )));
+ ]));
// Remove email.
if ($email->activecount || $email->completecount) {
- $actions[] = html_writer::empty_tag('img', array(
+ $actions[] = html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/delete'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('cannotremoveemailinuse', 'block_workflow'),
'alt' => get_string('deleteemail', 'block_workflow'),
- ));
+ ]);
} else {
- $url = new moodle_url('/blocks/workflow/deleteemail.php', array('emailid' => $email->id));
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array(
+ $url = new moodle_url('/blocks/workflow/deleteemail.php', ['emailid' => $email->id]);
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/delete'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('deleteemail', 'block_workflow'),
'alt' => get_string('deleteemail', 'block_workflow'),
- )));
+ ]));
}
// Add the steps.
@@ -581,19 +573,21 @@ public function list_steps($workflow) {
$info->appliesto = $workflow->appliesto;
// The image to add a new step.
- $add = html_writer::empty_tag('img', array('src' => $this->output->image_url('t/add'),
- 'class' => 'iconsmall',
- 'title' => get_string('addstep', 'block_workflow'),
- 'alt' => get_string('addstep', 'block_workflow')
- ));
+ $add = html_writer::empty_tag('img',
+ [
+ 'src' => $this->output->image_url('t/add'),
+ 'class' => 'iconsmall icon',
+ 'title' => get_string('addstep', 'block_workflow'),
+ 'alt' => get_string('addstep', 'block_workflow'),
+ ]);
// Add a step to the beginning.
$addempty = new html_table_cell();
$addempty->colspan = 5;
$addcell = new html_table_cell(html_writer::link(new moodle_url('/blocks/workflow/editstep.php',
- array('workflowid' => $workflow->id, 'beforeafter' => -1)), $add));
+ ['workflowid' => $workflow->id, 'beforeafter' => -1]), $add));
$addcell->attributes['class'] = 'mdl-align';
- $addrow = new html_table_row(array($addempty, $addcell));
+ $addrow = new html_table_row([$addempty, $addcell]);
$table->data[] = $addrow;
// Process the other steps.
@@ -609,11 +603,11 @@ public function list_steps($workflow) {
$infocell->colspan = 5;
$infocell->attributes['class'] = 'mdl-align';
- $url = new moodle_url('/blocks/workflow/editstep.php', array('workflowid' => $workflow->id));
+ $url = new moodle_url('/blocks/workflow/editstep.php', ['workflowid' => $workflow->id]);
$addnewcell = new html_table_cell(html_writer::link($url, $add));
$addnewcell->attributes['class'] = 'mdl-align';
- $row = new html_table_row(array($infocell, $addnewcell));
+ $row = new html_table_row([$infocell, $addnewcell]);
$table->data[] = $row;
// Display the table.
@@ -622,6 +616,13 @@ public function list_steps($workflow) {
return $output;
}
+ /**
+ * Renders a single workflow step.
+ *
+ * @param object $step The workflow step object containing step details.
+ * @param object $info Additional information related to the workflow step.
+ * @return html_table_row The rendered HTML output for the workflow step.
+ */
protected function workflow_step($step, $info) {
$row = new html_table_row();
@@ -647,57 +648,60 @@ protected function workflow_step($step, $info) {
$row->cells[] = $cell;
// Modification.
- $actions = array();
- $url = new moodle_url('/blocks/workflow/editstep.php', array('stepid' => $step->id));
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array('src' => $this->output->image_url('t/edit'),
- 'class' => 'iconsmall',
- 'title' => get_string('editstep', 'block_workflow'),
- 'alt' => get_string('editstep', 'block_workflow')
- )));
+ $actions = [];
+ $url = new moodle_url('/blocks/workflow/editstep.php', ['stepid' => $step->id]);
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img',
+ [
+ 'src' => $this->output->image_url('t/edit'),
+ 'class' => 'iconsmall icon',
+ 'title' => get_string('editstep', 'block_workflow'),
+ 'alt' => get_string('editstep', 'block_workflow'),
+ ]
+ ));
// Add step after this one.
$url = new moodle_url('/blocks/workflow/editstep.php',
- array('workflowid' => $info->workflowid, 'beforeafter' => $step->stepno));
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array(
+ ['workflowid' => $info->workflowid, 'beforeafter' => $step->stepno]);
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/add'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('addstepafter', 'block_workflow'),
- 'alt' => get_string('addstepafter', 'block_workflow')
- )));
+ 'alt' => get_string('addstepafter', 'block_workflow'),
+ ]));
// Can't be removed if this is the only step or in use.
if ($info->stepcount != 1 && !block_workflow_step::is_step_in_use($step->id)) {
- $url = new moodle_url('/blocks/workflow/deletestep.php', array('stepid' => $step->id));
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array(
+ $url = new moodle_url('/blocks/workflow/deletestep.php', ['stepid' => $step->id]);
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/delete'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('removestep', 'block_workflow'),
- 'alt' => get_string('removestep', 'block_workflow')
- )));
+ 'alt' => get_string('removestep', 'block_workflow'),
+ ]));
}
// Move up if this is not the first step.
if ($step->stepno != 1) {
$url = new moodle_url('/blocks/workflow/movestep.php',
- array('sesskey' => sesskey(), 'id' => $step->id, 'direction' => 'up'));
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array(
+ ['sesskey' => sesskey(), 'id' => $step->id, 'direction' => 'up']);
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/up'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('moveup', 'block_workflow'),
- 'alt' => get_string('moveup', 'block_workflow')
- )));
+ 'alt' => get_string('moveup', 'block_workflow'),
+ ]));
}
// Move down if this is not the final step.
if (!isset($step->finalstep)) {
$url = new moodle_url('/blocks/workflow/movestep.php',
- array('sesskey' => sesskey(), 'id' => $step->id, 'direction' => 'down'));
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array(
+ ['sesskey' => sesskey(), 'id' => $step->id, 'direction' => 'down']);
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/down'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('movedown', 'block_workflow'),
- 'alt' => get_string('movedown', 'block_workflow')
- )));
+ 'alt' => get_string('movedown', 'block_workflow'),
+ ]));
}
$cell = new html_table_cell(implode(' ', $actions));
@@ -755,13 +759,19 @@ protected function workflow_step_auto_finish($step, $appliesto) {
*/
protected function workflow_step_doers($stepdata) {
$step = block_workflow_step::make($stepdata);
- $doernames = array();
+ $doernames = [];
foreach ($step->roles() as $doer) {
$doernames[] = $doer->localname;
}
return implode(', ', $doernames);
}
+ /**
+ * Displays detailed information about the given workflow.
+ *
+ * @param object $workflow The workflow object containing workflow details to be displayed.
+ * @return string The rendered HTML output for the workflow information.
+ */
protected function workflow_information($workflow) {
$output = '';
@@ -770,29 +780,29 @@ protected function workflow_information($workflow) {
$table = $this->setup_table();
// Workflow name and shortname.
- $row = new html_table_row(array(get_string('name', 'block_workflow')));
+ $row = new html_table_row([get_string('name', 'block_workflow')]);
$cell = new html_table_cell();
- $data = array('name' => format_string($workflow->name), 'shortname' => s($workflow->shortname));
+ $data = ['name' => format_string($workflow->name), 'shortname' => s($workflow->shortname)];
$cell->text = get_string('nameshortname', 'block_workflow', $data);
$row->cells[] = $cell;
$table->data[] = $row;
// Description.
- $row = new html_table_row(array(get_string('description', 'block_workflow')));
+ $row = new html_table_row([get_string('description', 'block_workflow')]);
$cell = new html_table_cell();
$cell->text = format_text($workflow->description, $workflow->descriptionformat);
$row->cells[] = $cell;
$table->data[] = $row;
// What contexts does this block apply to.
- $row = new html_table_row(array(get_string('appliesto', 'block_workflow')));
+ $row = new html_table_row([get_string('appliesto', 'block_workflow')]);
$cell = new html_table_cell();
$cell->text = $workflow->appliesto;
$row->cells[] = $cell;
$table->data[] = $row;
// Status information.
- $row = new html_table_row(array(get_string('status', 'block_workflow')));
+ $row = new html_table_row([get_string('status', 'block_workflow')]);
$cell = new html_table_cell();
if ($workflow->obsolete == BLOCK_WORKFLOW_OBSOLETE) {
$cell->text = get_string('obsoleteworkflow', 'block_workflow');
@@ -803,7 +813,7 @@ protected function workflow_information($workflow) {
$table->data[] = $row;
// Other info.
- $row = new html_table_row(array(get_string('inuseby', 'block_workflow')));
+ $row = new html_table_row([get_string('inuseby', 'block_workflow')]);
$cell = new html_table_cell('This workflow is active in x contexts');
$row->cells[] = $cell;
$table->data[] = $row;
@@ -829,36 +839,36 @@ public function display_workflow($workflow) {
$table->attributes['class'] = '';
// Shortname.
- $row = new html_table_row(array(
+ $row = new html_table_row([
get_string('shortname', 'block_workflow'),
s($workflow->shortname),
- ));
+ ]);
$table->data[] = $row;
// Name.
- $row = new html_table_row(array(
+ $row = new html_table_row([
get_string('name', 'block_workflow'),
format_string($workflow->name),
- ));
+ ]);
$table->data[] = $row;
// Description.
- $row = new html_table_row(array(
+ $row = new html_table_row([
get_string('description', 'block_workflow'),
format_text($workflow->description, $workflow->descriptionformat),
- ));
+ ]);
$table->data[] = $row;
// Applies to.
- $row = new html_table_row(array(
+ $row = new html_table_row([
get_string('thisworkflowappliesto', 'block_workflow'),
block_workflow_appliesto($workflow->appliesto),
- ));
+ ]);
$table->data[] = $row;
// Current status.
$togglelink = new moodle_url('/blocks/workflow/toggleworkflowobsolete.php',
- array('workflowid' => $workflow->id, 'returnto' => 'editsteps', 'sesskey' => sesskey()));
+ ['workflowid' => $workflow->id, 'returnto' => 'editsteps', 'sesskey' => sesskey()]);
if ($workflow->obsolete) {
$status = get_string('workflowobsolete', 'block_workflow', $togglelink->out());
} else {
@@ -871,10 +881,10 @@ public function display_workflow($workflow) {
$status .= get_string('notcurrentlyinuse', 'block_workflow');
}
- $row = new html_table_row(array(
+ $row = new html_table_row([
get_string('workflowstatus', 'block_workflow'),
- $status
- ));
+ $status,
+ ]);
$table->data[] = $row;
// Workflow actions.
@@ -883,23 +893,23 @@ public function display_workflow($workflow) {
$cell->colspan = 2;
$cell->attributes['class'] = 'mdl-align';
- $actions = array();
+ $actions = [];
// Edit the workflow.
- $url = new moodle_url('/blocks/workflow/editsettings.php', array('workflowid' => $workflow->id));
+ $url = new moodle_url('/blocks/workflow/editsettings.php', ['workflowid' => $workflow->id]);
$actions[] = html_writer::link($url, get_string('edit', 'block_workflow'));
// Clone the workflow.
- $url = new moodle_url('/blocks/workflow/clone.php', array('workflowid' => $workflow->id));
+ $url = new moodle_url('/blocks/workflow/clone.php', ['workflowid' => $workflow->id]);
$actions[] = html_writer::link($url, get_string('clone', 'block_workflow'));
// Export the workflow.
- $url = new moodle_url('/blocks/workflow/export.php', array('sesskey' => sesskey(), 'workflowid' => $workflow->id));
+ $url = new moodle_url('/blocks/workflow/export.php', ['sesskey' => sesskey(), 'workflowid' => $workflow->id]);
$actions[] = html_writer::link($url, get_string('export', 'block_workflow'));
if (block_workflow_workflow::is_workflow_deletable($workflow->id)) {
// Delete the workflow.
- $url = new moodle_url('/blocks/workflow/delete.php', array('workflowid' => $workflow->id));
+ $url = new moodle_url('/blocks/workflow/delete.php', ['workflowid' => $workflow->id]);
$actions[] = html_writer::link($url, get_string('delete', 'block_workflow'));
}
@@ -914,6 +924,13 @@ public function display_workflow($workflow) {
return $output;
}
+ /**
+ * Renders the to-do list for a given workflow step.
+ *
+ * @param array $todos An array of to-do items associated with the workflow step.
+ * @param object $step The workflow step object for which the to-do list is being rendered.
+ * @return string The HTML output for the to-do list.
+ */
public function step_todolist($todos, $step) {
$output = '';
@@ -932,15 +949,16 @@ public function step_todolist($todos, $step) {
// Add option to add a new task.
$emptycell = new html_table_cell();
- $add = html_writer::empty_tag('img', array('src' => $this->output->image_url('t/add'),
- 'class' => 'iconsmall',
- 'title' => get_string('addtask', 'block_workflow'),
- 'alt' => get_string('addtask', 'block_workflow')
- ));
- $url = new moodle_url('/blocks/workflow/edittask.php', array('stepid' => $step->id));
+ $add = html_writer::empty_tag('img', [
+ 'src' => $this->output->image_url('t/add'),
+ 'class' => 'iconsmall icon',
+ 'title' => get_string('addtask', 'block_workflow'),
+ 'alt' => get_string('addtask', 'block_workflow'),
+ ]);
+ $url = new moodle_url('/blocks/workflow/edittask.php', ['stepid' => $step->id]);
$addnewcell = new html_table_cell(html_writer::link($url, $add));
- $row = new html_table_row(array($emptycell, $addnewcell));
+ $row = new html_table_row([$emptycell, $addnewcell]);
$table->data[] = $row;
// Display the table.
@@ -948,52 +966,71 @@ public function step_todolist($todos, $step) {
return $output;
}
+
+ /**
+ * Renders a to-do list item for a workflow step.
+ *
+ * @param stdClass $task The task object containing information about the workflow step.
+ * @return string The HTML output for the to-do list item.
+ */
protected function step_todolist_item(stdClass $task) {
$row = new html_table_row();
$name = new html_table_cell(format_string($task->task));
- $actions = array();
+ $actions = [];
- $url = new moodle_url('/blocks/workflow/edittask.php', array('id' => $task->id));
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array('src' => $this->output->image_url('t/edit'),
- 'class' => 'iconsmall',
- 'title' => get_string('edittask', 'block_workflow'),
- 'alt' => get_string('edittask', 'block_workflow')
- )));
+ $url = new moodle_url('/blocks/workflow/edittask.php', ['id' => $task->id]);
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img', [
+ 'src' => $this->output->image_url('t/edit'),
+ 'class' => 'iconsmall icon',
+ 'title' => get_string('edittask', 'block_workflow'),
+ 'alt' => get_string('edittask', 'block_workflow'),
+ ]));
// Obsolete task.
- $url = new moodle_url('/blocks/workflow/toggletaskobsolete.php', array('sesskey' => sesskey(), 'taskid' => $task->id));
+ $url = new moodle_url('/blocks/workflow/toggletaskobsolete.php', ['sesskey' => sesskey(), 'taskid' => $task->id]);
if ($task->obsolete == BLOCK_WORKFLOW_ENABLED) {
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array('src' => $this->output->image_url('t/hide'),
- 'class' => 'iconsmall',
- 'title' => get_string('hidetask', 'block_workflow'),
- 'alt' => get_string('hidetask', 'block_workflow')
- )));
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img', [
+ 'src' => $this->output->image_url('t/hide'),
+ 'class' => 'iconsmall icon',
+ 'title' => get_string('hidetask', 'block_workflow'),
+ 'alt' => get_string('hidetask', 'block_workflow'),
+ ]));
} else {
- $actions[] = html_writer::link($url, html_writer::empty_tag('img', array('src' => $this->output->image_url('t/show'),
- 'class' => 'iconsmall',
- 'title' => get_string('showtask', 'block_workflow'),
- 'alt' => get_string('showtask', 'block_workflow')
- )));
+ $actions[] = html_writer::link($url, html_writer::empty_tag('img', [
+ 'src' => $this->output->image_url('t/show'),
+ 'class' => 'iconsmall icon',
+ 'title' => get_string('showtask', 'block_workflow'),
+ 'alt' => get_string('showtask', 'block_workflow'),
+ ]));
}
// Delete task.
if ($task->isremovable) {
- $url = new moodle_url('/blocks/workflow/deletetask.php', array('id' => $task->id));
+ $url = new moodle_url('/blocks/workflow/deletetask.php', ['id' => $task->id]);
$actions[] = html_writer::link($url,
- html_writer::empty_tag('img', array('src' => $this->output->image_url('t/delete'),
- 'class' => 'iconsmall',
- 'title' => get_string('removetask', 'block_workflow'),
- 'alt' => get_string('removetask', 'block_workflow')
- )));
+ html_writer::empty_tag('img', [
+ 'src' => $this->output->image_url('t/delete'),
+ 'class' => 'iconsmall icon',
+ 'title' => get_string('removetask', 'block_workflow'),
+ 'alt' => get_string('removetask', 'block_workflow'),
+ ]));
}
$actions = new html_table_cell(implode(' ', $actions));
// Put it all together into a row and return the data.
- $row = new html_table_row(array($name, $actions));
+ $row = new html_table_row([$name, $actions]);
return $row;
}
+ /**
+ * Generates the step doers.
+ *
+ * @param array $roles Array of role objects or IDs relevant to the workflow step.
+ * @param array $doers Array of user objects or IDs who are assigned as doers for the step.
+ * @param int $stepid The unique identifier of the workflow step.
+ * @return string HTML output displaying the doers for the specified step.
+ */
public function step_doers($roles, $doers, $stepid) {
$output = '';
@@ -1023,30 +1060,38 @@ public function step_doers($roles, $doers, $stepid) {
return $output;
}
+
+ /**
+ * Returns the user or entity responsible for performing a specific workflow step.
+ *
+ * @param object $role The role or identifier of the doer.
+ * @param int $stepid The ID of the workflow step.
+ * @return string The doer of the specified workflow step.
+ */
protected function step_doer($role, $stepid) {
$row = new html_table_row();
$name = new html_table_cell($role->localname);
$url = new moodle_url('/blocks/workflow/togglerole.php',
- array('sesskey' => sesskey(), 'roleid' => $role->id, 'stepid' => $stepid));
+ ['sesskey' => sesskey(), 'roleid' => $role->id, 'stepid' => $stepid]);
if ($role->doer) {
- $actions = html_writer::link($url, html_writer::empty_tag('img', array(
+ $actions = html_writer::link($url, html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/delete'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('removerolefromstep', 'block_workflow'),
- 'alt' => get_string('removerolefromstep', 'block_workflow')
- )));
+ 'alt' => get_string('removerolefromstep', 'block_workflow'),
+ ]));
} else {
- $actions = html_writer::link($url, html_writer::empty_tag('img', array(
+ $actions = html_writer::link($url, html_writer::empty_tag('img', [
'src' => $this->output->image_url('t/add'),
- 'class' => 'iconsmall',
+ 'class' => 'iconsmall icon',
'title' => get_string('addroletostep', 'block_workflow'),
- 'alt' => get_string('addroletostep', 'block_workflow')
- )));
+ 'alt' => get_string('addroletostep', 'block_workflow'),
+ ]));
}
// Put it all together into a row and return the data.
- $row = new html_table_row(array($name, $actions));
+ $row = new html_table_row([$name, $actions]);
return $row;
}
@@ -1129,9 +1174,9 @@ public function create_step_instructions(block_workflow_workflow $workflow) {
*/
protected function setup_table() {
$table = new html_table();
- $table->head = array();
- $table->colclasses = array();
- $table->data = array();
+ $table->head = [];
+ $table->colclasses = [];
+ $table->data = [];
return $table;
}
@@ -1144,6 +1189,14 @@ protected function get_box_start_css_classes() {
return 'generalbox boxwidthwide boxaligncenter';
}
+ /**
+ * Renders the overview of a workflow.
+ *
+ * @param object $workflow The workflow object containing workflow details.
+ * @param array $states An array of workflow states.
+ * @param object $context The context in which the workflow is being rendered.
+ * @return string The rendered HTML output for the workflow overview.
+ */
public function workflow_overview($workflow, array $states, $context) {
$output = '';
@@ -1165,24 +1218,31 @@ public function workflow_overview($workflow, array $states, $context) {
foreach ($states as $state) {
$table->data[] = $this->workflow_overview_step($state, $context);
}
- $this->page->requires->yui_module('moodle-block_workflow-userinfo', 'M.block_workflow.userinfo.init');
+ $this->page->requires->js_call_amd('block_workflow/userinfo', 'init');
// Put everything together and return.
$output .= html_writer::table($table);
// Put text and button after the table.
- $output .= html_writer::tag('div', $this->atendgobackto($workflow), array('id' => 'text-after-table'));
+ $output .= html_writer::tag('div', $this->atendgobackto($workflow), ['id' => 'text-after-table']);
if (has_capability('block/workflow:manage', $context)) {
$url = new moodle_url('/blocks/workflow/removeworkflow.php',
- array('contextid' => $context->id, 'workflowid' => $workflow->id));
+ ['contextid' => $context->id, 'workflowid' => $workflow->id]);
$output .= $this->output->render(new single_button($url, get_string('removeworkflow', 'block_workflow')));
}
$output .= $this->box_end();
return $output;
}
+ /**
+ * Renders the overview for a specific workflow step.
+ *
+ * @param stdClass $stepstate The current state of the workflow step.
+ * @param object $context The context in which the workflow is being rendered.
+ * @return string The rendered HTML output for the workflow step overview.
+ */
private function workflow_overview_step($stepstate, $context) {
$row = new html_table_row();
- $classes = array('step');
+ $classes = ['step'];
// Add some CSS classes to help colour-code the states.
if ($stepstate->state == BLOCK_WORKFLOW_STATE_ACTIVE) {
@@ -1202,7 +1262,7 @@ private function workflow_overview_step($stepstate, $context) {
$complete = html_writer::tag('span',
get_string('percentcomplete', 'block_workflow',
format_float($stepstate->complete, 0)),
- array('class' => 'completeinfo'));
+ ['class' => 'completeinfo']);
} else {
$complete = '';
}
@@ -1233,7 +1293,7 @@ private function workflow_overview_step($stepstate, $context) {
// Comments.
$cell = new html_table_cell();
- $cell->text = format_text($stepstate->comment, $stepstate->commentformat, array('context' => $context));
+ $cell->text = format_text($stepstate->comment, $stepstate->commentformat, ['context' => $context]);
if (!$cell->text) {
$cell->text = get_string('nocomment', 'block_workflow');
}
@@ -1253,7 +1313,7 @@ private function workflow_overview_step($stepstate, $context) {
$cell = new html_table_cell();
if ($stepstate->timemodified) {
$cell->text = $stepstate->modifieduser . html_writer::tag('span',
- userdate($stepstate->timemodified), array('class' => 'dateinfo'));
+ userdate($stepstate->timemodified), ['class' => 'dateinfo']);
}
$cell->attributes['class'] = 'mdl-align';
$row->cells[] = $cell;
@@ -1282,10 +1342,16 @@ private function workflow_overview_step($stepstate, $context) {
return $row;
}
+ /**
+ * Generates the step history overview for a given workflow state.
+ *
+ * @param int $stateid The ID of the workflow state to retrieve the step history for.
+ * @return string The rendered HTML output of the step history overview.
+ */
private function workflow_overview_step_history($stateid) {
- $history = array();
+ $history = [];
foreach (block_workflow_step_state::state_changes($stateid) as $change) {
- $a = array();
+ $a = [];
$a['newstate'] = get_string('state_history_' . $change->newstate, 'block_workflow');
$a['time'] = userdate($change->timestamp);
$a['user'] = $change->username;
@@ -1302,7 +1368,7 @@ private function workflow_overview_step_history($stateid) {
*/
protected function atendgobackto($workflow) {
// At end go back to ...
- $a = array();
+ $a = [];
// ... count the steps.
$a['stepcount'] = count($workflow->steps());
@@ -1321,7 +1387,7 @@ protected function atendgobackto($workflow) {
* @return String The rendered button to take the user to the finishstep form
*/
protected function finish_step($stateid) {
- $url = new moodle_url('/blocks/workflow/finishstep.php', array('stateid' => $stateid));
+ $url = new moodle_url('/blocks/workflow/finishstep.php', ['stateid' => $stateid]);
return $this->output->render(new single_button($url, get_string('finishstep', 'block_workflow'), 'get'));
}
@@ -1332,7 +1398,7 @@ protected function finish_step($stateid) {
* @return String The rendered button to take the user to the jumptostep form
*/
protected function jump_to_step($stepid, $contextid) {
- $url = new moodle_url('/blocks/workflow/jumptostep.php', array('stepid' => $stepid, 'contextid' => $contextid));
+ $url = new moodle_url('/blocks/workflow/jumptostep.php', ['stepid' => $stepid, 'contextid' => $contextid]);
return $this->output->render(new single_button($url, get_string('jumptostep', 'block_workflow'), 'get'));
}
@@ -1380,16 +1446,16 @@ protected function get_popup_table($users, $stepno) {
// Get extra user information from the user policies settings.
$extrafields = \core_user\fields::get_identity_fields($this->page->context, true);
// Set up the table header.
- $tableheader = array();
+ $tableheader = [];
$tableheader[] = get_string('name');
foreach ($extrafields as $field) {
$tableheader[] = \core_user\fields::get_display_name($field);
}
$tableheader[] = get_string('roles');
- $data = array();
+ $data = [];
foreach ($users as $key => $user) {
- $row = array();
+ $row = [];
$row[0] = html_writer::tag('b', fullname($user));
$extraindex = 1;
if ($extrafields) {
@@ -1419,7 +1485,7 @@ protected function get_popup_table($users, $stepno) {
$popupheader .= " (Step $stepno)";
}
// Return header and body of the popup.
- return array($popupheader, html_writer::table($table));
+ return [$popupheader, html_writer::table($table)];
}
/**
@@ -1433,7 +1499,7 @@ protected function get_popup_button($roles, $context, $stepno = 0) {
$users = $steptate->get_all_users_and_their_roles($roles, $context);
$numberofusers = $users === null ? 0 : count($users);
list ($header, $body) = $this->get_popup_table($users, $stepno);
- $options = array('class' => 'userinfoclass', 'header' => $header, 'body' => $body, 'stepno' => $stepno);
+ $options = ['class' => 'userinfoclass', 'header' => $header, 'body' => $body, 'stepno' => $stepno];
if (!$roles) {
return null;
diff --git a/styles.css b/styles.css
index 23fd842..c0d75de 100644
--- a/styles.css
+++ b/styles.css
@@ -69,11 +69,6 @@
display: block;
font-size: 0.8em;
}
-body.ie7 .moodle-dialogue-base .moodle-dialogue-hd .closebutton {
- float: none;
- position: absolute;
- right: 5px;
-}
#page-admin-blocks-workflow-manage #manage td.c2 {
font-size: 0.8em;
}
diff --git a/tests/autostepfinisher_test.php b/tests/autostepfinisher_test.php
index c5e0995..2b23894 100644
--- a/tests/autostepfinisher_test.php
+++ b/tests/autostepfinisher_test.php
@@ -32,9 +32,17 @@
require_once($CFG->dirroot . '/blocks/workflow/locallib.php');
require_once($CFG->dirroot . '/blocks/workflow/tests/lib.php');
-class autostepfinisher_test extends \block_workflow_testlib {
-
- public function test_automatic_step_finisher() {
+/**
+ * Unit tests for the autostepfinisher functionality in the block_workflow plugin.
+ */
+final class autostepfinisher_test extends \block_workflow_testlib {
+
+ /**
+ * Tests the block_workflow_autofinish_steps method.
+ *
+ * @covers ::block_workflow_autofinish_steps
+ */
+ public function test_automatic_step_finisher(): void {
global $CFG, $DB;
$now = time();
$after5days = $this->get_days(5);
@@ -47,11 +55,11 @@ public function test_automatic_step_finisher() {
$generator = $this->getDataGenerator();
// Create a course object.
- $course1 = $generator->create_course(array('shortname' => 'M123-12J', 'startdate' => $timestamp1));
+ $course1 = $generator->create_course(['shortname' => 'M123-12J', 'startdate' => $timestamp1]);
$coursecontext1 = \context_course::instance($course1->id);
// Create another course object.
- $course2 = $generator->create_course(array('shortname' => 'K123-12J', 'startdate' => $timestamp2));
+ $course2 = $generator->create_course(['shortname' => 'K123-12J', 'startdate' => $timestamp2]);
$coursecontext2 = \context_course::instance($course2->id);
// Generate a vl_v_crs_version_pres table.
@@ -65,14 +73,14 @@ public function test_automatic_step_finisher() {
$courseondataloadtable = $DB->get_record_sql(
'SELECT * FROM vl_v_crs_version_pres ' .
- 'WHERE vle_course_short_name = ?', array($courseshortname), MUST_EXIST);
+ 'WHERE vle_course_short_name = ?', [$courseshortname], MUST_EXIST);
// Create a new workflow object which applies to course.
- $stepoptions = array('autofinish' => 'course;startdate', 'autofinishoffset' => $before5days);
+ $stepoptions = ['autofinish' => 'course;startdate', 'autofinishoffset' => $before5days];
list($courseworkflow, $step1) = $this->create_a_workflow_with_one_step($stepoptions);
// Required DB tables are not populated and therefore following methods return empty arrays.
- $stepoptions = array('autofinish', 'autofinishoffset', null);
+ $stepoptions = ['autofinish', 'autofinishoffset', null];
$activesteps = block_workflow_get_active_steps_with_fields_not_null($stepoptions);
$this->assertEmpty($activesteps);
@@ -104,7 +112,7 @@ public function test_automatic_step_finisher() {
$this->assertEquals($expectedactivesteps, $activesteps);
// Check relevant fields in 'block_workflow_step_states' table before finishing automatically.
- $statebeforefinish = $DB->get_record('block_workflow_step_states', array('id' => $state1->id));
+ $statebeforefinish = $DB->get_record('block_workflow_step_states', ['id' => $state1->id]);
$this->assertEquals(BLOCK_WORKFLOW_STATE_ACTIVE, $statebeforefinish->state);
$this->assertEmpty($statebeforefinish->comment);
@@ -112,7 +120,7 @@ public function test_automatic_step_finisher() {
block_workflow_autofinish_steps();
// Check relevant fields in 'block_workflow_step_states' table after finishing automatically.
- $stateafterfinish = $DB->get_record('block_workflow_step_states', array('id' => $state1->id));
+ $stateafterfinish = $DB->get_record('block_workflow_step_states', ['id' => $state1->id]);
$this->assertEquals(BLOCK_WORKFLOW_STATE_COMPLETED, $stateafterfinish->state);
$this->assertNotEmpty($stateafterfinish->comment);
}
diff --git a/tests/behat/behat_block_workflow.php b/tests/behat/behat_block_workflow.php
index 9bb6942..755a28f 100644
--- a/tests/behat/behat_block_workflow.php
+++ b/tests/behat/behat_block_workflow.php
@@ -100,10 +100,11 @@ public function quiz_workflow_is_at_step($quizname, $stepname) {
*/
public function test_course_visibility(string $coursefullname, string $isvisible): void {
global $DB;
- $course = $DB->get_record("course", array("fullname" => $coursefullname), 'visible', MUST_EXIST);
+ $course = $DB->get_record("course", ["fullname" => $coursefullname], 'visible', MUST_EXIST);
$expectedvisibility = $isvisible == 'visible';
if ($course->visible != $expectedvisibility) {
- throw new ExpectationException('"' . $coursefullname . '" should be ' . $isvisible . ' but isn\'t.', $this->getSession());
+ throw new ExpectationException('"' . $coursefullname . '" should be ' . $isvisible . ' but isn\'t.',
+ $this->getSession());
}
}
}
diff --git a/tests/behat/use_workflow_tinymce.feature b/tests/behat/use_workflow_tinymce.feature
index 6584ac4..afcf6fc 100644
--- a/tests/behat/use_workflow_tinymce.feature
+++ b/tests/behat/use_workflow_tinymce.feature
@@ -35,7 +35,7 @@ Feature: Workflow block - follow a workflow using TinyMCE
And I upload "blocks/workflow/tests/fixtures/testworkflow.workflow.xml" file to "File" filemanager
And I press "Import workflow"
And I navigate to "Plugins > Text editors > Manage editors" in site administration
- And I click on "Disable" "link" in the "Atto HTML editor" "table_row"
+ And I click on "Disable" "checkbox" in the "TinyMCE editor" "table_row"
And I log out
When I log in as "manager1"
@@ -126,3 +126,23 @@ Feature: Workflow block - follow a workflow using TinyMCE
And I click on "Workflow overview" "button" in the "Workflow" "block"
And I should see "Complete" in the "Configure basic site" "table_row"
And I should see "Complete" in the "Prepare your web site" "table_row"
+
+ @javascript @_file_upload
+ Scenario: Add a workflow to a course and edit comment.
+ Given I log in as "admin"
+ When I navigate to "Plugins > Blocks > Workflows" in site administration
+ And I follow "Import workflow"
+ And I upload "blocks/workflow/tests/fixtures/testworkflow.workflow.xml" file to "File" filemanager
+ And I press "Import workflow"
+ And I am on "Course 1" course homepage
+ And I turn editing mode on
+ And I add the "Workflows" block
+ And I set the field "workflow" to "Test course workflow"
+ And I press "Edit comments"
+ And I set the field "Update workflow comment" to "This is a comment"
+ And I click on "Save changes" "button" in the "Edit comments" "dialogue"
+ And I press "Finish step"
+ And I should see "This is a comment"
+ And I click on "Finish step" "button" in the "Finish step" "dialogue"
+ And I press "Edit comments"
+ Then I should not see "This is a comment"
diff --git a/tests/command_test.php b/tests/command_test.php
index eae738b..5a95129 100644
--- a/tests/command_test.php
+++ b/tests/command_test.php
@@ -33,19 +33,25 @@
require_once(dirname(__FILE__) . '/../locallib.php');
require_once(dirname(__FILE__) . '/lib.php');
-class command_test extends \block_workflow_testlib {
+/**
+ * Unit test class for the block_workflow command functionality.
+ */
+final class command_test extends \block_workflow_testlib {
/**
* Test the role_exists function
* - Positive test for a known good role
* - Negative test for a known bad role (check for exception)
+ *
+ * @covers \block_workflow_command::role_exists
+ * @covers \block_workflow_command::require_role_exists
*/
- public function test_role_exists() {
+ public function test_role_exists(): void {
// First test that a known good role works.
$result = block_workflow_command::role_exists('manager');
$this->assertInstanceOf('stdClass', $result);
- $errors = array();
+ $errors = [];
$result = block_workflow_command::require_role_exists('manager', $errors);
$this->assertInstanceOf('stdClass', $result);
$this->assertEquals(count($errors), 0);
@@ -54,7 +60,7 @@ public function test_role_exists() {
$result = block_workflow_command::role_exists('invalidrole');
$this->assertFalse($result);
- $errors = array();
+ $errors = [];
$result = block_workflow_command::require_role_exists('invalidrole', $errors);
$this->assertEquals(count($errors), 1);
}
@@ -63,8 +69,10 @@ public function test_role_exists() {
* Test the type of workflow
* - Positive test for an activity (activity == true)
* - Negative test for an activity (activity == false)
+ *
+ * @covers \block_workflow_command::is_activity
*/
- public function test_is_activity() {
+ public function test_is_activity(): void {
$this->resetAfterTest(true);
diff --git a/tests/commandassignrole_test.php b/tests/commandassignrole_test.php
index 6b85482..06f93c0 100644
--- a/tests/commandassignrole_test.php
+++ b/tests/commandassignrole_test.php
@@ -34,14 +34,30 @@
global $CFG;
require_once(dirname(__FILE__) . '/lib.php');
-class commandassignrole_test extends \block_workflow_testlib {
-
- public function test_assignrole() {
+/**
+ * Unit tests for the commandassignrole functionality in the block_workflow plugin.
+ *
+ * This test class extends the block_workflow_testlib base class to provide
+ * test cases for assigning roles via workflow commands.
+ */
+final class commandassignrole_test extends \block_workflow_testlib {
+
+ /**
+ * Tests the assignrole method.
+ *
+ * @covers \block_workflow_command_assignrole
+ */
+ public function test_assignrole(): void {
$command = new block_workflow_command_assignrole();
$this->assertInstanceOf('block_workflow_command', $command);
}
- public function test_parse_no_state() {
+ /**
+ * Tests the parse method for no state.
+ *
+ * @covers \block_workflow_command_assignrole::parse
+ */
+ public function test_parse_no_state(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
@@ -79,7 +95,12 @@ public function test_parse_no_state() {
$this->assertEquals(count($result->users), 0);
}
- public function test_parse_no_state_invalid_newrole() {
+ /**
+ * Tests the parse method for no state invalid new role.
+ *
+ * @covers \block_workflow_command_assignrole::parse
+ */
+ public function test_parse_no_state_invalid_newrole(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
@@ -117,7 +138,12 @@ public function test_parse_no_state_invalid_newrole() {
$this->assertEquals(count($result->users), 0);
}
- public function test_parse_no_state_invalid_targetrole() {
+ /**
+ * Tests the parse method for no state invalid targetrole.
+ *
+ * @covers \block_workflow_command_assignrole::parse
+ */
+ public function test_parse_no_state_invalid_targetrole(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
@@ -155,7 +181,12 @@ public function test_parse_no_state_invalid_targetrole() {
$this->assertEquals(count($result->users), 0);
}
- public function test_parse_with_state() {
+ /**
+ * Tests the parse method.
+ *
+ * @covers \block_workflow_command_assignrole::parse
+ */
+ public function test_parse_with_state(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
$state = $this->assign_workflow($workflow);
@@ -196,7 +227,12 @@ public function test_parse_with_state() {
$this->assertEquals(count($result->users), 2);
}
- public function test_parse_with_state_invalid_newrole() {
+ /**
+ * Tests the parse method.
+ *
+ * @covers \block_workflow_command_assignrole::parse
+ */
+ public function test_parse_with_state_invalid_newrole(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
$state = $this->assign_workflow($workflow);
@@ -237,7 +273,12 @@ public function test_parse_with_state_invalid_newrole() {
$this->assertEquals(count($result->users), 2);
}
- public function test_parse_with_state_invalid_targetrole() {
+ /**
+ * Tests the parse method.
+ *
+ * @covers \block_workflow_command_assignrole::parse
+ */
+ public function test_parse_with_state_invalid_targetrole(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
$state = $this->assign_workflow($workflow);
@@ -278,7 +319,12 @@ public function test_parse_with_state_invalid_targetrole() {
$this->assertEquals(count($result->users), 1);
}
- public function test_execute() {
+ /**
+ * Tests the execute method.
+ *
+ * @covers \block_workflow_command_assignrole::execute
+ */
+ public function test_execute(): void {
global $DB;
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
@@ -293,9 +339,9 @@ public function test_execute() {
// Check the current assignments.
foreach ($result->users as $user) {
- $assignments = $DB->get_records('role_assignments', array('roleid' => $result->newrole->id,
+ $assignments = $DB->get_records('role_assignments', ['roleid' => $result->newrole->id,
'contextid' => $result->context->id, 'userid' => $user->id, 'component' => 'block_workflow',
- 'itemid' => $state->id));
+ 'itemid' => $state->id]);
$this->assertEquals(count($assignments), 0);
}
@@ -305,9 +351,9 @@ public function test_execute() {
// Check the new assignments.
foreach ($result->users as $user) {
- $assignments = $DB->get_records('role_assignments', array('roleid' => $result->newrole->id,
+ $assignments = $DB->get_records('role_assignments', ['roleid' => $result->newrole->id,
'contextid' => $result->context->id, 'userid' => $user->id, 'component' => 'block_workflow',
- 'itemid' => $state->id));
+ 'itemid' => $state->id]);
$this->assertEquals(count($assignments), 1);
}
}
diff --git a/tests/commandsetactivitylinkedsetting_test.php b/tests/commandsetactivitylinkedsetting_test.php
index 02b32e8..96222cc 100644
--- a/tests/commandsetactivitylinkedsetting_test.php
+++ b/tests/commandsetactivitylinkedsetting_test.php
@@ -43,19 +43,40 @@
* @copyright 2012 the Open University.
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class commandsetactivitylinkedsetting_test extends \block_workflow_testlib {
- public function test_setcoursevisibility() {
+final class commandsetactivitylinkedsetting_test extends \block_workflow_testlib {
+
+ /** @var object current workflow*/
+ private $workflow;
+ /** @var object current step*/
+ private $step;
+
+ /**
+ * Tests the block_workflow_command_setactivitylinkedsetting.
+ *
+ * @covers \block_workflow_command_setactivitylinkedsetting
+ */
+ public function test_setcoursevisibility(): void {
$command = $this->make_command();
$this->assertInstanceOf('block_workflow_command', $command);
}
+ /**
+ * Creates and returns a command instance for testing purposes.
+ *
+ * @return object The command instance created for the test.
+ */
protected function make_command() {
$this->workflow = $this->create_activity_workflow('quiz', false);
$this->step = $this->create_step($this->workflow);
return block_workflow_command::create('block_workflow_command_setactivitylinkedsetting');
}
- public function test_parse_clear() {
+ /**
+ * Tests the block_workflow_command_setactivitylinkedsetting::parse method.
+ *
+ * @covers \block_workflow_command_setactivitylinkedsetting::parse
+ */
+ public function test_parse_clear(): void {
$command = $this->make_command();
$result = $command->parse('block_workflow_steps by workflowid clear', $this->step);
@@ -67,7 +88,12 @@ public function test_parse_clear() {
$this->assertEquals($result->action, block_workflow_command_setactivitylinkedsetting::CLEAR);
}
- public function test_parse_set() {
+ /**
+ * Tests the block_workflow_command_setactivitylinkedsetting::parse method.
+ *
+ * @covers \block_workflow_command_setactivitylinkedsetting::parse
+ */
+ public function test_parse_set(): void {
$command = $this->make_command();
$result = $command->parse('block_workflow_steps by workflowid set stepno 1 name Fred', $this->step);
@@ -77,10 +103,15 @@ public function test_parse_set() {
$this->assertEquals($result->table, 'block_workflow_steps');
$this->assertEquals($result->fkcolumn, 'workflowid');
$this->assertEquals($result->action, block_workflow_command_setactivitylinkedsetting::SET);
- $this->assertEquals($result->toset, array('stepno' => '1', 'name' => 'Fred'));
+ $this->assertEquals($result->toset, ['stepno' => '1', 'name' => 'Fred']);
}
- public function test_parse_missing_by() {
+ /**
+ * Tests the block_workflow_command_setactivitylinkedsetting::parse method.
+ *
+ * @covers \block_workflow_command_setactivitylinkedsetting::parse
+ */
+ public function test_parse_missing_by(): void {
$command = $this->make_command();
$result = $command->parse('block_workflow_steps workflowid clear', $this->step);
@@ -89,7 +120,12 @@ public function test_parse_missing_by() {
$this->assertEquals(count($result->errors), 1);
}
- public function test_parse_missing_clear() {
+ /**
+ * Tests the block_workflow_command_setactivitylinkedsetting::parse method.
+ *
+ * @covers \block_workflow_command_setactivitylinkedsetting::parse
+ */
+ public function test_parse_missing_clear(): void {
$command = $this->make_command();
$result = $command->parse('block_workflow_steps by workflowid', $this->step);
@@ -98,7 +134,12 @@ public function test_parse_missing_clear() {
$this->assertEquals(count($result->errors), 1);
}
- public function test_parse_missing_neither_clear_nor_set() {
+ /**
+ * Tests the block_workflow_command_setactivitylinkedsetting::parse method.
+ *
+ * @covers \block_workflow_command_setactivitylinkedsetting::parse
+ */
+ public function test_parse_missing_neither_clear_nor_set(): void {
$command = $this->make_command();
$result = $command->parse('block_workflow_steps by workflowid frog', $this->step);
@@ -107,7 +148,12 @@ public function test_parse_missing_neither_clear_nor_set() {
$this->assertEquals(count($result->errors), 1);
}
- public function test_parse_junk_after_clear() {
+ /**
+ * Tests the block_workflow_command_setactivitylinkedsetting::parse method.
+ *
+ * @covers \block_workflow_command_setactivitylinkedsetting::parse
+ */
+ public function test_parse_junk_after_clear(): void {
$command = $this->make_command();
$result = $command->parse('block_workflow_steps by workflowid clear junk', $this->step);
@@ -116,7 +162,12 @@ public function test_parse_junk_after_clear() {
$this->assertEquals(count($result->errors), 1);
}
- public function test_parse_cols_values_mismatched() {
+ /**
+ * Tests the block_workflow_command_setactivitylinkedsetting::parse method.
+ *
+ * @covers \block_workflow_command_setactivitylinkedsetting::parse
+ */
+ public function test_parse_cols_values_mismatched(): void {
$command = $this->make_command();
$result = $command->parse('block_workflow_steps by workflowid set name', $this->step);
@@ -125,7 +176,12 @@ public function test_parse_cols_values_mismatched() {
$this->assertEquals(count($result->errors), 1);
}
- public function test_parse_unknown_table() {
+ /**
+ * Tests the block_workflow_command_setactivitylinkedsetting::parse method.
+ *
+ * @covers \block_workflow_command_setactivitylinkedsetting::parse
+ */
+ public function test_parse_unknown_table(): void {
$command = $this->make_command();
$result = $command->parse('__unknown_db_table_name___ by workflowid clear', $this->step);
@@ -134,7 +190,12 @@ public function test_parse_unknown_table() {
$this->assertEquals(count($result->errors), 1);
}
- public function test_parse_unknown_fk_column() {
+ /**
+ * Tests the block_workflow_command_setactivitylinkedsetting::parse method.
+ *
+ * @covers \block_workflow_command_setactivitylinkedsetting::parse
+ */
+ public function test_parse_unknown_fk_column(): void {
$command = $this->make_command();
$result = $command->parse('block_workflow_steps by __unknown_column__ clear', $this->step);
@@ -143,7 +204,12 @@ public function test_parse_unknown_fk_column() {
$this->assertEquals(count($result->errors), 1);
}
- public function test_parse_unknown_set_column() {
+ /**
+ * Tests the block_workflow_command_setactivitylinkedsetting::parse method.
+ *
+ * @covers \block_workflow_command_setactivitylinkedsetting::parse
+ */
+ public function test_parse_unknown_set_column(): void {
$command = $this->make_command();
$result = $command->parse('block_workflow_steps by workflowid set name frog __unknown_column__ 1', $this->step);
diff --git a/tests/commandsetactivityvisibility_test.php b/tests/commandsetactivityvisibility_test.php
index b624a60..ab8214f 100644
--- a/tests/commandsetactivityvisibility_test.php
+++ b/tests/commandsetactivityvisibility_test.php
@@ -34,13 +34,29 @@
global $CFG;
require_once(dirname(__FILE__) . '/lib.php');
-class commandsetactivityvisibility_test extends \block_workflow_testlib {
- public function test_setactivityvisibility() {
+/**
+ * Unit tests for the commandsetactivityvisibility functionality in the block_workflow plugin.
+ *
+ * This class extends the block_workflow_testlib to provide test cases for verifying
+ * the correct behavior of activity visibility commands within the workflow block.
+ */
+final class commandsetactivityvisibility_test extends \block_workflow_testlib {
+ /**
+ * Tests setactivityvisibility.
+ *
+ * @covers \block_workflow_command_setactivityvisibility
+ */
+ public function test_setactivityvisibility(): void {
$command = new block_workflow_command_setactivityvisibility();
$this->assertInstanceOf('block_workflow_command', $command);
}
- public function test_parse_no_state_hidden() {
+ /**
+ * Tests the parse methods no state hidden.
+ *
+ * @covers \block_workflow_command_setactivityvisibility::parse
+ */
+ public function test_parse_no_state_hidden(): void {
$workflow = $this->create_activity_workflow('quiz', false);
$step = $this->create_step($workflow);
@@ -64,7 +80,12 @@ public function test_parse_no_state_hidden() {
$this->assertFalse(isset($result->id));
}
- public function test_parse_no_state_visible() {
+ /**
+ * Tests the parse methods no state visible.
+ *
+ * @covers \block_workflow_command_setactivityvisibility::parse
+ */
+ public function test_parse_no_state_visible(): void {
$workflow = $this->create_activity_workflow('quiz', false);
$step = $this->create_step($workflow);
@@ -88,7 +109,12 @@ public function test_parse_no_state_visible() {
$this->assertFalse(isset($result->id));
}
- public function test_parse_no_state_invalid_state() {
+ /**
+ * Tests the parse methods no state invalid state.
+ *
+ * @covers \block_workflow_command_setactivityvisibility::parse
+ */
+ public function test_parse_no_state_invalid_state(): void {
$workflow = $this->create_activity_workflow('quiz', false);
$step = $this->create_step($workflow);
@@ -112,7 +138,12 @@ public function test_parse_no_state_invalid_state() {
$this->assertFalse(isset($result->id));
}
- public function test_parse_no_state_appliestocourse() {
+ /**
+ * Tests the parse methods no state appliestocourse.
+ *
+ * @covers \block_workflow_command_setactivityvisibility::parse
+ */
+ public function test_parse_no_state_appliestocourse(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
@@ -133,7 +164,12 @@ public function test_parse_no_state_appliestocourse() {
$this->assertFalse(isset($result->id));
}
- public function test_parse_with_state_hidden() {
+ /**
+ * Tests the parse methods with state hidden.
+ *
+ * @covers \block_workflow_command_setactivityvisibility::parse
+ */
+ public function test_parse_with_state_hidden(): void {
$workflow = $this->create_activity_workflow('quiz', false);
$step = $this->create_step($workflow);
$state = $this->assign_workflow($workflow);
@@ -161,7 +197,12 @@ public function test_parse_with_state_hidden() {
$this->assertNotNull($result->cm);
}
- public function test_parse_with_state_visible() {
+ /**
+ * Tests the parse methods with state visible.
+ *
+ * @covers \block_workflow_command_setactivityvisibility::parse
+ */
+ public function test_parse_with_state_visible(): void {
$workflow = $this->create_activity_workflow('quiz', false);
$step = $this->create_step($workflow);
$state = $this->assign_workflow($workflow);
@@ -189,7 +230,12 @@ public function test_parse_with_state_visible() {
$this->assertNotNull($result->cm);
}
- public function test_parse_with_state_invalid_state() {
+ /**
+ * Tests the parse methods with state invalid state.
+ *
+ * @covers \block_workflow_command_setactivityvisibility::parse
+ */
+ public function test_parse_with_state_invalid_state(): void {
$workflow = $this->create_activity_workflow('quiz', false);
$step = $this->create_step($workflow);
$state = $this->assign_workflow($workflow);
@@ -217,7 +263,12 @@ public function test_parse_with_state_invalid_state() {
$this->assertNotNull($result->cm);
}
- public function test_parse_with_state_appliestocourse() {
+ /**
+ * Tests the parse methods.
+ *
+ * @covers \block_workflow_command_setactivityvisibility::parse
+ */
+ public function test_parse_with_state_appliestocourse(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
$state = $this->assign_workflow($workflow);
@@ -236,7 +287,12 @@ public function test_parse_with_state_appliestocourse() {
$this->assertEquals(count($result->errors), 1);
}
- public function test_execute_hidden() {
+ /**
+ * Tests the execute methods.
+ *
+ * @covers \block_workflow_command_setactivityvisibility::execute
+ */
+ public function test_execute_hidden(): void {
global $DB;
$workflow = $this->create_activity_workflow('quiz', false);
$step = $this->create_step($workflow);
@@ -246,7 +302,7 @@ public function test_execute_hidden() {
$args = 'hidden';
// Check that the parent course is visible.
- $check = $DB->get_record('course', array('id' => $this->courseid));
+ $check = $DB->get_record('course', ['id' => $this->courseid]);
$this->assertEquals($check->visible, 1);
$module = $workflow->appliesto;
@@ -256,10 +312,10 @@ public function test_execute_hidden() {
INNER JOIN {context} c ON c.instanceid = cm.id
INNER JOIN {modules} md ON md.id = cm.module
WHERE md.name = ? AND cm.course = ? LIMIT 1";
- $instance = $DB->get_record_sql($sql, array($module, $this->courseid));
+ $instance = $DB->get_record_sql($sql, [$module, $this->courseid]);
// Check that the activity visibility is currently visible.
- $check = $DB->get_record('course_modules', array('id' => $instance->id));
+ $check = $DB->get_record('course_modules', ['id' => $instance->id]);
$this->assertEquals($check->visible, 1);
// Execute.
@@ -267,11 +323,11 @@ public function test_execute_hidden() {
$class->execute($args, $state);
// Check that the activity visibility is now hidden.
- $check = $DB->get_record('course_modules', array('id' => $instance->id));
+ $check = $DB->get_record('course_modules', ['id' => $instance->id]);
$this->assertEquals($check->visible, 0);
// This should not have affected the parent courses visibility.
- $check = $DB->get_record('course', array('id' => $this->courseid));
+ $check = $DB->get_record('course', ['id' => $this->courseid]);
$this->assertEquals($check->visible, 1);
}
}
diff --git a/tests/commandsetcoursevisibility_test.php b/tests/commandsetcoursevisibility_test.php
index 2576c2e..c6eab6f 100644
--- a/tests/commandsetcoursevisibility_test.php
+++ b/tests/commandsetcoursevisibility_test.php
@@ -34,13 +34,26 @@
global $CFG;
require_once(dirname(__FILE__) . '/lib.php');
-class commandsetcoursevisibility_test extends \block_workflow_testlib {
- public function test_setcoursevisibility() {
+/**
+ * Unit tests for the commandsetcoursevisibility class in the block_workflow plugin.
+ */
+final class commandsetcoursevisibility_test extends \block_workflow_testlib {
+ /**
+ * Tests the block_workflow_command_setcoursevisibility method.
+ *
+ * @covers \block_workflow_command_setcoursevisibility
+ */
+ public function test_setcoursevisibility(): void {
$command = new block_workflow_command_setcoursevisibility();
$this->assertInstanceOf('block_workflow_command', $command);
}
- public function test_parse_no_state_hidden() {
+ /**
+ * Tests the block_workflow_command_setcoursevisibility parse method no state hidden.
+ *
+ * @covers \block_workflow_command_setcoursevisibility::parse
+ */
+ public function test_parse_no_state_hidden(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
@@ -64,7 +77,12 @@ public function test_parse_no_state_hidden() {
$this->assertFalse((bool)isset($result->id));
}
- public function test_parse_no_state_visible() {
+ /**
+ * Tests the block_workflow_command_setcoursevisibility parse method no state visible.
+ *
+ * @covers \block_workflow_command_setcoursevisibility::parse
+ */
+ public function test_parse_no_state_visible(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
@@ -88,7 +106,12 @@ public function test_parse_no_state_visible() {
$this->assertFalse((bool)isset($result->id));
}
- public function test_parse_no_state_invalid_state() {
+ /**
+ * Tests the block_workflow_command_setcoursevisibility parse method no state invalid state.
+ *
+ * @covers \block_workflow_command_setcoursevisibility::parse
+ */
+ public function test_parse_no_state_invalid_state(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
@@ -112,7 +135,12 @@ public function test_parse_no_state_invalid_state() {
$this->assertFalse((bool)isset($result->id));
}
- public function test_parse_no_state_appliestoactivity() {
+ /**
+ * Tests the block_workflow_command_setcoursevisibility parse method no state appliestoactivity.
+ *
+ * @covers \block_workflow_command_setcoursevisibility::parse
+ */
+ public function test_parse_no_state_appliestoactivity(): void {
$workflow = $this->create_activity_workflow('quiz', false);
$step = $this->create_step($workflow);
@@ -133,7 +161,12 @@ public function test_parse_no_state_appliestoactivity() {
$this->assertFalse((bool)isset($result->id));
}
- public function test_parse_with_state_hidden() {
+ /**
+ * Tests the block_workflow_command_setcoursevisibility parse method with state hidden.
+ *
+ * @covers \block_workflow_command_setcoursevisibility::parse
+ */
+ public function test_parse_with_state_hidden(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
$state = $this->assign_workflow($workflow);
@@ -158,7 +191,12 @@ public function test_parse_with_state_hidden() {
$this->assertEquals($result->id, $this->courseid);
}
- public function test_parse_with_state_visible() {
+ /**
+ * Tests the block_workflow_command_setcoursevisibility parse method with state visible.
+ *
+ * @covers \block_workflow_command_setcoursevisibility::parse
+ */
+ public function test_parse_with_state_visible(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
$state = $this->assign_workflow($workflow);
@@ -183,7 +221,12 @@ public function test_parse_with_state_visible() {
$this->assertEquals($result->id, $this->courseid);
}
- public function test_parse_with_state_invalid_state() {
+ /**
+ * Tests the block_workflow_command_setcoursevisibility parse method with state invalid state.
+ *
+ * @covers \block_workflow_command_setcoursevisibility::parse
+ */
+ public function test_parse_with_state_invalid_state(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
$state = $this->assign_workflow($workflow);
@@ -208,7 +251,12 @@ public function test_parse_with_state_invalid_state() {
$this->assertEquals($result->id, $this->courseid);
}
- public function test_parse_with_state_appliestoactivity() {
+ /**
+ * Tests the block_workflow_command_setcoursevisibility parse method with state appliestoactivity.
+ *
+ * @covers \block_workflow_command_setcoursevisibility::parse
+ */
+ public function test_parse_with_state_appliestoactivity(): void {
$workflow = $this->create_activity_workflow('quiz', false);
$step = $this->create_step($workflow);
$state = $this->assign_workflow($workflow);
@@ -227,7 +275,12 @@ public function test_parse_with_state_appliestoactivity() {
$this->assertEquals(count($result->errors), 1);
}
- public function test_execute_hidden() {
+ /**
+ * Tests the block_workflow_command_setcoursevisibility execute hidden method.
+ *
+ * @covers \block_workflow_command_setcoursevisibility::execute
+ */
+ public function test_execute_hidden(): void {
global $DB;
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
@@ -237,7 +290,7 @@ public function test_execute_hidden() {
$args = 'hidden';
// Check that the course visibility is currently visible.
- $check = $DB->get_record('course', array('id' => $this->courseid));
+ $check = $DB->get_record('course', ['id' => $this->courseid]);
$this->assertEquals($check->visible, 1);
// Try parsing without a context.
@@ -245,7 +298,7 @@ public function test_execute_hidden() {
$class->execute($args, $state);
// Check that the course visibility is now hidden.
- $check = $DB->get_record('course', array('id' => $this->courseid));
+ $check = $DB->get_record('course', ['id' => $this->courseid]);
$this->assertEquals($check->visible, 0);
}
}
diff --git a/tests/commandsetgradeitemvisibility_test.php b/tests/commandsetgradeitemvisibility_test.php
index 45c1054..df5ed96 100644
--- a/tests/commandsetgradeitemvisibility_test.php
+++ b/tests/commandsetgradeitemvisibility_test.php
@@ -35,22 +35,41 @@
require_once(dirname(__FILE__) . '/lib.php');
require_once($CFG->dirroot.'/lib/grade/grade_item.php');
-class commandsetgradeitemvisibility_test extends \block_workflow_testlib {
+/**
+ * Unit tests for the commandsetgradeitemvisibility class in the block_workflow plugin.
+ */
+final class commandsetgradeitemvisibility_test extends \block_workflow_testlib {
+ /**
+ * Generates a module instance of the specified type.
+ *
+ * @param string $modname The name of the module to generate.
+ * @return mixed The generated module instance.
+ */
private function generate_module($modname) {
global $CFG;
if (!is_readable($CFG->dirroot . '/mod/externalquiz/tests/generator/lib.php')) {
$this->markTestSkipped('This test requires mod_externalquiz to be installed.');
}
$generator = $this->getDataGenerator()->get_plugin_generator('mod_' . $modname);
- return $generator->create_instance(array('course' => $this->courseid));
+ return $generator->create_instance(['course' => $this->courseid]);
}
- public function test_setgradeitemvisibility() {
+ /**
+ * Tests the setgradeitemvisibility method.
+ *
+ * @covers \block_workflow_command_setgradeitemvisibility
+ */
+ public function test_setgradeitemvisibility(): void {
$command = new block_workflow_command_setgradeitemvisibility();
$this->assertInstanceOf('block_workflow_command', $command);
}
- public function test_parse_no_state_visible() {
+ /**
+ * Tests the block_workflow_command_setgradeitemvisibility parse no state visible.
+ *
+ * @covers \block_workflow_command_setgradeitemvisibility::parse
+ */
+ public function test_parse_no_state_visible(): void {
$workflow = $this->create_activity_workflow('assign', false);
$step = $this->create_step($workflow);
@@ -74,7 +93,12 @@ public function test_parse_no_state_visible() {
$this->assertFalse(isset($result->id));
}
- public function test_parse_no_state_hidden() {
+ /**
+ * Tests the block_workflow_command_setgradeitemvisibility parse no state hidden.
+ *
+ * @covers \block_workflow_command_setgradeitemvisibility::parse
+ */
+ public function test_parse_no_state_hidden(): void {
$workflow = $this->create_activity_workflow('assign', false);
$step = $this->create_step($workflow);
@@ -98,7 +122,12 @@ public function test_parse_no_state_hidden() {
$this->assertFalse(isset($result->id));
}
- public function test_parse_no_state_invalid_state() {
+ /**
+ * Tests the block_workflow_command_setgradeitemvisibility parse no state invalid state.
+ *
+ * @covers \block_workflow_command_setgradeitemvisibility::parse
+ */
+ public function test_parse_no_state_invalid_state(): void {
$workflow = $this->create_activity_workflow('assign', false);
$step = $this->create_step($workflow);
@@ -114,8 +143,8 @@ public function test_parse_no_state_invalid_state() {
// There should be one error.
$this->assertEquals(count($result->errors), 1);
- $this->assertEquals($result->errors, array(
- get_string('invalidvisibilitysetting', 'block_workflow', $args)));
+ $this->assertEquals($result->errors, [
+ get_string('invalidvisibilitysetting', 'block_workflow', $args)]);
// Test: $result should have no visible.
$this->assertFalse(isset($result->visibility));
@@ -124,7 +153,12 @@ public function test_parse_no_state_invalid_state() {
$this->assertFalse(isset($result->id));
}
- public function test_parse_no_state_appliestocourse() {
+ /**
+ * Tests the block_workflow_command_setgradeitemvisibility parse no state appliestocourse.
+ *
+ * @covers \block_workflow_command_setgradeitemvisibility::parse
+ */
+ public function test_parse_no_state_appliestocourse(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
@@ -140,14 +174,19 @@ public function test_parse_no_state_appliestocourse() {
// There should be one error.
$this->assertEquals(count($result->errors), 1);
- $this->assertEquals($result->errors, array(
- get_string('notanactivity', 'block_workflow', 'setgradeitemvisibility')));
+ $this->assertEquals($result->errors, [
+ get_string('notanactivity', 'block_workflow', 'setgradeitemvisibility')]);
// Test: $result should have no id.
$this->assertFalse(isset($result->id));
}
- public function test_parse_no_state_appliesto_a_activity_which_controls_gradeitemvisibility() {
+ /**
+ * Tests the block_workflow_command_setgradeitemvisibility parse no state applies.
+ *
+ * @covers \block_workflow_command_setgradeitemvisibility::parse
+ */
+ public function test_parse_no_state_appliesto_a_activity_which_controls_gradeitemvisibility(): void {
$workflow = $this->create_activity_workflow('quiz', false);
$step = $this->create_step($workflow);
@@ -160,11 +199,16 @@ public function test_parse_no_state_appliesto_a_activity_which_controls_gradeite
// There should be one error.
$this->assertEquals(count($result->errors), 1);
- $this->assertEquals($result->errors, array(
- get_string('notcontrollablegradeitem', 'block_workflow', 'setgradeitemvisibility')));
+ $this->assertEquals($result->errors, [
+ get_string('notcontrollablegradeitem', 'block_workflow', 'setgradeitemvisibility')]);
}
- public function test_parse_with_state_visible() {
+ /**
+ * Tests the block_workflow_command_setgradeitemvisibility parse with state visible.
+ *
+ * @covers \block_workflow_command_setgradeitemvisibility::parse
+ */
+ public function test_parse_with_state_visible(): void {
$this->generate_module('assign');
$workflow = $this->create_activity_workflow('assign', false);
$step = $this->create_step($workflow);
@@ -190,7 +234,12 @@ public function test_parse_with_state_visible() {
$this->assertEquals('assign', $result->cm->modname);
}
- public function test_parse_with_state_hidden() {
+ /**
+ * Tests the block_workflow_command_setgradeitemvisibility parse with state hidden.
+ *
+ * @covers \block_workflow_command_setgradeitemvisibility::parse
+ */
+ public function test_parse_with_state_hidden(): void {
$this->generate_module('forum');
$workflow = $this->create_activity_workflow('forum', false);
$step = $this->create_step($workflow);
@@ -216,7 +265,12 @@ public function test_parse_with_state_hidden() {
$this->assertEquals('forum', $result->cm->modname);
}
- public function test_parse_with_state_invalid_state() {
+ /**
+ * Tests the block_workflow_command_setgradeitemvisibility parse with state invalid state.
+ *
+ * @covers \block_workflow_command_setgradeitemvisibility::parse
+ */
+ public function test_parse_with_state_invalid_state(): void {
$this->generate_module('assign');
$workflow = $this->create_activity_workflow('assign', false);
$step = $this->create_step($workflow);
@@ -242,7 +296,12 @@ public function test_parse_with_state_invalid_state() {
$this->assertEquals('assign', $result->cm->modname);
}
- public function test_parse_with_state_appliestocourse() {
+ /**
+ * Tests the block_workflow_command_setgradeitemvisibility parse with state appliestocourse.
+ *
+ * @covers \block_workflow_command_setgradeitemvisibility::parse
+ */
+ public function test_parse_with_state_appliestocourse(): void {
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
$state = $this->assign_workflow($workflow);
@@ -255,15 +314,21 @@ public function test_parse_with_state_appliestocourse() {
$result = $class->parse($args, $step, $state);
// Test: $result should have have the validation error.
- $this->assertEquals(array(get_string('notanactivity', 'block_workflow', 'setgradeitemvisibility')),
+ $this->assertEquals([get_string('notanactivity', 'block_workflow', 'setgradeitemvisibility')],
$result->errors);
// There should be one error.
$this->assertCount(1, $result->errors);
}
- public function test_parse_with_state_no_support_for_grade() {
- $workflow = $this->create_activity_workflow('chat', false);
+ /**
+ * Tests the block_workflow_command_setgradeitemvisibility parse methods with state no support for grade.
+ *
+ * @covers \block_workflow_command_setgradeitemvisibility::parse
+ */
+ public function test_parse_with_state_no_support_for_grade(): void {
+ $this->generate_module('forum');
+ $workflow = $this->create_activity_workflow('forum', false);
$step = $this->create_step($workflow);
$state = $this->assign_workflow($workflow);
@@ -274,20 +339,25 @@ public function test_parse_with_state_no_support_for_grade() {
$result = $class->parse($args, $step, $state);
// Test: $result should have have the validation error.
- $this->assertEquals(array(get_string('notgradesupported', 'block_workflow', 'setgradeitemvisibility')),
+ $this->assertEquals([get_string('notgradesupported', 'block_workflow', 'setgradeitemvisibility')],
$result->errors);
$this->assertCount(1, $result->errors);
}
- public function test_execute_hidden() {
+ /**
+ * Tests the block_workflow_command_setgradeitemvisibility execute hidden methods.
+ *
+ * @covers \block_workflow_command_setgradeitemvisibility::execute
+ */
+ public function test_execute_hidden(): void {
global $DB;
$assign = $this->generate_module('externalquiz');
// Check the value of the field hidden in grade_items table before executing setgradeitemvisibility command.
$hiddenfieldbefore = $DB->get_field('grade_items', 'hidden',
- array('courseid' => $this->courseid, 'itemtype' => 'mod',
- 'itemmodule' => 'externalquiz', 'iteminstance' => $assign->id));
+ ['courseid' => $this->courseid, 'itemtype' => 'mod',
+ 'itemmodule' => 'externalquiz', 'iteminstance' => $assign->id]);
$this->assertEquals($hiddenfieldbefore, 0);
// Create a workflow which applies to 'assign' module with one step.
@@ -298,23 +368,28 @@ public function test_execute_hidden() {
$wfc = block_workflow_command::create('block_workflow_command_setgradeitemvisibility');
$wfc->execute('hidden', $state);
$hiddenfieldafter = $DB->get_field('grade_items', 'hidden',
- array('courseid' => $this->courseid, 'itemtype' => 'mod',
- 'itemmodule' => 'externalquiz', 'iteminstance' => $assign->id));
+ ['courseid' => $this->courseid, 'itemtype' => 'mod',
+ 'itemmodule' => 'externalquiz', 'iteminstance' => $assign->id]);
$this->assertEquals($hiddenfieldafter, 1);
}
- public function test_execute_visible() {
+ /**
+ * Tests the block_workflow_command_setgradeitemvisibility execute methods.
+ *
+ * @covers \block_workflow_command_setgradeitemvisibility::execute
+ */
+ public function test_execute_visible(): void {
global $DB;
$assign = $this->generate_module('externalquiz');
$DB->set_field('grade_items', 'hidden', 1,
- array('courseid' => $this->courseid, 'itemtype' => 'mod',
- 'itemmodule' => 'externalquiz', 'iteminstance' => $assign->id));
+ ['courseid' => $this->courseid, 'itemtype' => 'mod',
+ 'itemmodule' => 'externalquiz', 'iteminstance' => $assign->id]);
// Check the value of the field hidden in grade_items table before executing setgradeitemvisibility command.
$hiddenfieldbefore = $DB->get_field('grade_items', 'hidden',
- array('courseid' => $this->courseid, 'itemtype' => 'mod',
- 'itemmodule' => 'externalquiz', 'iteminstance' => $assign->id));
+ ['courseid' => $this->courseid, 'itemtype' => 'mod',
+ 'itemmodule' => 'externalquiz', 'iteminstance' => $assign->id]);
$this->assertEquals($hiddenfieldbefore, 1);
// Create a workflow which applies to 'assign' module with one step.
@@ -325,8 +400,8 @@ public function test_execute_visible() {
$wfc = block_workflow_command::create('block_workflow_command_setgradeitemvisibility');
$wfc->execute('visible', $state);
$hiddenfieldafter = $DB->get_field('grade_items', 'hidden',
- array('courseid' => $this->courseid, 'itemtype' => 'mod',
- 'itemmodule' => 'externalquiz', 'iteminstance' => $assign->id));
+ ['courseid' => $this->courseid, 'itemtype' => 'mod',
+ 'itemmodule' => 'externalquiz', 'iteminstance' => $assign->id]);
$this->assertEquals($hiddenfieldafter, 0);
}
}
diff --git a/tests/emails_test.php b/tests/emails_test.php
index 189f6fb..2238c56 100644
--- a/tests/emails_test.php
+++ b/tests/emails_test.php
@@ -35,8 +35,16 @@
global $CFG;
require_once(dirname(__FILE__) . '/lib.php');
-class emails_test extends \block_workflow_testlib {
- public function test_email_validation() {
+/**
+ * Unit tests for email-related functionality in the block_workflow plugin.
+ */
+final class emails_test extends \block_workflow_testlib {
+ /**
+ * Tests the block_workflow_email::create method.
+ *
+ * @covers \block_workflow_email::create
+ */
+ public function test_email_validation(): void {
$data = new stdClass();
$email = new block_workflow_email();
@@ -68,7 +76,12 @@ public function test_email_validation() {
unset($data->badfield);
}
- public function test_email_create() {
+ /**
+ * Tests the block_workflow_email::create method.
+ *
+ * @covers \block_workflow_email::create
+ */
+ public function test_email_create(): void {
$data = new stdClass();
$data->shortname = 'shortname';
$data->subject = 'Example Subject';
@@ -80,7 +93,7 @@ public function test_email_create() {
$return = $email->create($data);
// The variable $email should match the entered data.
- $this->compare_email($data, $email, array('id'));
+ $this->compare_email($data, $email, ['id']);
// Check that the return value is also a block_workflow_email.
$this->assertInstanceOf('block_workflow_email', $return);
@@ -89,7 +102,7 @@ public function test_email_create() {
$this->assertInstanceOf('block_workflow_email', $email);
// And the two should match.
- $this->compare_email($data, $email, array());
+ $this->compare_email($data, $email, []);
// And trying to create another email with the same (valid) data should result in an
// exception because the shortname is already in use.
@@ -109,7 +122,12 @@ public function test_email_create() {
$data->shortname = 'newshortname';
}
- public function test_email_update() {
+ /**
+ * Tests the block_workflow_email::update method.
+ *
+ * @covers \block_workflow_email::update
+ */
+ public function test_email_update(): void {
$data = new stdClass();
$data->shortname = 'shortname';
$data->subject = 'Example Subject';
@@ -121,7 +139,7 @@ public function test_email_update() {
$return = $email->create($data);
// The variable $email should match the entered data.
- $this->compare_email($data, $email, array('id'));
+ $this->compare_email($data, $email, ['id']);
// Check that the return value is also a block_workflow_email.
$this->assertInstanceOf('block_workflow_email', $return);
@@ -130,7 +148,7 @@ public function test_email_update() {
$this->assertInstanceOf('block_workflow_email', $email);
// And the two should match.
- $this->compare_email($data, $email, array());
+ $this->compare_email($data, $email, []);
// Check validation on e-mail updates.
$data->shortname = 'newshortname';
@@ -143,7 +161,12 @@ public function test_email_update() {
$this->assertEquals($updated->shortname, 'shortname');
}
- public function test_email_update_validation_exception() {
+ /**
+ * Tests the block_workflow_email::update method.
+ *
+ * @covers \block_workflow_email::update
+ */
+ public function test_email_update_validation_exception(): void {
$email = $this->create_email();
$data = new stdClass();
@@ -154,7 +177,12 @@ public function test_email_update_validation_exception() {
unset($data->badfield);
}
- public function test_email_update_validation() {
+ /**
+ * Tests the block_workflow_email::update method.
+ *
+ * @covers \block_workflow_email::update
+ */
+ public function test_email_update_validation(): void {
$email = $this->create_email();
$data = new stdClass();
// And change the shortname.
@@ -163,7 +191,12 @@ public function test_email_update_validation() {
$this->compare_email($data, $email);
}
- public function test_email_duplicate_shortnames_exception() {
+ /**
+ * Tests the block_workflow_email::create method.
+ *
+ * @covers \block_workflow_email::create
+ */
+ public function test_email_duplicate_shortnames_exception(): void {
// Create an e-mail with shortname 'shortname'.
$this->create_email('shortname');
$email = new block_workflow_email();
@@ -178,7 +211,12 @@ public function test_email_duplicate_shortnames_exception() {
$email, 'create', $data);
}
- public function test_email_duplicate_shortnames() {
+ /**
+ * Tests the block_workflow_email::update method.
+ *
+ * @covers \block_workflow_email::update
+ */
+ public function test_email_duplicate_shortnames(): void {
// Create an e-mail with shortname 'shortname'.
$this->create_email('shortname');
$email = new block_workflow_email();
@@ -196,7 +234,12 @@ public function test_email_duplicate_shortnames() {
$email, 'update', $data);
}
- public function test_email_loading() {
+ /**
+ * Tests the block_workflow_email::load_email_shortname method.
+ *
+ * @covers \block_workflow_email::load_email_shortname
+ */
+ public function test_email_loading(): void {
// Create a new e-mail.
$email = $this->create_email('shortname');
@@ -229,7 +272,12 @@ public function test_email_loading() {
}
- public function test_email_listing() {
+ /**
+ * Tests the block_workflow_email::load_emails method.
+ *
+ * @covers \block_workflow_email::load_emails
+ */
+ public function test_email_listing(): void {
// Initially we should have no emails.
$list = block_workflow_email::load_emails();
$this->assertEquals(count($list), 0);
@@ -256,7 +304,12 @@ public function test_email_listing() {
$this->assertEquals(count($list), 1);
}
- public function test_email_not_used() {
+ /**
+ * Tests the block_workflow_command::is_deletable method.
+ *
+ * @covers \block_workflow_email::is_deletable
+ */
+ public function test_email_not_used(): void {
// Create a new e-mail.
$email = $this->create_email('shortname');
@@ -381,4 +434,50 @@ public function test_email_not_used() {
// And we shouldn't throw an exception when deleting.
$email->delete();
}
+
+ /**
+ * Tests the block_workflow_command::execute method.
+ *
+ * @covers \block_workflow_command::execute
+ */
+ public function test_email_send_failed(): void {
+ // The workflow system has some logic (which I think is no longer required)
+ // which stops it from sending messages if a transaction is in progress.
+ // We should probably untangle that one day, but for now.
+ $this->preventResetByRollback();
+
+ // Disable the send email feature so message_send function will always fail.
+ set_config('block_workflow_notification_disable', 1, 'message');
+
+ // Create a new template e-mail.
+ $this->create_email('shortname');
+
+ $workflow = $this->create_workflow(false);
+ $this->create_step($workflow);
+ $state = $this->assign_workflow($workflow);
+ $sink = $this->redirectEvents();
+
+ // This command should assign and send email template to student.
+ $command = 'shortname to student';
+ $emailcommand = \block_workflow_command::create('block_workflow_command_email');
+ // Check that we throw an exception with correct error message.
+ $emailcommand->execute($command, $state);
+ $events = $sink->get_events();
+ $event = reset($events);
+ // Check that the event data is valid.
+ $this->assertInstanceOf('\block_workflow\event\email_sent_status', $event);
+ $this->assertStringContainsString("Failed send email 'Example subject' to egstudent@localhost.com",
+ $event->other['error']);
+ $this->assertStringContainsString("The email to user with id", $event->get_description());
+
+ // Test send email successfully.
+ $sink = $this->redirectEvents();
+ set_config('block_workflow_notification_disable', 0, 'message');
+ $emailcommand->execute($command, $state);
+ $events = $sink->get_events();
+ // The first event is core\event\notification_sent.
+ // Check that the event data is valid.
+ $this->assertInstanceOf('\block_workflow\event\email_sent_status', $events[1]);
+ $this->assertStringContainsString("The email was successfully sent to user with id", $events[1]->get_description());
+ }
}
diff --git a/tests/external/external_api_base_lib.php b/tests/external/external_api_base_lib.php
new file mode 100644
index 0000000..4b24c08
--- /dev/null
+++ b/tests/external/external_api_base_lib.php
@@ -0,0 +1,119 @@
+.
+
+namespace block_workflow\external;
+use externallib_advanced_testcase;
+use block_workflow_workflow;
+use block_workflow_step;
+
+defined('MOODLE_INTERNAL') || die();
+global $CFG;
+require_once($CFG->dirroot . '/webservice/tests/helpers.php');
+
+/**
+ * Mocking data and common function for all the web service tests.
+ *
+ * @package block_workflow
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class external_api_base_lib extends externallib_advanced_testcase {
+
+ /**
+ * @var int|null ID of the first workflow state, or null if not set.
+ */
+ protected $state1id = null;
+ /**
+ * @var mixed|null Step 1 variable, initialized as null.
+ */
+ protected $step1 = null;
+ /**
+ * @var mixed|null Stores the second step in the workflow, or null if not set.
+ */
+ protected $step2 = null;
+ /**
+ * Example student user object for testing purposes.
+ *
+ * @var mixed|null
+ */
+ protected $egstudent = null;
+ /**
+ * @var stdClass|null The course object associated with the test, or null if not set.
+ */
+ protected $course = null;
+ /**
+ * @var int|null The ID of the student role, or null if not set.
+ */
+ protected $studenroleid = null;
+
+ #[\Override]
+ public function setUp(): void {
+ $this->resetAfterTest();
+ $this->setAdminUser();
+ global $DB;
+
+ $generator = $this->getDataGenerator();
+ $this->course = $generator->create_course(['shortname' => 'X943-12K']);
+ $coursecontext = \context_course::instance($this->course->id);
+
+ $this->egstudent = $generator->create_user(['username' => 'egstudent']);
+
+ $roleids = $DB->get_records_menu('role', null, '', 'shortname,id');
+ $this->studenroleid = $roleids['student'];
+
+ $manualenrol = enrol_get_plugin('manual');
+ $manualenrol->add_default_instance($this->course);
+ $instance1 = $DB->get_record('enrol', ['enrol' => 'manual', 'courseid' => $this->course->id]);
+ $manualenrol->enrol_user($instance1, $this->egstudent->id, $roleids['student']);
+ // Create a new workflow object.
+ $workflow = new block_workflow_workflow();
+
+ // Create a new workflow.
+ $data = new \stdClass();
+ $data->shortname = 'courseworkflow';
+ $data->name = 'First course workflow';
+ $data->appliesto = 'course';
+ $data->obsolete = 0;
+ $data->description = 'This is a test workflow applying to a course for the unit test';
+ $data->descriptionformat = FORMAT_HTML;
+ // Create_workflow will return a completed workflow object.
+ $workflow->create_workflow($data);
+
+ // When creating a workflow, the initial step will have automatically been created.
+ // Retrieve the list of steps.
+ $steps = $workflow->steps();
+ $step = array_pop($steps);
+ $this->step1 = new block_workflow_step($step->id);
+ // Update the first step to have some scripts.
+ $step->onactivescript = 'assignrole teacher to student';
+ $this->step1->update_step($step);
+
+ // Create a new step in the workflow.
+ $nsdata = new \stdClass();
+ $nsdata->workflowid = $workflow->id;
+ $nsdata->name = 'Second step';
+ $nsdata->instructions = 'New instructions';
+ $nsdata->instructionsformat = FORMAT_HTML;
+ $nsdata->onactivescript = 'setcoursevisibility visible';
+ $nsdata->oncompletescript = 'setcoursevisibility hidden';
+
+ $newstep = new block_workflow_step();
+ $this->step2 = $newstep->create_step($nsdata);
+ $state = $workflow->add_to_context($coursecontext->id);
+ $state->update_comment('
Sample Comment
', FORMAT_HTML);
+ $this->state1id = $state->id;
+ }
+}
diff --git a/tests/external/finish_step_test.php b/tests/external/finish_step_test.php
new file mode 100644
index 0000000..b19c604
--- /dev/null
+++ b/tests/external/finish_step_test.php
@@ -0,0 +1,67 @@
+.
+
+namespace block_workflow\external;
+use block_workflow_step_state;
+
+defined('MOODLE_INTERNAL') || die();
+// Include api test library so that we can use the same mocking system for all tests.
+require_once(dirname(__FILE__) . '/external_api_base_lib.php');
+
+/**
+ * Unit tests for the finish_step web service.
+ *
+ * @package block_workflow
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+final class finish_step_test extends external_api_base_lib {
+
+ /**
+ * Test finish step run successfully.
+ *
+ * @covers \finish_step::execute
+ */
+ public function test_finish_step(): void {
+ // Call the external service function.
+ $returnvalue = finish_step::execute($this->state1id, 'Finish comment', FORMAT_HTML);
+
+ // We need to execute the return values cleaning process to simulate
+ // the web service server.
+ $returnvalue = \core_external\external_api::clean_returnvalue(
+ finish_step::execute_returns(),
+ $returnvalue
+ );
+ // Load the updated data for two states.
+ $state1 = new block_workflow_step_state($this->state1id);
+ $state2 = new block_workflow_step_state($returnvalue['stateid']);
+
+ // Verify step 1 is complete.
+ $this->assertEquals($this->step1->id, $state1->stepid);
+ $this->assertEquals(BLOCK_WORKFLOW_STATE_COMPLETED, $state1->state);
+
+ // Verify step 2 is active.
+ $this->assertEquals($this->step2->id, $state2->stepid);
+ $this->assertEquals(BLOCK_WORKFLOW_STATE_ACTIVE, $state2->state);
+ // Finish step state 2.
+ $returnvalue = finish_step::execute($state2->id, 'Finish comment', FORMAT_HTML);
+ $state2 = new block_workflow_step_state($state2->id);
+ // Verify step 2 is complete.
+ $this->assertEquals(BLOCK_WORKFLOW_STATE_COMPLETED, $state2->state);
+ // We should return the listofworkflows.
+ $this->assertEquals(1, $returnvalue['listworkflows']);
+ }
+}
diff --git a/tests/external/get_step_state_comment_test.php b/tests/external/get_step_state_comment_test.php
new file mode 100644
index 0000000..be6ec03
--- /dev/null
+++ b/tests/external/get_step_state_comment_test.php
@@ -0,0 +1,67 @@
+.
+
+namespace block_workflow\external;
+
+defined('MOODLE_INTERNAL') || die();
+// Include api test library so that we can use the same mocking system for all tests.
+require_once(dirname(__FILE__) . '/external_api_base_lib.php');
+
+/**
+ * Unit tests for the get_step_state_comment webservice.
+ *
+ * @package block_workflow
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+final class get_step_state_comment_test extends external_api_base_lib {
+
+ /**
+ * Test get step state comment successfully.
+ *
+ * @covers \get_step_state_comment::execute
+ */
+ public function test_get_step_state_comment(): void {
+ // Call the external service function.
+ $returnvalue = get_step_state_comment::execute($this->state1id);
+
+ // We need to execute the return values cleaning process to simulate
+ // the web service server.
+ $returnvalue = \core_external\external_api::clean_returnvalue(
+ get_step_state_comment::execute_returns(),
+ $returnvalue
+ );
+ $this->assertEquals('
Sample Comment
', $returnvalue['response']);
+ }
+
+ /**
+ * Test get step state comment without capability.
+ *
+ * @covers \get_step_state_comment::execute
+ * @runInSeparateProcess
+ */
+ public function test_get_step_state_comment_failed(): void {
+ $this->resetAfterTest();
+ $this->setUser($this->egstudent);
+
+ // Remove the required capabilities by the external function.
+ $context = \context_course::instance($this->course->id);
+ $this->unassignUserCapability('block/workflow:dostep', $context->id, $this->studenroleid, $this->course->id);
+ // User can't make change in block.
+ $this->expectExceptionMessage(get_string('notallowedtodothisstep', 'block_workflow'));
+ get_step_state_comment::execute($this->state1id);
+ }
+}
diff --git a/tests/external/update_step_state_comment_test.php b/tests/external/update_step_state_comment_test.php
new file mode 100644
index 0000000..fea6da8
--- /dev/null
+++ b/tests/external/update_step_state_comment_test.php
@@ -0,0 +1,50 @@
+.
+
+namespace block_workflow\external;
+
+defined('MOODLE_INTERNAL') || die();
+// Include api test library so that we can use the same mocking system for all tests.
+require_once(dirname(__FILE__) . '/external_api_base_lib.php');
+
+/**
+ * Unit tests for the update_step_state_comment webservice.
+ *
+ * @package block_workflow
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+final class update_step_state_comment_test extends external_api_base_lib {
+
+ /**
+ * Test update step_state comment successfully.
+ *
+ * @covers \update_step_state_comment::execute
+ */
+ public function test_update_step_state_comment(): void {
+ // Call the external service function.
+ $returnvalue = update_step_state_comment::execute($this->state1id,
+ '
New comment', FORMAT_HTML);
+
+ // We need to execute the return values cleaning process to simulate
+ // the web service server.
+ $returnvalue = \core_external\external_api::clean_returnvalue(
+ update_step_state_comment::execute_returns(),
+ $returnvalue
+ );
+ $this->assertEquals('
New comment', $returnvalue['response']);
+ }
+}
diff --git a/tests/external/update_step_state_task_state_test.php b/tests/external/update_step_state_task_state_test.php
new file mode 100644
index 0000000..3e91aca
--- /dev/null
+++ b/tests/external/update_step_state_task_state_test.php
@@ -0,0 +1,56 @@
+.
+
+namespace block_workflow\external;
+
+defined('MOODLE_INTERNAL') || die();
+// Include api test library so that we can use the same mocking system for all tests.
+require_once(dirname(__FILE__) . '/external_api_base_lib.php');
+
+/**
+ * Unit tests for the update_step_state_task_state webservice.
+ *
+ * @package block_workflow
+ * @copyright 2023 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+final class update_step_state_task_state_test extends external_api_base_lib {
+
+ /**
+ * Test update update_step_state_task_state successfully.
+ *
+ * @covers \update_step_state_task_state::execute
+ */
+ public function test_update_step_state_task_state(): void {
+ // Create a new to-do.
+ $todo = new \block_workflow_todo();
+ $data = new \stdClass();
+ $data->stepid = $this->step1->id;
+ $data->task = 'TASK ONE';
+ $todo->create_todo($data);
+
+ // Call the external service function.
+ $returnvalue = update_step_state_task_state::execute($this->state1id, $todo->id, true);
+
+ // We need to execute the return values cleaning process to simulate
+ // the web service server.
+ $returnvalue = \core_external\external_api::clean_returnvalue(
+ update_step_state_task_state::execute_returns(),
+ $returnvalue
+ );
+ $this->assertEquals(1, $returnvalue['response']);
+ }
+}
diff --git a/tests/extranotify_test.php b/tests/extranotify_test.php
index 9a893a2..e690ead 100644
--- a/tests/extranotify_test.php
+++ b/tests/extranotify_test.php
@@ -34,8 +34,20 @@
require_once($CFG->dirroot . '/blocks/workflow/locallib.php');
require_once($CFG->dirroot . '/blocks/workflow/tests/lib.php');
-class extranotify_test extends \block_workflow_testlib {
- public function test_extra_notify() {
+/**
+ * Unit tests for the extranotify functionality in the block_workflow plugin.
+ *
+ * This class extends the block_workflow_testlib to provide specific test cases
+ * for the extranotify feature, ensuring correct behavior and integration within
+ * the workflow block.
+ */
+final class extranotify_test extends \block_workflow_testlib {
+ /**
+ * Tests the block_workflow_send_extra_notification methods.
+ *
+ * @covers ::block_workflow_send_extra_notification
+ */
+ public function test_extra_notify(): void {
global $CFG, $DB;
$now = time();
$after5days = $this->get_days(5);
@@ -48,11 +60,11 @@ public function test_extra_notify() {
$generator = $this->getDataGenerator();
// Create a course object.
- $course1 = $generator->create_course(array('shortname' => 'M123-12J', 'startdate' => $timestamp1));
+ $course1 = $generator->create_course(['shortname' => 'M123-12J', 'startdate' => $timestamp1]);
$coursecontext1 = \context_course::instance($course1->id);
// Create another course object.
- $course2 = $generator->create_course(array('shortname' => 'K123-12J', 'startdate' => $timestamp2));
+ $course2 = $generator->create_course(['shortname' => 'K123-12J', 'startdate' => $timestamp2]);
$coursecontext2 = \context_course::instance($course2->id);
// Generate a vl_v_crs_version_pres table.
@@ -66,7 +78,7 @@ public function test_extra_notify() {
$courseondataloadtable = $DB->get_record_sql(
'SELECT * FROM vl_v_crs_version_pres ' .
- 'WHERE vle_course_short_name = ?', array($courseshortname), MUST_EXIST);
+ 'WHERE vle_course_short_name = ?', [$courseshortname], MUST_EXIST);
// Create an email template.
$data = new \stdClass();
@@ -78,12 +90,12 @@ public function test_extra_notify() {
$email->create($data);
// Create a new workflow object which applies to course.
- $stepoptions = array('extranotify' => 'course;startdate', 'extranotifyoffset' => $before5days,
- 'onextranotifyscript' => 'email testing to manager');
+ $stepoptions = ['extranotify' => 'course;startdate', 'extranotifyoffset' => $before5days,
+ 'onextranotifyscript' => 'email testing to manager'];
list($courseworkflow, $step1) = $this->create_a_workflow_with_one_step($stepoptions);
// Required DB tables are not populated and therefore following methods return empty arrays.
- $stepoptions = array('extranotify', 'extranotifyoffset', 'onextranotifyscript');
+ $stepoptions = ['extranotify', 'extranotifyoffset', 'onextranotifyscript'];
$activesteps = block_workflow_get_active_steps_with_fields_not_null($stepoptions);
$this->assertEmpty($activesteps);
@@ -115,18 +127,23 @@ public function test_extra_notify() {
$this->assertEquals($expectedactivesteps, $activesteps);
// Check relevant fields in 'block_workflow_step_states' table before sending extra notification.
- $state = $DB->get_record('block_workflow_step_states', array('id' => $state1->id));
+ $state = $DB->get_record('block_workflow_step_states', ['id' => $state1->id]);
$this->assertEquals(BLOCK_WORKFLOW_STATE_ACTIVE, $state->state);
// Get ready active steps and finish them automatically.
block_workflow_send_extra_notification();
// Check relevant fields in 'block_workflow_step_states' table after finishing automatically.
- $stateafterfinish = $DB->get_record('block_workflow_step_states', array('id' => $state1->id));
+ $stateafterfinish = $DB->get_record('block_workflow_step_states', ['id' => $state1->id]);
$this->assertEquals(BLOCK_WORKFLOW_STATE_ACTIVE, $stateafterfinish->state);
}
- public function test_block_workflow_get_offset_time_relative_to_course() {
+ /**
+ * Tests the block_workflow_get_offset_time methods relative to course.
+ *
+ * @covers ::block_workflow_get_offset_time
+ */
+ public function test_block_workflow_get_offset_time_relative_to_course(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
@@ -141,7 +158,12 @@ public function test_block_workflow_get_offset_time_relative_to_course() {
$this->assertEquals(strtotime('2019-02-01'), $timestamp);
}
- public function test_block_workflow_get_offset_time_relative_to_quiz() {
+ /**
+ * Tests the block_workflow_get_offset_time methods relative to quiz.
+ *
+ * @covers ::block_workflow_get_offset_time
+ */
+ public function test_block_workflow_get_offset_time_relative_to_quiz(): void {
global $SITE;
$this->resetAfterTest();
@@ -157,7 +179,12 @@ public function test_block_workflow_get_offset_time_relative_to_quiz() {
$this->assertEquals(strtotime('2019-02-01'), $timestamp);
}
- public function test_block_workflow_get_offset_time_relative_to_crs_version_pres() {
+ /**
+ * Tests the block_workflow_get_offset_time methods.
+ *
+ * @covers ::block_workflow_get_offset_time
+ */
+ public function test_block_workflow_get_offset_time_relative_to_crs_version_pres(): void {
$this->resetAfterTest();
if (!class_exists('\local_oudataload\util') || !class_exists('local_createwebsite_utils')) {
diff --git a/tests/generator/behat_block_workflow_generator.php b/tests/generator/behat_block_workflow_generator.php
index 1fa95d5..00b7250 100644
--- a/tests/generator/behat_block_workflow_generator.php
+++ b/tests/generator/behat_block_workflow_generator.php
@@ -22,8 +22,16 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+/**
+ * Behat data generator for the block_workflow plugin.
+ */
class behat_block_workflow_generator extends behat_generator_base {
+ /**
+ * Returns an array of creatable entities for the block_workflow generator.
+ *
+ * @return array List of creatable entity.
+ */
protected function get_creatable_entities(): array {
return [
'workflows' => [
diff --git a/tests/generator/lib.php b/tests/generator/lib.php
index 6cfce04..964091e 100644
--- a/tests/generator/lib.php
+++ b/tests/generator/lib.php
@@ -28,6 +28,9 @@
require_once($CFG->dirroot . '/blocks/workflow/locallib.php');
+/**
+ * Data generator class for the block_workflow plugin.
+ */
class block_workflow_generator extends testing_block_generator {
/**
@@ -60,6 +63,12 @@ public function create_workflow(array $record): block_workflow_workflow {
return $workflow;
}
+ /**
+ * Creates a workflow step with the provided record data.
+ *
+ * @param array $record Associative array containing the workflow step data.
+ * @return block_workflow_step The created workflow step instance.
+ */
public function create_workflow_step(array $record) {
$data = (object) $record;
@@ -79,6 +88,12 @@ public function create_workflow_step(array $record) {
return $step;
}
+ /**
+ * Creates an email object for testing purposes.
+ *
+ * @param string $shortname The shortname to assign to the email. Defaults to 'TESTMAIL'.
+ * @return block_workflow_email The created email object.
+ */
public function create_email($shortname = 'TESTMAIL') {
// Create a new email template.
$email = new block_workflow_email();
@@ -90,6 +105,12 @@ public function create_email($shortname = 'TESTMAIL') {
return $email;
}
+ /**
+ * Creates a new todo item for the specified workflow step.
+ *
+ * @param object $step The workflow step to create the todo item.
+ * @return block_workflow_todo The created todo item or relevant result.
+ */
public function create_todo($step) {
// Create a new todo.
$todo = new block_workflow_todo();
diff --git a/tests/lib.php b/tests/lib.php
index e12afc8..6e1c51a 100644
--- a/tests/lib.php
+++ b/tests/lib.php
@@ -20,7 +20,6 @@
* @package block_workflow
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- * @group block_workflow
*/
defined('MOODLE_INTERNAL') || die();
@@ -29,7 +28,16 @@
require_once($CFG->dirroot . '/blocks/workflow/locallib.php');
+/**
+ * Class block_workflow_testing_context_hack.
+ */
class block_workflow_testing_context_hack extends context_system {
+ /**
+ * Clears the context caches for the provided test database.
+ *
+ * @param object $testdb The test database instance whose context caches should be cleared.
+ * @return void
+ */
public static function clear_context_caches($testdb) {
// We need to reset the contexcache.
@@ -49,14 +57,32 @@ public static function clear_context_caches($testdb) {
}
}
+/**
+ * Abstract test library for the block_workflow plugin.
+ */
abstract class block_workflow_testlib extends advanced_testcase {
- // Add code coverage for the libraries.
- public static $includecoverage = array('blocks/workflow/locallib.php');
- // The test course's ID, and contextid for future reference.
+ /**
+ * @var array Add code coverage for the libraries.
+ */
+ public static $includecoverage = ['blocks/workflow/locallib.php'];
+ /**
+ * @var int The test course's ID, and contextid for future reference.
+ */
protected $courseid;
+ /**
+ * @var int The context ID associated with this instance.
+ */
protected $contextid;
+
+ /**
+ * @var array List of roles relevant to the workflow.
+ */
protected $roles;
+
+ /**
+ * @var array List of users involved in the workflow.
+ */
protected $users;
/**
@@ -107,31 +133,32 @@ public function setUp(): void {
$this->contextid = $context->id;
// Create some roles.
- $roles = array(
+ $roles = [
'manager' => 'manager',
'coursecreator' => 'coursecreator',
'teacher' => 'teacher',
'editingteacher' => 'editingteacher',
'student' => 'student',
- );
+ ];
foreach ($roles as $shortname => $archetype) {
- $role = $DB->get_record('role', array('shortname' => $shortname));
+ $role = $DB->get_record('role', ['shortname' => $shortname]);
$this->roles[$shortname] = $role->id;
}
// Create some users.
- $users = array(
+ $users = [
'egmanager' => 'manager',
'egteacher' => 'teacher',
'egeditingteacher' => 'editingteacher',
'egcoursecreator' => 'coursecreator',
'egstudent' => 'student',
- );
+ ];
foreach ($users as $username => $role) {
$user = new StdClass;
$user->username = $username;
$user->firstname = $username;
$user->lastname = $username;
+ $user->email = $username . '@localhost.com';
$user->id = $DB->insert_record('user', $user);
$assignment = new stdClass();
$assignment->roleid = $this->roles[$role];
@@ -142,7 +169,6 @@ public function setUp(): void {
}
$generator->get_plugin_generator('mod_quiz')->create_instance(['course' => $course->id]);
- $generator->get_plugin_generator('mod_chat')->create_instance(['course' => $course->id]);
}
/**
@@ -154,7 +180,7 @@ public function setUp(): void {
* @param object $step The object to compare with using assertEquals
* @param array $ignore Which fields to ignore
*/
- protected function compare_step($source, $with, $ignore = array('id', 'stepno')) {
+ protected function compare_step($source, $with, $ignore = ['id', 'stepno']) {
// If we're given a step, then grab it's expected settings.
if (is_a($source, 'block_workflow_step')) {
$fields = $source->expected_settings();
@@ -174,7 +200,7 @@ protected function compare_step($source, $with, $ignore = array('id', 'stepno'))
* @param object $workflow The object to compare with using assertEqualss
* @param array $ignore Which fields to ignore
*/
- protected function compare_workflow($source, $with, $ignore = array('id', 'shortname')) {
+ protected function compare_workflow($source, $with, $ignore = ['id', 'shortname']) {
// If we're given a workflow, then grab it's expected settings.
if (is_a($source, 'block_workflow_workflow')) {
$fields = $source->expected_settings();
@@ -194,7 +220,7 @@ protected function compare_workflow($source, $with, $ignore = array('id', 'short
* @param object $todo The object to compare with using assertEqualss
* @param array $ignore Which fields to ignore
*/
- protected function compare_email($source, $with, $ignore = array('id', 'shortname')) {
+ protected function compare_email($source, $with, $ignore = ['id', 'shortname']) {
// If we're given a todo, then grab it's expected settings.
if (is_a($source, 'block_workflow_email')) {
$fields = $source->expected_settings();
@@ -214,7 +240,7 @@ protected function compare_email($source, $with, $ignore = array('id', 'shortnam
* @param object $todo The object to compare with using assertEqualss
* @param array $ignore Which fields to ignore
*/
- protected function compare_todo($source, $with, $ignore = array('id', 'obsolete')) {
+ protected function compare_todo($source, $with, $ignore = ['id', 'obsolete']) {
// If we're given a todo, then grab it's expected settings.
if (is_a($source, 'block_workflow_todo')) {
$fields = $source->expected_settings();
@@ -225,6 +251,15 @@ protected function compare_todo($source, $with, $ignore = array('id', 'obsolete'
$this->compare_object($source, $with, $fields, $ignore);
}
+ /**
+ * Compares two objects based on specified fields, ignoring certain fields.
+ *
+ * @param object $source The source object to compare.
+ * @param object $target The target object to compare against.
+ * @param array $fields The list of fields to compare between the objects.
+ * @param array $ignore The list of fields to ignore during comparison.
+ * @return void
+ */
protected function compare_object($source, $target, $fields, $ignore) {
// Check each field.
foreach ($fields as $name) {
@@ -245,7 +280,7 @@ protected function compare_object($source, $target, $fields, $ignore) {
* @param string $command The function to run on $object
* @param mixed $args Any arguments to pass to the function
*/
- protected function expect_exception_without_halting($et, $class = null, $command) {
+ protected function expect_exception_without_halting($et, $class, $command) {
$args = func_get_args();
array_shift($args);
array_shift($args);
@@ -253,7 +288,7 @@ protected function expect_exception_without_halting($et, $class = null, $command
try {
if ($class) {
- $func = array($class, $command);
+ $func = [$class, $command];
} else {
$func = $command;
}
@@ -267,6 +302,12 @@ protected function expect_exception_without_halting($et, $class = null, $command
}
}
+ /**
+ * Creates a workflow instance for testing purposes.
+ *
+ * @param bool $createstep Whether to create a workflow step (default: true).
+ * @return block_workflow_workflow The created workflow instance or relevant test object.
+ */
protected function create_workflow($createstep = true) {
// Create a new workflow.
$data = new stdClass();
@@ -282,6 +323,12 @@ protected function create_workflow($createstep = true) {
return $workflow;
}
+ /**
+ * Creates a new step for the given workflow.
+ *
+ * @param object $workflow The workflow object to which the step will be added.
+ * @return block_workflow_step The created step object.
+ */
protected function create_step($workflow) {
// Create a new step.
$step = new block_workflow_step();
@@ -293,6 +340,12 @@ protected function create_step($workflow) {
return $step;
}
+ /**
+ * Creates an email object for testing purposes.
+ *
+ * @param string $shortname Optional. The short name to assign to the email. Default is 'TESTMAIL'.
+ * @return block_workflow_email The created email object.
+ */
protected function create_email($shortname = 'TESTMAIL') {
// Create a new todo.
$email = new block_workflow_email();
@@ -304,6 +357,12 @@ protected function create_email($shortname = 'TESTMAIL') {
return $email;
}
+ /**
+ * Creates a new todo item for the specified workflow step.
+ *
+ * @param object $step The workflow step for which to create the todo item.
+ * @return block_workflow_todo The created todo item.
+ */
protected function create_todo($step) {
// Create a new todo.
$todo = new block_workflow_todo();
@@ -314,6 +373,12 @@ protected function create_todo($step) {
return $todo;
}
+ /**
+ * Assigns a workflow to the current context or object.
+ *
+ * @param object $workflow The workflow instance.
+ * @return mixed
+ */
protected function assign_workflow($workflow) {
global $DB;
@@ -330,12 +395,19 @@ protected function assign_workflow($workflow) {
INNER JOIN {context} c ON c.instanceid = cm.id
INNER JOIN {modules} md ON md.id = cm.module
WHERE md.name = ? AND cm.course = ? LIMIT 1";
- $instance = $DB->get_record_sql($sql, array($module, $this->courseid));
+ $instance = $DB->get_record_sql($sql, [$module, $this->courseid]);
// Create the activity for this type of workflow.
return $workflow->add_to_context($instance->id);
}
+ /**
+ * Creates a workflow for a specified activity type.
+ *
+ * @param string $appliesto The type of activity the workflow applies to.
+ * @param bool $createstep Whether to create an initial step in the workflow. Defaults to true.
+ * @return block_workflow_workflow The created workflow object or relevant data structure.
+ */
protected function create_activity_workflow($appliesto, $createstep = true) {
// Create a new workflow.
$data = new stdClass();
@@ -412,6 +484,13 @@ protected function create_version_pres_tables() {
$DB->execute("TRUNCATE vl_v_crs_version_pres");
}
+ /**
+ * Calculates and returns a date based on the specified number of days before or after the current date.
+ *
+ * @param int $days The number of days to add or subtract from the current date.
+ * @param string $beforeafter Determines whether to calculate the date 'before' or 'after' the current date. Default is 'after'.
+ * @return int The calculated data.
+ */
protected function get_days($days, $beforeafter = 'after') {
if ($beforeafter === 'before') {
return -($days * 24 * 60 * 60);
@@ -452,7 +531,7 @@ protected function create_a_workflow_with_one_step($stepoptions, $appliesto = 'c
// Update current step.
$newstep = new block_workflow_step($step1->id);
$newstep->update_step($step1);
- return array($workflow, $step1);
+ return [$workflow, $step1];
}
/**
@@ -465,32 +544,32 @@ protected function create_a_workflow_with_one_step($stepoptions, $appliesto = 'c
*/
protected function create_expected_active_step($state, $step, $appliesto, $course, $cmid = 0, $type = 'autofinish') {
if ($type == 'autofinish') {
- return array($state->id => (object)array(
- 'stateid' => $state->id,
- 'stepid' => $step->id,
- 'state' => BLOCK_WORKFLOW_STATE_ACTIVE,
- 'workflowid' => $step->workflowid,
- 'appliesto' => $appliesto,
- 'stepname' => $step->name,
- 'autofinish' => $step->autofinish,
- 'autofinishoffset' => $step->autofinishoffset,
- 'courseid' => ($course ? $course->id : null),
- 'courseshortname' => ($course ? $course->shortname : null),
- 'moduleid' => $cmid)
- );
- }
- return array($state->id => (object)array(
+ return [$state->id => (object)[
'stateid' => $state->id,
'stepid' => $step->id,
'state' => BLOCK_WORKFLOW_STATE_ACTIVE,
'workflowid' => $step->workflowid,
'appliesto' => $appliesto,
'stepname' => $step->name,
- 'extranotify' => $step->extranotify,
- 'extranotifyoffset' => "$step->extranotifyoffset",
+ 'autofinish' => $step->autofinish,
+ 'autofinishoffset' => $step->autofinishoffset,
'courseid' => ($course ? $course->id : null),
'courseshortname' => ($course ? $course->shortname : null),
- 'moduleid' => $cmid)
- );
+ 'moduleid' => $cmid,
+ ]];
+ }
+ return [$state->id => (object)[
+ 'stateid' => $state->id,
+ 'stepid' => $step->id,
+ 'state' => BLOCK_WORKFLOW_STATE_ACTIVE,
+ 'workflowid' => $step->workflowid,
+ 'appliesto' => $appliesto,
+ 'stepname' => $step->name,
+ 'extranotify' => $step->extranotify,
+ 'extranotifyoffset' => "$step->extranotifyoffset",
+ 'courseid' => ($course ? $course->id : null),
+ 'courseshortname' => ($course ? $course->shortname : null),
+ 'moduleid' => $cmid,
+ ]];
}
}
diff --git a/tests/lib_test.php b/tests/lib_test.php
index 8efbeb1..75dd43b 100644
--- a/tests/lib_test.php
+++ b/tests/lib_test.php
@@ -35,7 +35,10 @@
global $CFG;
require_once(dirname(__FILE__) . '/lib.php');
-class lib_test extends \block_workflow_testlib {
+/**
+ * Unit test class for the block_workflow library.
+ */
+final class lib_test extends \block_workflow_testlib {
/**
* Test that each of the defined variables are set correctly
@@ -44,8 +47,10 @@ class lib_test extends \block_workflow_testlib {
* - BLOCK_WORKFLOW_STATE_ABORTED
* - BLOCK_WORKFLOW_ENABLED
* - BLOCK_WORKFLOW_OBSOLETE
+ *
+ * @coversNothing
*/
- public function test_defines() {
+ public function test_defines(): void {
$this->assertEquals(BLOCK_WORKFLOW_STATE_ACTIVE, 'active');
$this->assertEquals(BLOCK_WORKFLOW_STATE_COMPLETED, 'completed');
$this->assertEquals(BLOCK_WORKFLOW_STATE_ABORTED, 'aborted');
@@ -53,7 +58,12 @@ public function test_defines() {
$this->assertEquals(BLOCK_WORKFLOW_OBSOLETE, 1);
}
- public function test_workflow_validation() {
+ /**
+ * Tests the block_workflow_workflow validation method.
+ *
+ * @covers ::block_workflow_workflow
+ */
+ public function test_workflow_validation(): void {
// Create a new workflow.
$data = new stdClass();
$workflow = new block_workflow_workflow();
@@ -92,7 +102,12 @@ public function test_workflow_validation() {
$workflow, 'create_workflow', $data);
}
- public function test_workflow_validation2() {
+ /**
+ * Tests the block_workflow_workflow validation method.
+ *
+ * @covers ::block_workflow_workflow
+ */
+ public function test_workflow_validation2(): void {
// Create a new workflow.
$data = new stdClass();
$workflow = new block_workflow_workflow();
@@ -127,7 +142,12 @@ public function test_workflow_validation2() {
$workflow, 'create_workflow', $data);
}
- public function test_workflow_validation3() {
+ /**
+ * Tests the block_workflow_workflow validation method.
+ *
+ * @covers ::block_workflow_workflow
+ */
+ public function test_workflow_validation3(): void {
// Create a new workflow.
$data = new stdClass();
$workflow = new block_workflow_workflow();
@@ -200,8 +220,10 @@ public function test_workflow_validation3() {
* - adding a step and checking it's data;
* - cloning that step and checking it's data; and
* - re-ordering the steps and checking the resultant data.
+ *
+ * @covers ::block_workflow_workflow
*/
- public function test_workflow() {
+ public function test_workflow(): void {
// Create a new workflow object.
$workflow = new block_workflow_workflow();
@@ -269,7 +291,13 @@ public function test_workflow() {
$this->expect_exception_without_halting('block_workflow_invalid_workflow_exception', $workflow, 'create_workflow', $data);
}
- public function test_workflow_toggle() {
+
+ /**
+ * Tests the block_workflow_step toggle method.
+ *
+ * @covers ::block_workflow_workflow::toggle
+ */
+ public function test_workflow_toggle(): void {
$workflow = new block_workflow_workflow();
// Create a new workflow.
@@ -300,7 +328,12 @@ public function test_workflow_toggle() {
$this->assertEquals($workflow->context(), CONTEXT_COURSE);
}
- public function test_workflow_steps() {
+ /**
+ * Tests the block_workflow_step method.
+ *
+ * @covers ::block_workflow_step
+ */
+ public function test_workflow_steps(): void {
// Create a new workflow.
$data = new stdClass();
$data->shortname = 'courseworkflow';
@@ -385,7 +418,12 @@ public function test_workflow_steps() {
$this->assertNull($workflow->atendgobacktostep);
}
- public function test_workflow_steps_2() {
+ /**
+ * Tests the block_workflow_step method.
+ *
+ * @covers ::block_workflow_step
+ */
+ public function test_workflow_steps_2(): void {
// Create a new workflow.
$data = new stdClass();
$data->shortname = 'courseworkflow';
@@ -510,7 +548,12 @@ public function test_workflow_steps_2() {
$step, 'load_workflow_stepno', -1, -1);
}
- public function test_workflow_extended_exception() {
+ /**
+ * Tests the workflow extended exception.
+ *
+ * @covers ::block_workflow_step
+ */
+ public function test_workflow_extended_exception(): void {
// Create a new workflow.
$data = new stdClass();
$data->shortname = 'courseworkflow';
@@ -567,7 +610,13 @@ public function test_workflow_extended_exception() {
$this->expect_exception_without_halting('block_workflow_invalid_step_exception',
$newstep, 'create_step', $nsdata);
}
- public function test_workflow_extended() {
+
+ /**
+ * Tests the block_workflow_step.
+ *
+ * @covers ::block_workflow_step
+ */
+ public function test_workflow_extended(): void {
// Create a new workflow.
$data = new stdClass();
$data->shortname = 'courseworkflow';
@@ -616,7 +665,12 @@ public function test_workflow_extended() {
$step->delete();
}
- public function test_workflow_clone_exception() {
+ /**
+ * Tests the block_workflow_workflow workflow clone exception method.
+ *
+ * @covers ::block_workflow_workflow
+ */
+ public function test_workflow_clone_exception(): void {
// Create a new workflow.
$data = new stdClass();
$data->shortname = 'courseworkflow';
@@ -654,7 +708,12 @@ public function test_workflow_clone_exception() {
'block_workflow_workflow', 'clone_workflow', $workflow->id, $newdata);
}
- public function test_workflow_clone() {
+ /**
+ * Tests the block_workflow_workflow workflow clone method.
+ *
+ * @covers ::block_workflow_workflow
+ */
+ public function test_workflow_clone(): void {
// Create a new workflow.
$data = new stdClass();
$data->shortname = 'courseworkflow';
@@ -701,10 +760,10 @@ public function test_workflow_clone() {
$tmp, '__construct', $cloneid);
// And then faking the form submission editor part too.
- $newdata->description_editor = array(
+ $newdata->description_editor = [
'text' => 'Example text',
'format' => FORMAT_HTML,
- );
+ ];
$clone = block_workflow_workflow::clone_workflow($workflow->id, $newdata);
// And remove them both.
@@ -712,7 +771,12 @@ public function test_workflow_clone() {
}
- public function test_course_workflow() {
+ /**
+ * Tests the block_workflow_workflow available_workflows method.
+ *
+ * @covers ::block_workflow_workflow
+ */
+ public function test_course_workflow(): void {
$workflow = $this->create_workflow();
// Retrieve a list of all workflows available to courses.
@@ -742,7 +806,12 @@ public function test_course_workflow() {
$workflow, 'add_to_context', $this->contextid);
}
- public function test_course_workflow_2() {
+ /**
+ * Tests the available_workflows method.
+ *
+ * @covers ::block_workflow_workflow
+ */
+ public function test_course_workflow_2(): void {
$workflow = $this->create_workflow();
// Retrieve a list of all workflows available to courses.
@@ -828,7 +897,12 @@ public function test_course_workflow_2() {
$workflow, 'remove_workflow', $this->contextid);
}
- public function test_activity_workflow() {
+ /**
+ * Tests the block_workflow_workflow method.
+ *
+ * @covers ::block_workflow_workflow
+ */
+ public function test_activity_workflow(): void {
// Create a new workflow.
$data = new stdClass();
$data->shortname = 'activityworkflow';
@@ -849,18 +923,34 @@ public function test_activity_workflow() {
$this->assertEquals($workflow->context(), CONTEXT_MODULE);
}
- public function test_appliesto_list() {
+ /**
+ * Tests the block_workflow_appliesto_list method.
+ *
+ * @covers ::block_workflow_appliesto_list
+ */
+ public function test_appliesto_list(): void {
$list = block_workflow_appliesto_list();
$this->assertEquals('array', gettype($list));
$this->assertNotEquals(count($list), 0);
}
- public function test_editor_options() {
+ /**
+ * Tests the block_workflow_editor_options method.
+ *
+ * @covers ::block_workflow_editor_options
+ */
+ public function test_editor_options(): void {
$format = block_workflow_editor_options();
$this->assertEquals($format['maxfiles'], 0);
}
- public function test_editor_format() {
+ /**
+ * Tests the block_workflow_editor_format, block_workflow_convert_editor_format method.
+ *
+ * @covers ::block_workflow_editor_format
+ * @covers ::block_workflow_convert_editor_format
+ */
+ public function test_editor_format(): void {
$this->assertEquals(block_workflow_editor_format(FORMAT_HTML), get_string('format_html', 'block_workflow'));
$this->assertEquals(block_workflow_editor_format(FORMAT_PLAIN), get_string('format_plain', 'block_workflow'));
$this->assertEquals(block_workflow_editor_format(-1), get_string('format_unknown', 'block_workflow'));
@@ -872,7 +962,12 @@ public function test_editor_format() {
null, 'block_workflow_convert_editor_format', 'baddata');
}
- public function test_appliesto_string() {
+ /**
+ * Tests the block_workflow_appliesto method.
+ *
+ * @covers ::block_workflow_appliesto
+ */
+ public function test_appliesto_string(): void {
// Test that we get the correct strings from block_workflow_appliesto for both of it's routes.
$this->assertEquals(block_workflow_appliesto('course'), get_string('course'));
$this->assertEquals(block_workflow_appliesto('quiz'), get_string('pluginname', 'mod_quiz'));
diff --git a/tests/privacy_provider_test.php b/tests/privacy_provider_test.php
index 81db25e..9e06b9d 100644
--- a/tests/privacy_provider_test.php
+++ b/tests/privacy_provider_test.php
@@ -40,7 +40,7 @@
* @copyright 2018 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class privacy_provider_test extends \core_privacy\tests\provider_testcase {
+final class privacy_provider_test extends \core_privacy\tests\provider_testcase {
/** @var \stdClass A student who is enrolled in course */
protected $student1;
@@ -64,6 +64,7 @@ class privacy_provider_test extends \core_privacy\tests\provider_testcase {
* Set up for each test
*/
public function setUp(): void {
+ parent::setUp();
$this->resetAfterTest(true);
$this->setAdminUser();
@@ -117,13 +118,15 @@ public function setUp(): void {
$this->todo->create_todo($data);
// Toggle the to-do item.
- $state->todo_toggle($this->todo->id);
+ $state->todo_toggle($this->todo->id, true);
}
/**
* Test for provider::get_contexts_for_userid().
+ *
+ * @covers \block_workflow\privacy\provider::get_contexts_for_userid
*/
- public function test_get_contexts_for_userid() {
+ public function test_get_contexts_for_userid(): void {
// Get workflow context for student1.
$contextids = provider::get_contexts_for_userid($this->student1->id)->get_contextids();
@@ -133,8 +136,10 @@ public function test_get_contexts_for_userid() {
/**
* Test for provider::get_users_in_context().
+ *
+ * @covers \block_workflow\privacy\provider::get_users_in_context
*/
- public function test_get_users_in_context() {
+ public function test_get_users_in_context(): void {
$userlist = new userlist($this->coursecontext, 'block_workflow');
$this->assertCount(0, $userlist);
provider::get_users_in_context($userlist);
@@ -144,8 +149,10 @@ public function test_get_users_in_context() {
/**
* Test for provider::export_user_data().
+ *
+ * @covers \block_workflow\privacy\provider::export_user_data
*/
- public function test_export_user_data() {
+ public function test_export_user_data(): void {
// Get workflow context for student1.
$contextids = provider::get_contexts_for_userid($this->student1->id)->get_contextids();
$context = \context::instance_by_id($contextids[0]);
@@ -164,28 +171,30 @@ public function test_export_user_data() {
'description' => $this->workflow->description,
'stepname' => $this->step->name,
'userid' => get_string('privacy_you', 'block_workflow'),
- 'newstate' => 'active'
+ 'newstate' => 'active',
], $data->statechangedata[0]);
$this->assertEquals((object)[
'workflowname' => $this->workflow->name,
'description' => $this->workflow->description,
'stepname' => $this->step->name,
'userid' => get_string('privacy_you', 'block_workflow'),
- 'newstate' => 'completed'
+ 'newstate' => 'completed',
], $data->statechangedata[1]);
// Check student1 has one task done.
$this->assertEquals((object)[
'stepname' => $this->step->name,
'taskdone' => $this->todo->task,
- 'userid' => get_string('privacy_you', 'block_workflow')
+ 'userid' => get_string('privacy_you', 'block_workflow'),
], $data->tododonedata[0]);
}
/**
* Test for delete_data_for_user().
+ *
+ * @covers \block_workflow\privacy\provider::delete_data_for_user
*/
- public function test_delete_data_for_user() {
+ public function test_delete_data_for_user(): void {
global $DB;
// Get workflow context for student1.
$contextids = provider::get_contexts_for_userid($this->student1->id)->get_contextids();
@@ -203,9 +212,11 @@ public function test_delete_data_for_user() {
}
/**
- * Test for provider::test_delete_data_for_users().
+ * Test for provider::delete_data_for_users().
+ *
+ * @covers \block_workflow\privacy\provider::delete_data_for_users
*/
- public function test_delete_data_for_users() {
+ public function test_delete_data_for_users(): void {
global $DB;
// Get workflow context for student1.
$approveduserids = [$this->student1->id];
@@ -224,8 +235,10 @@ public function test_delete_data_for_users() {
/**
* Test for delete_data_for_all_users_in_context().
+ *
+ * @covers \block_workflow\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 {
global $DB;
// Add the workflow to our course (returns the block_workflow_step_state).
@@ -243,7 +256,7 @@ public function test_delete_data_for_all_users_in_context() {
$this->todo->create_todo($data);
// Toggle the to-do item.
- $state->todo_toggle($this->todo->id);
+ $state->todo_toggle($this->todo->id, true);
$params = ['statescontextid' => $this->coursecontext->id];
$statechangesql = "SELECT statechanges.id, statechanges.userid
diff --git a/tests/steps_test.php b/tests/steps_test.php
index 69a1973..2f891a1 100644
--- a/tests/steps_test.php
+++ b/tests/steps_test.php
@@ -37,8 +37,19 @@
global $CFG;
require_once(dirname(__FILE__) . '/lib.php');
-class steps_test extends \block_workflow_testlib {
- public function test_step_validation() {
+/**
+ * Unit tests for the workflow steps functionality in the block_workflow plugin.
+ *
+ * This class extends the block_workflow_testlib to provide test cases
+ * for verifying the behavior and integrity of workflow steps.
+ */
+final class steps_test extends \block_workflow_testlib {
+ /**
+ * Tests the create_step methods.
+ *
+ * @covers \block_workflow_step::create_step
+ */
+ public function test_step_validation(): void {
// Create a new workflow.
$workflow = $this->create_workflow();
@@ -91,7 +102,18 @@ public function test_step_validation() {
unset($data->oncompletescript);
}
- public function test_step_validation_2() {
+ /**
+ * Tests the create_step, update_step methods.
+ *
+ * @covers \block_workflow_step::create_step
+ * @covers \block_workflow_step::update_step
+ * @covers \block_workflow_step::delete
+ * @covers \block_workflow_step::load_workflow_stepno
+ * @covers \block_workflow_workflow::update
+ * @covers \block_workflow_workflow::load_workflow
+ * @covers \block_workflow_workflow::steps
+ */
+ public function test_step_validation_2(): void {
// Create a new workflow.
$workflow = $this->create_workflow();
@@ -190,7 +212,13 @@ public function test_step_validation_2() {
unset($data->oncompletescript);
}
- public function test_step_validation_3() {
+ /**
+ * Tests the create_step methods.
+ *
+ * @covers \block_workflow_step::create_step
+ * @covers \block_workflow_step::update_step
+ */
+ public function test_step_validation_3(): void {
// Create a new workflow.
$workflow = $this->create_workflow();
@@ -272,6 +300,8 @@ public function test_step_validation_3() {
}
/**
+ * Tests the toggle_role methods.
+ *
* Test toggling of block_workflow_step roles
* - Ensure that we can add a role
* - Ensure that we get the right result from step->roles()
@@ -281,8 +311,11 @@ public function test_step_validation_3() {
* - Ensure that we get the right result from step->roles()
* - Ensure that we can remove the second role
* - Ensure that we get the right result from step->roles()
+ *
+ * @covers \block_workflow_step::toggle_role
+ * @covers \block_workflow_step::roles
*/
- public function test_step_roles() {
+ public function test_step_roles(): void {
global $DB;
// Create a new workflow.
$data = new stdClass();
@@ -304,7 +337,7 @@ public function test_step_roles() {
$step->load_workflow_stepno($workflow->id, 1);
// Find the ID for the manager role.
- $managerid = $DB->get_field('role', 'id', array('shortname' => 'manager'));
+ $managerid = $DB->get_field('role', 'id', ['shortname' => 'manager']);
// Enable the role.
$return = $step->toggle_role($managerid);
@@ -323,7 +356,7 @@ public function test_step_roles() {
$this->assertEquals($thisrole->id, $managerid);
// Add a second role.
- $teacherid = $DB->get_field('role', 'id', array('shortname' => 'teacher'));
+ $teacherid = $DB->get_field('role', 'id', ['shortname' => 'teacher']);
// Enable the second role.
$return = $step->toggle_role($teacherid);
@@ -364,7 +397,12 @@ public function test_step_roles() {
$this->assertEquals(count($return), 0);
}
- public function test_script_parse() {
+ /**
+ * Tests the parse_script methods.
+ *
+ * @covers \block_workflow_step::parse_script
+ */
+ public function test_script_parse(): void {
// Create a new workflow and step.
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
@@ -382,7 +420,14 @@ public function test_script_parse() {
$this->assertEquals(count($command->errors), 0);
}
- public function test_script_validation() {
+ /**
+ * Tests the is_script_valid, require_script_valid, get_validation_errors methods.
+ *
+ * @covers \block_workflow_step::is_script_valid
+ * @covers \block_workflow_step::require_script_valid
+ * @covers \block_workflow_step::get_validation_errors
+ */
+ public function test_script_validation(): void {
// Create a new workflow and step.
$workflow = $this->create_workflow(false);
$step = $this->create_step($workflow);
@@ -415,7 +460,14 @@ public function test_script_validation() {
$this->assertEquals(count($errors), 0);
}
- public function test_step_commands() {
+ /**
+ * Tests the validate_script, update_step, create methods.
+ *
+ * @covers \block_workflow_step::validate_script
+ * @covers \block_workflow_step::update_step
+ * @covers \block_workflow_email::create
+ */
+ public function test_step_commands(): void {
// Create a new workflow.
$data = new stdClass();
$data->shortname = 'courseworkflow';
@@ -496,7 +548,12 @@ public function test_step_commands() {
$this->expect_exception_without_halting('block_workflow_invalid_command_exception', $step, 'update_step', $update);
}
- public function test_next_step_end() {
+ /**
+ * Tests the get_next_step method.
+ *
+ * @covers \block_workflow_step::get_next_step
+ */
+ public function test_next_step_end(): void {
// Create a new workflow.
$workflow = $this->create_workflow(false);
@@ -521,7 +578,12 @@ public function test_next_step_end() {
$this->assertFalse($getnext);
}
- public function test_next_step_loop() {
+ /**
+ * Tests the get_next_step method.
+ *
+ * @covers \block_workflow_step::get_next_step
+ */
+ public function test_next_step_loop(): void {
// Create a new workflow.
$workflow = $this->create_workflow(false);
@@ -553,7 +615,12 @@ public function test_next_step_loop() {
$this->compare_step($firststep, $getnext);
}
- public function test_set_workflow() {
+ /**
+ * Tests the set_workflow method.
+ *
+ * @covers \block_workflow_step::set_workflow
+ */
+ public function test_set_workflow(): void {
$step = new block_workflow_step();
$step->set_workflow(1);
$this->assertEquals($step->workflowid, 1);
@@ -563,7 +630,12 @@ public function test_set_workflow() {
'set_workflow', 1);
}
- public function test_get_all_users_and_their_roles() {
+ /**
+ * Tests the get_all_users_and_their_roles method.
+ *
+ * @covers \block_workflow_step_state::get_all_users_and_their_roles
+ */
+ public function test_get_all_users_and_their_roles(): void {
global $DB;
$this->resetAfterTest(true);
@@ -571,7 +643,7 @@ public function test_get_all_users_and_their_roles() {
$roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
$roles = $DB->get_records('role');
- $rolenames = array();
+ $rolenames = [];
$rolenames['manager'] = 'Manager';
$rolenames['coursecreator'] = 'Course creater';
$rolenames['editingteacher'] = 'Teacher';
@@ -593,12 +665,12 @@ public function test_get_all_users_and_their_roles() {
// Create users.
$maxnumberofusers = 5;
- $users = array();
+ $users = [];
for ($index = 1; $index < ($maxnumberofusers + 1); $index++) {
- $users[$index] = $generator->create_user(array('username' => 'user' . $index));
+ $users[$index] = $generator->create_user(['username' => 'user' . $index]);
}
// Create a course.
- $course = $generator->create_course(array('shortname' => 'MK123-12J'));
+ $course = $generator->create_course(['shortname' => 'MK123-12J']);
$coursecontext = \context_course::instance($course->id);
// Users one to 5 get following roles.
@@ -609,16 +681,16 @@ public function test_get_all_users_and_their_roles() {
// user5 is a student.
$manualenrol = enrol_get_plugin('manual');
$manualenrol->add_default_instance($course);
- $instance1 = $DB->get_record('enrol', array('enrol' => 'manual', 'courseid' => $course->id));
+ $instance1 = $DB->get_record('enrol', ['enrol' => 'manual', 'courseid' => $course->id]);
foreach ($users as $i => $user) {
$manualenrol->enrol_user($instance1, $user->id, $roleids[$roles[$i]->shortname]);
}
- $expectedroles = array();
+ $expectedroles = [];
- $expectedusers = array();
+ $expectedusers = [];
foreach ($users as $key => $user) {
- $user->roles = array();
+ $user->roles = [];
$user->roles[] = $rolenames[$roles[$key]->shortname];
$expectedusers[$user->id] = $user;
}
diff --git a/tests/todos_test.php b/tests/todos_test.php
index 5d0a66c..0afc42b 100644
--- a/tests/todos_test.php
+++ b/tests/todos_test.php
@@ -34,8 +34,19 @@
global $CFG;
require_once(dirname(__FILE__) . '/lib.php');
-class todos_test extends \block_workflow_testlib {
- public function test_todo_validation() {
+/**
+ * Unit tests for the block_workflow plugin's todo functionality.
+ *
+ * This class contains test cases for verifying the behavior and features
+ * related to todos in the block_workflow plugin.
+ */
+final class todos_test extends \block_workflow_testlib {
+ /**
+ * Tests the validation method of the block_workflow_todo class.
+ *
+ * @covers \block_workflow_todo::validation
+ */
+ public function test_todo_validation(): void {
// Create a new workflow.
$workflow = $this->create_workflow();
@@ -71,7 +82,12 @@ public function test_todo_validation() {
$data->obsolete = BLOCK_WORKFLOW_OBSOLETE;
}
- public function test_todo_create() {
+ /**
+ * Tests the create_todo method of the block_workflow_todo class.
+ *
+ * @covers \block_workflow_todo::create_todo
+ */
+ public function test_todo_create(): void {
// Create a new workflow.
$workflow = $this->create_workflow();
@@ -108,7 +124,12 @@ public function test_todo_create() {
unset($data->badfield);
}
- public function test_todo_update() {
+ /**
+ * Tests the update_todo method of the block_workflow_todo class.
+ *
+ * @covers \block_workflow_todo::update_todo
+ */
+ public function test_todo_update(): void {
// Create a new workflow.
$workflow = $this->create_workflow();
@@ -136,10 +157,15 @@ public function test_todo_update() {
$todo->update_todo($data);
// Compare the updated task.
- $this->compare_todo($data, $todo, array('id'));
+ $this->compare_todo($data, $todo, ['id']);
}
- public function test_todo_loading() {
+ /**
+ * Tests the load_by_id method of the block_workflow_todo class.
+ *
+ * @covers \block_workflow_todo::load_by_id
+ */
+ public function test_todo_loading(): void {
// Create a new workflow.
$workflow = $this->create_workflow();
@@ -160,7 +186,12 @@ public function test_todo_loading() {
$this->compare_todo($todo, $reloaded);
}
- public function test_todo_clone() {
+ /**
+ * Tests the clone_todo method of the block_workflow_todo class.
+ *
+ * @covers \block_workflow_todo::clone_todo
+ */
+ public function test_todo_clone(): void {
// Create a new workflow.
$workflow = $this->create_workflow();
@@ -173,19 +204,24 @@ public function test_todo_clone() {
// Clone the todo.
$clone = $todo->clone_todo($todo->id);
- $this->compare_todo($todo, $clone, array('id'));
+ $this->compare_todo($todo, $clone, ['id']);
$this->assertNotEquals($todo->id, $clone->id);
// Add a second step and clone the task from the first step.
$newstep = $this->create_step($workflow);
$clone = $todo->clone_todo($todo->id, $newstep->id);
- $this->compare_todo($todo, $clone, array('id', 'stepid'));
+ $this->compare_todo($todo, $clone, ['id', 'stepid']);
$this->assertNotEquals($todo->id, $clone->id);
$this->assertNotEquals($todo->stepid, $clone->stepid);
$this->assertEquals($clone->stepid, $newstep->id);
}
- public function test_todo_delete() {
+ /**
+ * Tests the delete_todo method of the block_workflow_todo class.
+ *
+ * @covers \block_workflow_todo::delete_todo
+ */
+ public function test_todo_delete(): void {
// Create a new workflow.
$workflow = $this->create_workflow();
@@ -204,7 +240,12 @@ public function test_todo_delete() {
$reload, 'load_by_id', $todo->id);
}
- public function test_todo_toggle() {
+ /**
+ * Tests the toggle functionality of the block_workflow_todo class.
+ *
+ * @covers \block_workflow_todo::toggle
+ */
+ public function test_todo_toggle(): void {
// Create a new workflow.
$workflow = $this->create_workflow();
@@ -232,16 +273,21 @@ public function test_todo_toggle() {
$return = block_workflow_todo::toggle_task($todo->id);
$check = new block_workflow_todo($todo->id);
$this->assertEquals($check->obsolete, BLOCK_WORKFLOW_OBSOLETE);
- $this->compare_todo($return, $check, array());
+ $this->compare_todo($return, $check, []);
// And also to re-enable.
$return = block_workflow_todo::toggle_task($todo->id);
$check = new block_workflow_todo($todo->id);
$this->assertEquals($check->obsolete, BLOCK_WORKFLOW_ENABLED);
- $this->compare_todo($return, $check, array());
+ $this->compare_todo($return, $check, []);
}
- public function test_todo_step() {
+ /**
+ * Tests the validation logic for the todo step in the workflow.
+ *
+ * @covers \block_workflow_todo::step
+ */
+ public function test_todo_step(): void {
// Create a new workflow.
$workflow = $this->create_workflow();
diff --git a/tests/walkthrough_test.php b/tests/walkthrough_test.php
index 4690570..88afe1f 100644
--- a/tests/walkthrough_test.php
+++ b/tests/walkthrough_test.php
@@ -43,7 +43,7 @@
* @copyright 2011 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class walkthrough_test extends \advanced_testcase {
+final class walkthrough_test extends \advanced_testcase {
/**
* Test some of the basic workflow actions including:
@@ -52,8 +52,11 @@ class walkthrough_test extends \advanced_testcase {
* - adding a step and checking it's data;
* - cloning that step and checking it's data; and
* - re-ordering the steps and checking the resultant data.
+ *
+ * @covers \block_workflow_workflow
+ * @covers \block_workflow_step
*/
- public function test_course_workflow() {
+ public function test_course_workflow(): void {
global $DB;
$this->resetAfterTest(true);
@@ -61,15 +64,15 @@ public function test_course_workflow() {
// Create a course ready to test with.
$generator = $this->getDataGenerator();
- $egstudent = $generator->create_user(array('username' => 'egstudent'));
- $u2 = $generator->create_user(array('username' => 'u2'));
+ $egstudent = $generator->create_user(['username' => 'egstudent']);
+ $u2 = $generator->create_user(['username' => 'u2']);
- $course = $generator->create_course(array('shortname' => 'X943-12K'));
+ $course = $generator->create_course(['shortname' => 'X943-12K']);
$coursecontext = \context_course::instance($course->id);
$manualenrol = enrol_get_plugin('manual');
$manualenrol->add_default_instance($course);
- $instance1 = $DB->get_record('enrol', array('enrol' => 'manual', 'courseid' => $course->id));
+ $instance1 = $DB->get_record('enrol', ['enrol' => 'manual', 'courseid' => $course->id]);
$manualenrol->enrol_user($instance1, $egstudent->id, $roleids['student']);
// Create a new workflow object.
@@ -118,15 +121,15 @@ public function test_course_workflow() {
$this->assertEquals(BLOCK_WORKFLOW_STATE_ACTIVE, $state->state);
// Verify that student is now a teacher - i.e. that step 1's onactivescript ran.
- $this->assertTrue($DB->record_exists('role_assignments', array(
+ $this->assertTrue($DB->record_exists('role_assignments', [
'userid' => $egstudent->id,
'roleid' => $roleids['teacher'],
'contextid' => $coursecontext->id,
'component' => 'block_workflow',
- )));
+ ]));
// Hide the course, so we can test if the onactivescript runs.
- $DB->set_field('course', 'visible', '0', array('id' => $course->id));
+ $DB->set_field('course', 'visible', '0', ['id' => $course->id]);
// Finish the first step.
$state2 = $state->finish_step('Comment on task 1', FORMAT_HTML);
@@ -140,18 +143,18 @@ public function test_course_workflow() {
$this->assertEquals(BLOCK_WORKFLOW_STATE_ACTIVE, $state2->state);
// Verify the role assignment from task 1 was removed.
- $this->assertFalse($DB->record_exists('role_assignments', array(
+ $this->assertFalse($DB->record_exists('role_assignments', [
'userid' => $egstudent->id,
'roleid' => $roleids['teacher'],
'contextid' => $coursecontext->id,
'component' => 'block_workflow',
- )));
+ ]));
// Verify the start script from task 2 ran.
- $this->assertTrue((bool) $DB->get_field('course', 'visible', array('id' => $course->id)));
+ $this->assertTrue((bool) $DB->get_field('course', 'visible', ['id' => $course->id]));
// The next line is redundant unless the previous assert failed, which
// was the case at one time.
- $DB->set_field('course', 'visible', 1, array('id' => $course->id));
+ $DB->set_field('course', 'visible', 1, ['id' => $course->id]);
// Jump back to step 1.
$state1again = $state2->jump_to_step(null, $step1->id);
@@ -165,24 +168,24 @@ public function test_course_workflow() {
$this->assertEquals(BLOCK_WORKFLOW_STATE_ACTIVE, $state1again->state);
// Verify that student is now a teacher - i.e. that step 1's onactivescript ran.
- $this->assertTrue($DB->record_exists('role_assignments', array(
+ $this->assertTrue($DB->record_exists('role_assignments', [
'userid' => $egstudent->id,
'roleid' => $roleids['teacher'],
'contextid' => $coursecontext->id,
'component' => 'block_workflow',
- )));
+ ]));
// Verify that step 2's oncomplete script did not run.
- $this->assertTrue((bool) $DB->get_field('course', 'visible', array('id' => $course->id)));
+ $this->assertTrue((bool) $DB->get_field('course', 'visible', ['id' => $course->id]));
// Now hide the course so we can tell if the onactive scripts runs in a minute.
- $DB->set_field('course', 'visible', 0, array('id' => $course->id));
+ $DB->set_field('course', 'visible', 0, ['id' => $course->id]);
// Finish both steps, and hence the workflow.
$state2again = $state1again->finish_step('Updated comment on task 1', FORMAT_HTML);
// Verify that step 2's onactive script ran.
- $this->assertTrue((bool) $DB->get_field('course', 'visible', array('id' => $course->id)));
+ $this->assertTrue((bool) $DB->get_field('course', 'visible', ['id' => $course->id]));
$results = $state2again->finish_step('Comment on task 2', FORMAT_HTML);
@@ -190,17 +193,17 @@ public function test_course_workflow() {
$this->assertSame(false, $results);
// Check that step 2's oncomplete script ran.
- $this->assertFalse((bool) $DB->get_field('course', 'visible', array('id' => $course->id)));
+ $this->assertFalse((bool) $DB->get_field('course', 'visible', ['id' => $course->id]));
// Start the workflow yet again.
$state = $workflow->add_to_context($coursecontext->id);
// Verify that student is now a teacher - i.e. that step 1's onactivescript ran.
- $this->assertTrue($DB->record_exists('role_assignments', array(
+ $this->assertTrue($DB->record_exists('role_assignments', [
'userid' => $egstudent->id,
'roleid' => $roleids['teacher'],
'contextid' => $coursecontext->id,
'component' => 'block_workflow',
- )));
+ ]));
}
}
diff --git a/togglerole.php b/togglerole.php
index 6181c8a..b714430 100644
--- a/togglerole.php
+++ b/togglerole.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
@@ -42,4 +43,4 @@
$step->toggle_role($roleid);
// Redirect.
-redirect(new moodle_url('/blocks/workflow/editstep.php', array('stepid' => $stepid)));
+redirect(new moodle_url('/blocks/workflow/editstep.php', ['stepid' => $stepid]));
diff --git a/toggletaskdone.php b/toggletaskdone.php
index 598423f..e299b60 100644
--- a/toggletaskdone.php
+++ b/toggletaskdone.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
@@ -41,7 +42,7 @@
require_capability('block/workflow:dostep', $context);
// Toggle the todo item.
-$state->todo_toggle($todoid);
+$state->todo_toggle($todoid, true);
if ($returnto) {
redirect(new moodle_url($returnto));
diff --git a/toggletaskobsolete.php b/toggletaskobsolete.php
index d229b09..280c1b5 100644
--- a/toggletaskobsolete.php
+++ b/toggletaskobsolete.php
@@ -21,6 +21,7 @@
* @copyright 2011 Lancaster University Network Services Limited
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+
require_once(dirname(__FILE__) . '/../../config.php');
require_once(dirname(__FILE__) . '/locallib.php');
@@ -38,4 +39,4 @@
$task = block_workflow_todo::toggle_task($taskid);
// Redirect.
-redirect(new moodle_url('/blocks/workflow/editstep.php', array('stepid' => $task->stepid)));
+redirect(new moodle_url('/blocks/workflow/editstep.php', ['stepid' => $task->stepid]));
diff --git a/toggleworkflowobsolete.php b/toggleworkflowobsolete.php
index f80d116..81ed041 100644
--- a/toggleworkflowobsolete.php
+++ b/toggleworkflowobsolete.php
@@ -42,7 +42,7 @@
// Redirect as appropriate.
if ($returnto == 'editsteps') {
- redirect(new moodle_url('/blocks/workflow/editsteps.php', array('workflowid' => $workflowid)));
+ redirect(new moodle_url('/blocks/workflow/editsteps.php', ['workflowid' => $workflowid]));
} else {
redirect(new moodle_url('/blocks/workflow/manage.php'));
}
diff --git a/version.php b/version.php
index 1e314f1..63b0601 100644
--- a/version.php
+++ b/version.php
@@ -24,10 +24,10 @@
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2022040800;
+$plugin->version = 2025073000;
$plugin->requires = 2021051700;
$plugin->component = 'block_workflow';
$plugin->maturity = MATURITY_STABLE;
-$plugin->release = 'v2.3 for Moodle 3.11+';
+$plugin->release = 'v2.4 for Moodle 5.0+';
$plugin->outestssufficient = true;
diff --git a/yui/build/moodle-block_workflow-comments/moodle-block_workflow-comments-debug.js b/yui/build/moodle-block_workflow-comments/moodle-block_workflow-comments-debug.js
deleted file mode 100644
index 045a254..0000000
--- a/yui/build/moodle-block_workflow-comments/moodle-block_workflow-comments-debug.js
+++ /dev/null
@@ -1,296 +0,0 @@
-YUI.add('moodle-block_workflow-comments', function (Y, NAME) {
-
-var COMMENTSNAME = 'blocks_workflow_comments',
- AJAXURL = '/blocks/workflow/ajax.php',
- STATEID = 'stateid',
- EDITORID = 'editorid',
- EDITORNAME = 'editorname',
- CSS = {
- BLOCKWORKFLOW: 'block_workflow',
- BLOCKCOMMENTS: 'block_workflow_comments',
- BLOCKCOMMBTN: 'block_workflow_editcommentbutton',
- BLOCKFINISHBTN: 'block_workflow_finishstepbutton',
- PANEL: 'block-workflow-panel',
- CONTENT: 'content',
- COMMENTS: 'wkf-comments',
- LIGHTBOX: 'loading-lightbox',
- LOADINGICON: 'loading-icon',
- TEXTAREA: 'wfk-textarea',
- SUBMIT: 'wfk-submit',
- HIDDEN: 'hidden'
- };
-
-var overlay = new M.core.dialogue({
- headerContent: '',
- bodyContent: Y.one('.' + CSS.PANEL),
- visible: false,
- modal: true,
- width: 'auto',
- zIndex: 100
-});
-
-var COMMENTS = function() {
- COMMENTS.superclass.constructor.apply(this, arguments);
-};
-
-Y.extend(COMMENTS, Y.Base, {
- _formSubmitEvent: null,
- _escCloseEvent: null,
- _closeButtonEvent: null,
- _loadingNode: null,
-
- initializer: function() {
- overlay.hide();
- var panel = Y.one('.' + CSS.PANEL);
- if (!panel) {
- return;
- }
- this._loadingNode = panel.one('.' + CSS.LIGHTBOX);
- this.attachEvents();
- },
-
- show: function (e, finishstep) {
- e.halt();
-
- // Different scenario depending on whether we finishing the step or just editiong the comment
- if (finishstep) {
- overlay.set('headerContent', M.str.block_workflow.finishstep);
- Y.one('.' + CSS.PANEL).one('.' + CSS.SUBMIT + ' input').set('value', M.str.block_workflow.finishstep);
- this._formSubmitEvent = Y.one('.' + CSS.SUBMIT + ' input').on('click', this.finishstep, this);
- } else {
- overlay.set('headerContent', M.str.block_workflow.editcomments);
- Y.one('.' + CSS.PANEL).one('.' + CSS.SUBMIT + ' input').set('value', M.str.moodle.savechanges);
- this._formSubmitEvent = Y.one('.' + CSS.SUBMIT + ' input').on('click', this.save, this);
- }
-
- overlay.show(); //show the overlay
- // We add a new event on the body in order to hide the overlay for the next click
- this._escCloseEvent = Y.on('key', this.hide, document.body, 'down:27', this);
-
- // Remove the existing handler for the closebutton
- Y.Event.purgeElement(Y.one('.moodle-dialogue-hd .closebutton'), true);
- // Add a new event for close button.
- this._closeButtonEvent = Y.on('click', this.hide, Y.one('.moodle-dialogue-hd .closebutton'), this);
-
- // Build the data for submission
- var data = {
- sesskey: M.cfg.sesskey,
- action: 'getcomment',
- stateid: this.get(STATEID)
- };
-
- if (typeof tinyMCE !== 'undefined') {
- var ed = tinyMCE.get(this.get(EDITORID));
-
- // Resize then editor when first shown if it would otherwise be too small.
- var ifr = tinymce.DOM.get(this.get(EDITORID) + '_ifr');
- var size = tinymce.DOM.getSize(ifr);
- if (size.h === 30) {
- ed.theme.resizeTo(size.w, 90);
- }
- }
-
- // Fetch the comment and update the form
- Y.io(M.cfg.wwwroot + AJAXURL, {
- method:'POST',
- data:build_querystring(data),
- on: {
- start: this.displayLoading,
- complete: function(tid, outcome) {
- var result;
- try {
- result = Y.JSON.parse(outcome.responseText);
- if (result.error) {
- return new M.core.ajaxException(result);
- }
- } catch (e) {
- new M.core.exception(e);
- }
- if (typeof tinyMCE !== 'undefined') {
- ed.setContent(result.response.comment);
- } else {
- var editorid = this.get(EDITORID);
- var editor = Y.one(document.getElementById(editorid + 'editable'));
- if (editor) {
- editor.setHTML(result.response.comment);
- }
- Y.one(document.getElementById(editorid)).set(
- 'value', result.response.comment);
- }
- },
- end: this.removeLoading
- },
- context:this
- });
- },
-
- hide: function () {
- overlay.hide(); //hide the overlay
- if (this._escCloseEvent) {
- this._escCloseEvent.detach();
- this._escCloseEvent = null;
- }
- if (this._closeButtonEvent) {
- this._closeButtonEvent.detach();
- this._closeButtonEvent = null;
- }
- if (this._formSubmitEvent) {
- this._formSubmitEvent.detach();
- this._formSubmitEvent = null;
- }
- },
- save: function () {
- var comment;
- if (typeof tinyMCE !== 'undefined') {
- comment = tinyMCE.get(this.get(EDITORID)).getContent();
- } else {
- comment = Y.one(document.getElementById(this.get(EDITORID))).get('value');
- }
-
- var commentsblock = Y.one('.' + CSS.BLOCKWORKFLOW + ' .' + CSS.BLOCKCOMMENTS);
- // Build the data for submission
- var data = {
- sesskey: M.cfg.sesskey,
- action: 'savecomment',
- stateid: this.get(STATEID),
- text: comment,
- format: document.getElementsByName(this.get(EDITORNAME) + '[format]')[0].value
- };
-
- Y.io(M.cfg.wwwroot + AJAXURL, {
- method:'POST',
- data:build_querystring(data),
- on: {
- start: this.displayLoading,
- complete: function(tid, outcome) {
- var result;
- try {
- result = Y.JSON.parse(outcome.responseText);
- if (result.error) {
- return new M.core.ajaxException(result);
- }
- } catch (e) {
- new M.core.exception(e);
- }
- if (result.response.blockcomments) {
- commentsblock.setContent(result.response.blockcomments);
- } else {
- commentsblock.setContent(M.str.block_workflow.nocomments);
- }
- },
- end: this.removeLoading
- },
- context:this
- });
- this.hide();
- },
- finishstep: function () {
- var comment;
- if (typeof tinyMCE !== 'undefined') {
- comment = tinyMCE.get(this.get(EDITORID)).getContent();
- } else {
- comment = Y.one(document.getElementById(this.get(EDITORID))).get('value');
- }
-
- var workflowblock = Y.one('.' + CSS.BLOCKWORKFLOW + ' .' + CSS.CONTENT);
- // Build the data for submission
- var data = {
- sesskey: M.cfg.sesskey,
- action: 'finishstep',
- stateid: this.get(STATEID),
- text: comment,
- format: document.getElementsByName(this.get(EDITORNAME) + '[format]')[0].value
- };
-
- Y.io(M.cfg.wwwroot + AJAXURL, {
- method:'POST',
- data:build_querystring(data),
- on: {
- start: this.displayLoading,
- complete: function(tid, outcome) {
- var result;
- try {
- result = Y.JSON.parse(outcome.responseText);
- if (result.error) {
- return new M.core.ajaxException(result);
- }
- } catch (e) {
- new M.core.exception(e);
- }
- if (result.response.blockcontent) {
- // Update content
- workflowblock.setContent(result.response.blockcontent);
- if (result.response.stateid) {
- // we are on the next step
- this.set(STATEID, result.response.stateid);
- // re-attach events to block buttons
- this.attachEvents();
- // reinit todo events
- M.blocks_workflow.init_todolist({"stateid":result.response.stateid});
- }
- if (result.response.listworkflows) {
- // Last step, available workflows are listed
- var select_id = workflowblock.one('.singleselect form select').getAttribute('id');
- // Reinit single_select event
- // This is horrible, but the core JS we need is now inline in the template,
- // so we have to copy it.
- require(['jquery'], function($) {
- $('#' + select_id).change(function() {
- var ignore = $(this).find(':selected').attr('data-ignore');
- if (typeof ignore === typeof undefined) {
- $('#' + select_id).closest('form').submit();
- }
- });
- });
- }
- }
- },
- end: this.removeLoading
- },
- context:this
- });
- this.hide();
- },
- displayLoading: function() {
- this._loadingNode.removeClass(CSS.HIDDEN);
- },
- removeLoading: function() {
- this._loadingNode.addClass(CSS.HIDDEN);
- },
- attachEvents: function() {
- var commentbutton = Y.one('.' + CSS.BLOCKCOMMBTN + ' button, .' +
- CSS.BLOCKCOMMBTN + ' input[type=submit]');
- if (commentbutton) {
- commentbutton.on('click', this.show, this, false);
- }
- var finishbutton = Y.one('.' + CSS.BLOCKFINISHBTN + ' button, .' +
- CSS.BLOCKFINISHBTN + ' input[type=submit]');
- if (finishbutton) {
- finishbutton.on('click', this.show, this, true);
- }
- }
-
-}, {
- NAME: COMMENTSNAME,
- ATTRS: {
- stateid: {
- value: null
- },
- editorid: {
- value: null
- },
- editorname: {
- validator: Y.Lang.isString,
- value: null
- }
-
- }
-});
-
-M.blocks_workflow = M.blocks_workflow || {};
-M.blocks_workflow.init_comments = function(params) {
- return new COMMENTS(params);
-};
-
-
-}, '@VERSION@', {"requires": ["base", "overlay", "moodle-core-formautosubmit", "moodle-core-notification"]});
diff --git a/yui/build/moodle-block_workflow-comments/moodle-block_workflow-comments-min.js b/yui/build/moodle-block_workflow-comments/moodle-block_workflow-comments-min.js
deleted file mode 100644
index 50b17d4..0000000
--- a/yui/build/moodle-block_workflow-comments/moodle-block_workflow-comments-min.js
+++ /dev/null
@@ -1 +0,0 @@
-YUI.add("moodle-block_workflow-comments",function(c,e){var o="/blocks/workflow/ajax.php",l="stateid",r="editorid",t="editorname",n="block_workflow",i="block_workflow_comments",u="block_workflow_editcommentbutton",m="block_workflow_finishstepbutton",a="block-workflow-panel",f="content",g="loading-lightbox",d="wfk-submit",w="hidden",h=new M.core.dialogue({headerContent:"",bodyContent:c.one("."+a),visible:!1,modal:!0,width:"auto",zIndex:100}),s=function(){s.superclass.constructor.apply(this,arguments)};c.extend(s,c.Base,{_formSubmitEvent:null,_escCloseEvent:null,_closeButtonEvent:null,_loadingNode:null,initializer:function(){h.hide();var e=c.one("."+a);e&&(this._loadingNode=e.one("."+g),this.attachEvents())},show:function(s,e){var i,t;s.halt(),e?(h.set("headerContent",M.str.block_workflow.finishstep),c.one("."+a).one("."+d+" input").set("value",M.str.block_workflow.finishstep),this._formSubmitEvent=c.one("."+d+" input").on("click",this.finishstep,this)):(h.set("headerContent",M.str.block_workflow.editcomments),c.one("."+a).one("."+d+" input").set("value",M.str.moodle.savechanges),this._formSubmitEvent=c.one("."+d+" input").on("click",this.save,this)),h.show(),this._escCloseEvent=c.on("key",this.hide,document.body,"down:27",this),c.Event.purgeElement(c.one(".moodle-dialogue-hd .closebutton"),!0),this._closeButtonEvent=c.on("click",this.hide,c.one(".moodle-dialogue-hd .closebutton"),this),e={sesskey:M.cfg.sesskey,action:"getcomment",stateid:this.get(l)},"undefined"!=typeof tinyMCE&&(i=tinyMCE.get(this.get(r)),t=tinymce.DOM.get(this.get(r)+"_ifr"),30===(t=tinymce.DOM.getSize(t)).h&&i.theme.resizeTo(t.w,90)),c.io(M.cfg.wwwroot+o,{method:"POST",data:build_querystring(e),on:{start:this.displayLoading,complete:function(e,t){var o,n;try{if((o=c.JSON.parse(t.responseText)).error)return new M.core.ajaxException(o)}catch(s){new M.core.exception(s)}"undefined"!=typeof tinyMCE?i.setContent(o.response.comment):(t=this.get(r),(n=c.one(document.getElementById(t+"editable")))&&n.setHTML(o.response.comment),c.one(document.getElementById(t)).set("value",o.response.comment))},end:this.removeLoading},context:this})},hide:function(){h.hide(),this._escCloseEvent&&(this._escCloseEvent.detach(),this._escCloseEvent=null),this._closeButtonEvent&&(this._closeButtonEvent.detach(),this._closeButtonEvent=null),this._formSubmitEvent&&(this._formSubmitEvent.detach(),this._formSubmitEvent=null)},save:function(){var e="undefined"!=typeof tinyMCE?tinyMCE.get(this.get(r)).getContent():c.one(document.getElementById(this.get(r))).get("value"),s=c.one("."+n+" ."+i),e={sesskey:M.cfg.sesskey,action:"savecomment",stateid:this.get(l),text:e,format:document.getElementsByName(this.get(t)+"[format]")[0].value};c.io(M.cfg.wwwroot+o,{method:"POST",data:build_querystring(e),on:{start:this.displayLoading,complete:function(e,t){var o;try{if((o=c.JSON.parse(t.responseText)).error)return new M.core.ajaxException(o)}catch(n){new M.core.exception(n)}o.response.blockcomments?s.setContent(o.response.blockcomments):s.setContent(M.str.block_workflow.nocomments)},end:this.removeLoading},context:this}),this.hide()},finishstep:function(){var e="undefined"!=typeof tinyMCE?tinyMCE.get(this.get(r)).getContent():c.one(document.getElementById(this.get(r))).get("value"),i=c.one("."+n+" ."+f),e={sesskey:M.cfg.sesskey,action:"finishstep",stateid:this.get(l),text:e,format:document.getElementsByName(this.get(t)+"[format]")[0].value};c.io(M.cfg.wwwroot+o,{method:"POST",data:build_querystring(e),on:{start:this.displayLoading,complete:function(e,t){var o,n;try{if((o=c.JSON.parse(t.responseText)).error)return new M.core.ajaxException(o)}catch(s){new M.core.exception(s)}o.response.blockcontent&&(i.setContent(o.response.blockcontent),o.response.stateid&&(this.set(l,o.response.stateid),this.attachEvents(),M.blocks_workflow.init_todolist({stateid:o.response.stateid})),o.response.listworkflows&&(n=i.one(".singleselect form select").getAttribute("id"),require(["jquery"],function(e){e("#"+n).change(function(){typeof e(this).find(":selected").attr("data-ignore")==typeof undefined&&e("#"+n).closest("form").submit()})})))},end:this.removeLoading},context:this}),this.hide()},displayLoading:function(){this._loadingNode.removeClass(w)},removeLoading:function(){this._loadingNode.addClass(w)},attachEvents:function(){var e=c.one("."+u+" button, ."+u+" input[type=submit]");e&&e.on("click",this.show,this,!1),(e=c.one("."+m+" button, ."+m+" input[type=submit]"))&&e.on("click",this.show,this,!0)}},{NAME:"blocks_workflow_comments",ATTRS:{stateid:{value:null},editorid:{value:null},editorname:{validator:c.Lang.isString,value:null}}}),M.blocks_workflow=M.blocks_workflow||{},M.blocks_workflow.init_comments=function(e){return new s(e)}},"@VERSION@",{requires:["base","overlay","moodle-core-formautosubmit","moodle-core-notification"]});
\ No newline at end of file
diff --git a/yui/build/moodle-block_workflow-comments/moodle-block_workflow-comments.js b/yui/build/moodle-block_workflow-comments/moodle-block_workflow-comments.js
deleted file mode 100644
index 045a254..0000000
--- a/yui/build/moodle-block_workflow-comments/moodle-block_workflow-comments.js
+++ /dev/null
@@ -1,296 +0,0 @@
-YUI.add('moodle-block_workflow-comments', function (Y, NAME) {
-
-var COMMENTSNAME = 'blocks_workflow_comments',
- AJAXURL = '/blocks/workflow/ajax.php',
- STATEID = 'stateid',
- EDITORID = 'editorid',
- EDITORNAME = 'editorname',
- CSS = {
- BLOCKWORKFLOW: 'block_workflow',
- BLOCKCOMMENTS: 'block_workflow_comments',
- BLOCKCOMMBTN: 'block_workflow_editcommentbutton',
- BLOCKFINISHBTN: 'block_workflow_finishstepbutton',
- PANEL: 'block-workflow-panel',
- CONTENT: 'content',
- COMMENTS: 'wkf-comments',
- LIGHTBOX: 'loading-lightbox',
- LOADINGICON: 'loading-icon',
- TEXTAREA: 'wfk-textarea',
- SUBMIT: 'wfk-submit',
- HIDDEN: 'hidden'
- };
-
-var overlay = new M.core.dialogue({
- headerContent: '',
- bodyContent: Y.one('.' + CSS.PANEL),
- visible: false,
- modal: true,
- width: 'auto',
- zIndex: 100
-});
-
-var COMMENTS = function() {
- COMMENTS.superclass.constructor.apply(this, arguments);
-};
-
-Y.extend(COMMENTS, Y.Base, {
- _formSubmitEvent: null,
- _escCloseEvent: null,
- _closeButtonEvent: null,
- _loadingNode: null,
-
- initializer: function() {
- overlay.hide();
- var panel = Y.one('.' + CSS.PANEL);
- if (!panel) {
- return;
- }
- this._loadingNode = panel.one('.' + CSS.LIGHTBOX);
- this.attachEvents();
- },
-
- show: function (e, finishstep) {
- e.halt();
-
- // Different scenario depending on whether we finishing the step or just editiong the comment
- if (finishstep) {
- overlay.set('headerContent', M.str.block_workflow.finishstep);
- Y.one('.' + CSS.PANEL).one('.' + CSS.SUBMIT + ' input').set('value', M.str.block_workflow.finishstep);
- this._formSubmitEvent = Y.one('.' + CSS.SUBMIT + ' input').on('click', this.finishstep, this);
- } else {
- overlay.set('headerContent', M.str.block_workflow.editcomments);
- Y.one('.' + CSS.PANEL).one('.' + CSS.SUBMIT + ' input').set('value', M.str.moodle.savechanges);
- this._formSubmitEvent = Y.one('.' + CSS.SUBMIT + ' input').on('click', this.save, this);
- }
-
- overlay.show(); //show the overlay
- // We add a new event on the body in order to hide the overlay for the next click
- this._escCloseEvent = Y.on('key', this.hide, document.body, 'down:27', this);
-
- // Remove the existing handler for the closebutton
- Y.Event.purgeElement(Y.one('.moodle-dialogue-hd .closebutton'), true);
- // Add a new event for close button.
- this._closeButtonEvent = Y.on('click', this.hide, Y.one('.moodle-dialogue-hd .closebutton'), this);
-
- // Build the data for submission
- var data = {
- sesskey: M.cfg.sesskey,
- action: 'getcomment',
- stateid: this.get(STATEID)
- };
-
- if (typeof tinyMCE !== 'undefined') {
- var ed = tinyMCE.get(this.get(EDITORID));
-
- // Resize then editor when first shown if it would otherwise be too small.
- var ifr = tinymce.DOM.get(this.get(EDITORID) + '_ifr');
- var size = tinymce.DOM.getSize(ifr);
- if (size.h === 30) {
- ed.theme.resizeTo(size.w, 90);
- }
- }
-
- // Fetch the comment and update the form
- Y.io(M.cfg.wwwroot + AJAXURL, {
- method:'POST',
- data:build_querystring(data),
- on: {
- start: this.displayLoading,
- complete: function(tid, outcome) {
- var result;
- try {
- result = Y.JSON.parse(outcome.responseText);
- if (result.error) {
- return new M.core.ajaxException(result);
- }
- } catch (e) {
- new M.core.exception(e);
- }
- if (typeof tinyMCE !== 'undefined') {
- ed.setContent(result.response.comment);
- } else {
- var editorid = this.get(EDITORID);
- var editor = Y.one(document.getElementById(editorid + 'editable'));
- if (editor) {
- editor.setHTML(result.response.comment);
- }
- Y.one(document.getElementById(editorid)).set(
- 'value', result.response.comment);
- }
- },
- end: this.removeLoading
- },
- context:this
- });
- },
-
- hide: function () {
- overlay.hide(); //hide the overlay
- if (this._escCloseEvent) {
- this._escCloseEvent.detach();
- this._escCloseEvent = null;
- }
- if (this._closeButtonEvent) {
- this._closeButtonEvent.detach();
- this._closeButtonEvent = null;
- }
- if (this._formSubmitEvent) {
- this._formSubmitEvent.detach();
- this._formSubmitEvent = null;
- }
- },
- save: function () {
- var comment;
- if (typeof tinyMCE !== 'undefined') {
- comment = tinyMCE.get(this.get(EDITORID)).getContent();
- } else {
- comment = Y.one(document.getElementById(this.get(EDITORID))).get('value');
- }
-
- var commentsblock = Y.one('.' + CSS.BLOCKWORKFLOW + ' .' + CSS.BLOCKCOMMENTS);
- // Build the data for submission
- var data = {
- sesskey: M.cfg.sesskey,
- action: 'savecomment',
- stateid: this.get(STATEID),
- text: comment,
- format: document.getElementsByName(this.get(EDITORNAME) + '[format]')[0].value
- };
-
- Y.io(M.cfg.wwwroot + AJAXURL, {
- method:'POST',
- data:build_querystring(data),
- on: {
- start: this.displayLoading,
- complete: function(tid, outcome) {
- var result;
- try {
- result = Y.JSON.parse(outcome.responseText);
- if (result.error) {
- return new M.core.ajaxException(result);
- }
- } catch (e) {
- new M.core.exception(e);
- }
- if (result.response.blockcomments) {
- commentsblock.setContent(result.response.blockcomments);
- } else {
- commentsblock.setContent(M.str.block_workflow.nocomments);
- }
- },
- end: this.removeLoading
- },
- context:this
- });
- this.hide();
- },
- finishstep: function () {
- var comment;
- if (typeof tinyMCE !== 'undefined') {
- comment = tinyMCE.get(this.get(EDITORID)).getContent();
- } else {
- comment = Y.one(document.getElementById(this.get(EDITORID))).get('value');
- }
-
- var workflowblock = Y.one('.' + CSS.BLOCKWORKFLOW + ' .' + CSS.CONTENT);
- // Build the data for submission
- var data = {
- sesskey: M.cfg.sesskey,
- action: 'finishstep',
- stateid: this.get(STATEID),
- text: comment,
- format: document.getElementsByName(this.get(EDITORNAME) + '[format]')[0].value
- };
-
- Y.io(M.cfg.wwwroot + AJAXURL, {
- method:'POST',
- data:build_querystring(data),
- on: {
- start: this.displayLoading,
- complete: function(tid, outcome) {
- var result;
- try {
- result = Y.JSON.parse(outcome.responseText);
- if (result.error) {
- return new M.core.ajaxException(result);
- }
- } catch (e) {
- new M.core.exception(e);
- }
- if (result.response.blockcontent) {
- // Update content
- workflowblock.setContent(result.response.blockcontent);
- if (result.response.stateid) {
- // we are on the next step
- this.set(STATEID, result.response.stateid);
- // re-attach events to block buttons
- this.attachEvents();
- // reinit todo events
- M.blocks_workflow.init_todolist({"stateid":result.response.stateid});
- }
- if (result.response.listworkflows) {
- // Last step, available workflows are listed
- var select_id = workflowblock.one('.singleselect form select').getAttribute('id');
- // Reinit single_select event
- // This is horrible, but the core JS we need is now inline in the template,
- // so we have to copy it.
- require(['jquery'], function($) {
- $('#' + select_id).change(function() {
- var ignore = $(this).find(':selected').attr('data-ignore');
- if (typeof ignore === typeof undefined) {
- $('#' + select_id).closest('form').submit();
- }
- });
- });
- }
- }
- },
- end: this.removeLoading
- },
- context:this
- });
- this.hide();
- },
- displayLoading: function() {
- this._loadingNode.removeClass(CSS.HIDDEN);
- },
- removeLoading: function() {
- this._loadingNode.addClass(CSS.HIDDEN);
- },
- attachEvents: function() {
- var commentbutton = Y.one('.' + CSS.BLOCKCOMMBTN + ' button, .' +
- CSS.BLOCKCOMMBTN + ' input[type=submit]');
- if (commentbutton) {
- commentbutton.on('click', this.show, this, false);
- }
- var finishbutton = Y.one('.' + CSS.BLOCKFINISHBTN + ' button, .' +
- CSS.BLOCKFINISHBTN + ' input[type=submit]');
- if (finishbutton) {
- finishbutton.on('click', this.show, this, true);
- }
- }
-
-}, {
- NAME: COMMENTSNAME,
- ATTRS: {
- stateid: {
- value: null
- },
- editorid: {
- value: null
- },
- editorname: {
- validator: Y.Lang.isString,
- value: null
- }
-
- }
-});
-
-M.blocks_workflow = M.blocks_workflow || {};
-M.blocks_workflow.init_comments = function(params) {
- return new COMMENTS(params);
-};
-
-
-}, '@VERSION@', {"requires": ["base", "overlay", "moodle-core-formautosubmit", "moodle-core-notification"]});
diff --git a/yui/build/moodle-block_workflow-todolist/moodle-block_workflow-todolist-debug.js b/yui/build/moodle-block_workflow-todolist/moodle-block_workflow-todolist-debug.js
deleted file mode 100644
index b383e8c..0000000
--- a/yui/build/moodle-block_workflow-todolist/moodle-block_workflow-todolist-debug.js
+++ /dev/null
@@ -1,81 +0,0 @@
-YUI.add('moodle-block_workflow-todolist', function (Y, NAME) {
-
-var TODOLISTNAME = 'blocks_workflow_todolist',
- AJAXURL = '/blocks/workflow/ajax.php',
- STATEID = 'stateid',
- CSS = {
- BLOCKWORKFLOW : 'block_workflow',
- BLOCKTODOLIST : 'block_workflow_todolist',
- BLOCKTODOTASK : 'block-workflow-todotask',
- BLOCKTODOID : 'block-workflow-todoid'
- };
-
-var TODOLIST = function() {
- TODOLIST.superclass.constructor.apply(this, arguments);
-};
-
-Y.extend(TODOLIST, Y.Base, {
-
- initializer : function() {
- // Take each of the workflow tasks, remove the anchor, and change it to
- // call our update function
- Y.all('a.' + CSS.BLOCKTODOTASK).each(function(node) {
- node.ancestor('li').on('click', this.toggle, this, node);
- node.setAttribute('href', '#');
- }, this);
- },
-
- toggle : function(e, node) {
- e.halt();
-
- // expression to fetch ID
- var reg = new RegExp(CSS.BLOCKTODOID + "-(\\d{1,})");
- // Build the data for submission
- var data = {
- sesskey : M.cfg.sesskey,
- action : 'toggletaskdone',
- stateid : this.get(STATEID),
- todoid : node.getAttribute('id').match(reg)[1]
- };
-
- // Send the query
- Y.io(M.cfg.wwwroot + AJAXURL, {
- method : 'POST',
- data : build_querystring(data),
- on : {
- complete : function(tid, outcome) {
- var result;
- try {
- result = Y.JSON.parse(outcome.responseText);
- if (result.error) {
- return new M.core.ajaxException(result);
- }
- } catch (e) {
- new M.core.exception(e);
- }
- if (result.response.iscompleted) {
- node.get('parentNode').addClass('completed');
- } else {
- node.get('parentNode').removeClass('completed');
- }
- }
- }
- });
- }
-
-}, {
- NAME : TODOLISTNAME,
- ATTRS : {
- stateid: {
- value: null
- }
- }
-});
-
-M.blocks_workflow = M.blocks_workflow || {};
-M.blocks_workflow.init_todolist = function(params) {
- return new TODOLIST(params);
-};
-
-
-}, '@VERSION@', {"requires": ["base", "node", "event"]});
diff --git a/yui/build/moodle-block_workflow-todolist/moodle-block_workflow-todolist-min.js b/yui/build/moodle-block_workflow-todolist/moodle-block_workflow-todolist-min.js
deleted file mode 100644
index 4f5a8e4..0000000
--- a/yui/build/moodle-block_workflow-todolist/moodle-block_workflow-todolist-min.js
+++ /dev/null
@@ -1 +0,0 @@
-YUI.add("moodle-block_workflow-todolist",function(i,o){var t="block-workflow-todotask",e="block-workflow-todoid",s=function(){s.superclass.constructor.apply(this,arguments)};i.extend(s,i.Base,{initializer:function(){i.all("a."+t).each(function(o){o.ancestor("li").on("click",this.toggle,this,o),o.setAttribute("href","#")},this)},toggle:function(s,l){var o;s.halt(),o=new RegExp(e+"-(\\d{1,})"),o={sesskey:M.cfg.sesskey,action:"toggletaskdone",stateid:this.get("stateid"),todoid:l.getAttribute("id").match(o)[1]},i.io(M.cfg.wwwroot+"/blocks/workflow/ajax.php",{method:"POST",data:build_querystring(o),on:{complete:function(o,t){var e;try{if((e=i.JSON.parse(t.responseText)).error)return new M.core.ajaxException(e)}catch(s){new M.core.exception(s)}e.response.iscompleted?l.get("parentNode").addClass("completed"):l.get("parentNode").removeClass("completed")}}})}},{NAME:"blocks_workflow_todolist",ATTRS:{stateid:{value:null}}}),M.blocks_workflow=M.blocks_workflow||{},M.blocks_workflow.init_todolist=function(o){return new s(o)}},"@VERSION@",{requires:["base","node","event"]});
\ No newline at end of file
diff --git a/yui/build/moodle-block_workflow-todolist/moodle-block_workflow-todolist.js b/yui/build/moodle-block_workflow-todolist/moodle-block_workflow-todolist.js
deleted file mode 100644
index b383e8c..0000000
--- a/yui/build/moodle-block_workflow-todolist/moodle-block_workflow-todolist.js
+++ /dev/null
@@ -1,81 +0,0 @@
-YUI.add('moodle-block_workflow-todolist', function (Y, NAME) {
-
-var TODOLISTNAME = 'blocks_workflow_todolist',
- AJAXURL = '/blocks/workflow/ajax.php',
- STATEID = 'stateid',
- CSS = {
- BLOCKWORKFLOW : 'block_workflow',
- BLOCKTODOLIST : 'block_workflow_todolist',
- BLOCKTODOTASK : 'block-workflow-todotask',
- BLOCKTODOID : 'block-workflow-todoid'
- };
-
-var TODOLIST = function() {
- TODOLIST.superclass.constructor.apply(this, arguments);
-};
-
-Y.extend(TODOLIST, Y.Base, {
-
- initializer : function() {
- // Take each of the workflow tasks, remove the anchor, and change it to
- // call our update function
- Y.all('a.' + CSS.BLOCKTODOTASK).each(function(node) {
- node.ancestor('li').on('click', this.toggle, this, node);
- node.setAttribute('href', '#');
- }, this);
- },
-
- toggle : function(e, node) {
- e.halt();
-
- // expression to fetch ID
- var reg = new RegExp(CSS.BLOCKTODOID + "-(\\d{1,})");
- // Build the data for submission
- var data = {
- sesskey : M.cfg.sesskey,
- action : 'toggletaskdone',
- stateid : this.get(STATEID),
- todoid : node.getAttribute('id').match(reg)[1]
- };
-
- // Send the query
- Y.io(M.cfg.wwwroot + AJAXURL, {
- method : 'POST',
- data : build_querystring(data),
- on : {
- complete : function(tid, outcome) {
- var result;
- try {
- result = Y.JSON.parse(outcome.responseText);
- if (result.error) {
- return new M.core.ajaxException(result);
- }
- } catch (e) {
- new M.core.exception(e);
- }
- if (result.response.iscompleted) {
- node.get('parentNode').addClass('completed');
- } else {
- node.get('parentNode').removeClass('completed');
- }
- }
- }
- });
- }
-
-}, {
- NAME : TODOLISTNAME,
- ATTRS : {
- stateid: {
- value: null
- }
- }
-});
-
-M.blocks_workflow = M.blocks_workflow || {};
-M.blocks_workflow.init_todolist = function(params) {
- return new TODOLIST(params);
-};
-
-
-}, '@VERSION@', {"requires": ["base", "node", "event"]});
diff --git a/yui/build/moodle-block_workflow-userinfo/moodle-block_workflow-userinfo-debug.js b/yui/build/moodle-block_workflow-userinfo/moodle-block_workflow-userinfo-debug.js
deleted file mode 100644
index f13e8f3..0000000
--- a/yui/build/moodle-block_workflow-userinfo/moodle-block_workflow-userinfo-debug.js
+++ /dev/null
@@ -1,83 +0,0 @@
-YUI.add('moodle-block_workflow-userinfo', function (Y, NAME) {
-
-// 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
.
-
-
-/**
- * User info functionality for a popup in workflow block.
- *
- * @package block_workflow
- * @copyright 2014 The Open University
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-var CSS = {
- USERINFO: '#userinfo',
- USERINFOCLASS: '.userinfoclass'
-};
-
-var PARAMS = {
- id: 'id',
- HEADER: 'header',
- BODY: 'body',
- STEPNO: 'stepno'
-};
-
-var POPUP = function() {
- POPUP.superclass.constructor.apply(this, arguments);
-};
-
-Y.extend(POPUP, Y.Base, {
-
- initializer : function() {
- Y.all(CSS.USERINFOCLASS).each(function(node) {
- var stepno = node.getAttribute(PARAMS.STEPNO);
- var header = node.getAttribute(PARAMS.HEADER);
- var body = node.getAttribute(PARAMS.BODY);
- node.on('click', this.display_dialog, this, stepno, header, body);
- }, this);
- },
-
- display_dialog : function (e, stepno, header, body) {
- e.preventDefault();
-
- // Configure the popup.
- var config = {
- headerContent : header,
- bodyContent : body,
- draggable : true,
- modal : true,
- zIndex : 1000,
- centered: false,
- width: 'auto',
- visible: false,
- postmethod: 'form',
- footerContent: null
- };
-
- var popup = { dialog: null };
- popup.dialog = new M.core.dialogue(config);
- popup.dialog.show();
- }
-});
-
-M.block_workflow = M.block_workflow || {};
-M.block_workflow.userinfo = M.block_workflow.userinfo || {};
-M.block_workflow.userinfo.init = function() {
- return new POPUP();
-};
-
-}, '@VERSION@', {"requires": ["base", "event", "node", "io"]});
diff --git a/yui/build/moodle-block_workflow-userinfo/moodle-block_workflow-userinfo-min.js b/yui/build/moodle-block_workflow-userinfo/moodle-block_workflow-userinfo-min.js
deleted file mode 100644
index 79f4ed0..0000000
--- a/yui/build/moodle-block_workflow-userinfo/moodle-block_workflow-userinfo-min.js
+++ /dev/null
@@ -1 +0,0 @@
-YUI.add("moodle-block_workflow-userinfo",function(o,e){var t=".userinfoclass",i="header",l="body",r="stepno",n=function(){n.superclass.constructor.apply(this,arguments)};o.extend(n,o.Base,{initializer:function(){o.all(t).each(function(o){var e=o.getAttribute(r),t=o.getAttribute(i),n=o.getAttribute(l);o.on("click",this.display_dialog,this,e,t,n)},this)},display_dialog:function(o,e,t,n){o.preventDefault(),(o={dialog:null}).dialog=new M.core.dialogue({headerContent:t,bodyContent:n,draggable:!0,modal:!0,zIndex:1e3,centered:!1,width:"auto",visible:!1,postmethod:"form",footerContent:null}),o.dialog.show()}}),M.block_workflow=M.block_workflow||{},M.block_workflow.userinfo=M.block_workflow.userinfo||{},M.block_workflow.userinfo.init=function(){return new n}},"@VERSION@",{requires:["base","event","node","io"]});
\ No newline at end of file
diff --git a/yui/build/moodle-block_workflow-userinfo/moodle-block_workflow-userinfo.js b/yui/build/moodle-block_workflow-userinfo/moodle-block_workflow-userinfo.js
deleted file mode 100644
index f13e8f3..0000000
--- a/yui/build/moodle-block_workflow-userinfo/moodle-block_workflow-userinfo.js
+++ /dev/null
@@ -1,83 +0,0 @@
-YUI.add('moodle-block_workflow-userinfo', function (Y, NAME) {
-
-// 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
.
-
-
-/**
- * User info functionality for a popup in workflow block.
- *
- * @package block_workflow
- * @copyright 2014 The Open University
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-var CSS = {
- USERINFO: '#userinfo',
- USERINFOCLASS: '.userinfoclass'
-};
-
-var PARAMS = {
- id: 'id',
- HEADER: 'header',
- BODY: 'body',
- STEPNO: 'stepno'
-};
-
-var POPUP = function() {
- POPUP.superclass.constructor.apply(this, arguments);
-};
-
-Y.extend(POPUP, Y.Base, {
-
- initializer : function() {
- Y.all(CSS.USERINFOCLASS).each(function(node) {
- var stepno = node.getAttribute(PARAMS.STEPNO);
- var header = node.getAttribute(PARAMS.HEADER);
- var body = node.getAttribute(PARAMS.BODY);
- node.on('click', this.display_dialog, this, stepno, header, body);
- }, this);
- },
-
- display_dialog : function (e, stepno, header, body) {
- e.preventDefault();
-
- // Configure the popup.
- var config = {
- headerContent : header,
- bodyContent : body,
- draggable : true,
- modal : true,
- zIndex : 1000,
- centered: false,
- width: 'auto',
- visible: false,
- postmethod: 'form',
- footerContent: null
- };
-
- var popup = { dialog: null };
- popup.dialog = new M.core.dialogue(config);
- popup.dialog.show();
- }
-});
-
-M.block_workflow = M.block_workflow || {};
-M.block_workflow.userinfo = M.block_workflow.userinfo || {};
-M.block_workflow.userinfo.init = function() {
- return new POPUP();
-};
-
-}, '@VERSION@', {"requires": ["base", "event", "node", "io"]});
diff --git a/yui/src/comments/build.json b/yui/src/comments/build.json
deleted file mode 100644
index 6ca73c2..0000000
--- a/yui/src/comments/build.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "name": "moodle-block_workflow-comments",
- "builds": {
- "moodle-block_workflow-comments": {
- "jsfiles": [
- "comments.js"
- ]
- }
- }
-}
diff --git a/yui/src/comments/js/comments.js b/yui/src/comments/js/comments.js
deleted file mode 100644
index a8f0d8e..0000000
--- a/yui/src/comments/js/comments.js
+++ /dev/null
@@ -1,291 +0,0 @@
-var COMMENTSNAME = 'blocks_workflow_comments',
- AJAXURL = '/blocks/workflow/ajax.php',
- STATEID = 'stateid',
- EDITORID = 'editorid',
- EDITORNAME = 'editorname',
- CSS = {
- BLOCKWORKFLOW: 'block_workflow',
- BLOCKCOMMENTS: 'block_workflow_comments',
- BLOCKCOMMBTN: 'block_workflow_editcommentbutton',
- BLOCKFINISHBTN: 'block_workflow_finishstepbutton',
- PANEL: 'block-workflow-panel',
- CONTENT: 'content',
- COMMENTS: 'wkf-comments',
- LIGHTBOX: 'loading-lightbox',
- LOADINGICON: 'loading-icon',
- TEXTAREA: 'wfk-textarea',
- SUBMIT: 'wfk-submit',
- HIDDEN: 'hidden'
- };
-
-var overlay = new M.core.dialogue({
- headerContent: '',
- bodyContent: Y.one('.' + CSS.PANEL),
- visible: false,
- modal: true,
- width: 'auto',
- zIndex: 100
-});
-
-var COMMENTS = function() {
- COMMENTS.superclass.constructor.apply(this, arguments);
-};
-
-Y.extend(COMMENTS, Y.Base, {
- _formSubmitEvent: null,
- _escCloseEvent: null,
- _closeButtonEvent: null,
- _loadingNode: null,
-
- initializer: function() {
- overlay.hide();
- var panel = Y.one('.' + CSS.PANEL);
- if (!panel) {
- return;
- }
- this._loadingNode = panel.one('.' + CSS.LIGHTBOX);
- this.attachEvents();
- },
-
- show: function (e, finishstep) {
- e.halt();
-
- // Different scenario depending on whether we finishing the step or just editiong the comment
- if (finishstep) {
- overlay.set('headerContent', M.str.block_workflow.finishstep);
- Y.one('.' + CSS.PANEL).one('.' + CSS.SUBMIT + ' input').set('value', M.str.block_workflow.finishstep);
- this._formSubmitEvent = Y.one('.' + CSS.SUBMIT + ' input').on('click', this.finishstep, this);
- } else {
- overlay.set('headerContent', M.str.block_workflow.editcomments);
- Y.one('.' + CSS.PANEL).one('.' + CSS.SUBMIT + ' input').set('value', M.str.moodle.savechanges);
- this._formSubmitEvent = Y.one('.' + CSS.SUBMIT + ' input').on('click', this.save, this);
- }
-
- overlay.show(); //show the overlay
- // We add a new event on the body in order to hide the overlay for the next click
- this._escCloseEvent = Y.on('key', this.hide, document.body, 'down:27', this);
-
- // Remove the existing handler for the closebutton
- Y.Event.purgeElement(Y.one('.moodle-dialogue-hd .closebutton'), true);
- // Add a new event for close button.
- this._closeButtonEvent = Y.on('click', this.hide, Y.one('.moodle-dialogue-hd .closebutton'), this);
-
- // Build the data for submission
- var data = {
- sesskey: M.cfg.sesskey,
- action: 'getcomment',
- stateid: this.get(STATEID)
- };
-
- if (typeof tinyMCE !== 'undefined') {
- var ed = tinyMCE.get(this.get(EDITORID));
-
- // Resize then editor when first shown if it would otherwise be too small.
- var ifr = tinymce.DOM.get(this.get(EDITORID) + '_ifr');
- var size = tinymce.DOM.getSize(ifr);
- if (size.h === 30) {
- ed.theme.resizeTo(size.w, 90);
- }
- }
-
- // Fetch the comment and update the form
- Y.io(M.cfg.wwwroot + AJAXURL, {
- method:'POST',
- data:build_querystring(data),
- on: {
- start: this.displayLoading,
- complete: function(tid, outcome) {
- var result;
- try {
- result = Y.JSON.parse(outcome.responseText);
- if (result.error) {
- return new M.core.ajaxException(result);
- }
- } catch (e) {
- new M.core.exception(e);
- }
- if (typeof tinyMCE !== 'undefined') {
- ed.setContent(result.response.comment);
- } else {
- var editorid = this.get(EDITORID);
- var editor = Y.one(document.getElementById(editorid + 'editable'));
- if (editor) {
- editor.setHTML(result.response.comment);
- }
- Y.one(document.getElementById(editorid)).set(
- 'value', result.response.comment);
- }
- },
- end: this.removeLoading
- },
- context:this
- });
- },
-
- hide: function () {
- overlay.hide(); //hide the overlay
- if (this._escCloseEvent) {
- this._escCloseEvent.detach();
- this._escCloseEvent = null;
- }
- if (this._closeButtonEvent) {
- this._closeButtonEvent.detach();
- this._closeButtonEvent = null;
- }
- if (this._formSubmitEvent) {
- this._formSubmitEvent.detach();
- this._formSubmitEvent = null;
- }
- },
- save: function () {
- var comment;
- if (typeof tinyMCE !== 'undefined') {
- comment = tinyMCE.get(this.get(EDITORID)).getContent();
- } else {
- comment = Y.one(document.getElementById(this.get(EDITORID))).get('value');
- }
-
- var commentsblock = Y.one('.' + CSS.BLOCKWORKFLOW + ' .' + CSS.BLOCKCOMMENTS);
- // Build the data for submission
- var data = {
- sesskey: M.cfg.sesskey,
- action: 'savecomment',
- stateid: this.get(STATEID),
- text: comment,
- format: document.getElementsByName(this.get(EDITORNAME) + '[format]')[0].value
- };
-
- Y.io(M.cfg.wwwroot + AJAXURL, {
- method:'POST',
- data:build_querystring(data),
- on: {
- start: this.displayLoading,
- complete: function(tid, outcome) {
- var result;
- try {
- result = Y.JSON.parse(outcome.responseText);
- if (result.error) {
- return new M.core.ajaxException(result);
- }
- } catch (e) {
- new M.core.exception(e);
- }
- if (result.response.blockcomments) {
- commentsblock.setContent(result.response.blockcomments);
- } else {
- commentsblock.setContent(M.str.block_workflow.nocomments);
- }
- },
- end: this.removeLoading
- },
- context:this
- });
- this.hide();
- },
- finishstep: function () {
- var comment;
- if (typeof tinyMCE !== 'undefined') {
- comment = tinyMCE.get(this.get(EDITORID)).getContent();
- } else {
- comment = Y.one(document.getElementById(this.get(EDITORID))).get('value');
- }
-
- var workflowblock = Y.one('.' + CSS.BLOCKWORKFLOW + ' .' + CSS.CONTENT);
- // Build the data for submission
- var data = {
- sesskey: M.cfg.sesskey,
- action: 'finishstep',
- stateid: this.get(STATEID),
- text: comment,
- format: document.getElementsByName(this.get(EDITORNAME) + '[format]')[0].value
- };
-
- Y.io(M.cfg.wwwroot + AJAXURL, {
- method:'POST',
- data:build_querystring(data),
- on: {
- start: this.displayLoading,
- complete: function(tid, outcome) {
- var result;
- try {
- result = Y.JSON.parse(outcome.responseText);
- if (result.error) {
- return new M.core.ajaxException(result);
- }
- } catch (e) {
- new M.core.exception(e);
- }
- if (result.response.blockcontent) {
- // Update content
- workflowblock.setContent(result.response.blockcontent);
- if (result.response.stateid) {
- // we are on the next step
- this.set(STATEID, result.response.stateid);
- // re-attach events to block buttons
- this.attachEvents();
- // reinit todo events
- M.blocks_workflow.init_todolist({"stateid":result.response.stateid});
- }
- if (result.response.listworkflows) {
- // Last step, available workflows are listed
- var select_id = workflowblock.one('.singleselect form select').getAttribute('id');
- // Reinit single_select event
- // This is horrible, but the core JS we need is now inline in the template,
- // so we have to copy it.
- require(['jquery'], function($) {
- $('#' + select_id).change(function() {
- var ignore = $(this).find(':selected').attr('data-ignore');
- if (typeof ignore === typeof undefined) {
- $('#' + select_id).closest('form').submit();
- }
- });
- });
- }
- }
- },
- end: this.removeLoading
- },
- context:this
- });
- this.hide();
- },
- displayLoading: function() {
- this._loadingNode.removeClass(CSS.HIDDEN);
- },
- removeLoading: function() {
- this._loadingNode.addClass(CSS.HIDDEN);
- },
- attachEvents: function() {
- var commentbutton = Y.one('.' + CSS.BLOCKCOMMBTN + ' button, .' +
- CSS.BLOCKCOMMBTN + ' input[type=submit]');
- if (commentbutton) {
- commentbutton.on('click', this.show, this, false);
- }
- var finishbutton = Y.one('.' + CSS.BLOCKFINISHBTN + ' button, .' +
- CSS.BLOCKFINISHBTN + ' input[type=submit]');
- if (finishbutton) {
- finishbutton.on('click', this.show, this, true);
- }
- }
-
-}, {
- NAME: COMMENTSNAME,
- ATTRS: {
- stateid: {
- value: null
- },
- editorid: {
- value: null
- },
- editorname: {
- validator: Y.Lang.isString,
- value: null
- }
-
- }
-});
-
-M.blocks_workflow = M.blocks_workflow || {};
-M.blocks_workflow.init_comments = function(params) {
- return new COMMENTS(params);
-};
diff --git a/yui/src/comments/meta/comments.json b/yui/src/comments/meta/comments.json
deleted file mode 100644
index f2e1ce5..0000000
--- a/yui/src/comments/meta/comments.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "moodle-block_workflow-comments": {
- "requires": [
- "base",
- "overlay",
- "moodle-core-formautosubmit",
- "moodle-core-notification"
- ]
- }
-}
diff --git a/yui/src/todolist/build.json b/yui/src/todolist/build.json
deleted file mode 100644
index e6b8b5a..0000000
--- a/yui/src/todolist/build.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "name": "moodle-block_workflow-todolist",
- "builds": {
- "moodle-block_workflow-todolist": {
- "jsfiles": [
- "todolist.js"
- ]
- }
- }
-}
diff --git a/yui/src/todolist/js/todolist.js b/yui/src/todolist/js/todolist.js
deleted file mode 100644
index 9ed0a82..0000000
--- a/yui/src/todolist/js/todolist.js
+++ /dev/null
@@ -1,76 +0,0 @@
-var TODOLISTNAME = 'blocks_workflow_todolist',
- AJAXURL = '/blocks/workflow/ajax.php',
- STATEID = 'stateid',
- CSS = {
- BLOCKWORKFLOW : 'block_workflow',
- BLOCKTODOLIST : 'block_workflow_todolist',
- BLOCKTODOTASK : 'block-workflow-todotask',
- BLOCKTODOID : 'block-workflow-todoid'
- };
-
-var TODOLIST = function() {
- TODOLIST.superclass.constructor.apply(this, arguments);
-};
-
-Y.extend(TODOLIST, Y.Base, {
-
- initializer : function() {
- // Take each of the workflow tasks, remove the anchor, and change it to
- // call our update function
- Y.all('a.' + CSS.BLOCKTODOTASK).each(function(node) {
- node.ancestor('li').on('click', this.toggle, this, node);
- node.setAttribute('href', '#');
- }, this);
- },
-
- toggle : function(e, node) {
- e.halt();
-
- // expression to fetch ID
- var reg = new RegExp(CSS.BLOCKTODOID + "-(\\d{1,})");
- // Build the data for submission
- var data = {
- sesskey : M.cfg.sesskey,
- action : 'toggletaskdone',
- stateid : this.get(STATEID),
- todoid : node.getAttribute('id').match(reg)[1]
- };
-
- // Send the query
- Y.io(M.cfg.wwwroot + AJAXURL, {
- method : 'POST',
- data : build_querystring(data),
- on : {
- complete : function(tid, outcome) {
- var result;
- try {
- result = Y.JSON.parse(outcome.responseText);
- if (result.error) {
- return new M.core.ajaxException(result);
- }
- } catch (e) {
- new M.core.exception(e);
- }
- if (result.response.iscompleted) {
- node.get('parentNode').addClass('completed');
- } else {
- node.get('parentNode').removeClass('completed');
- }
- }
- }
- });
- }
-
-}, {
- NAME : TODOLISTNAME,
- ATTRS : {
- stateid: {
- value: null
- }
- }
-});
-
-M.blocks_workflow = M.blocks_workflow || {};
-M.blocks_workflow.init_todolist = function(params) {
- return new TODOLIST(params);
-};
diff --git a/yui/src/todolist/meta/todolist.json b/yui/src/todolist/meta/todolist.json
deleted file mode 100644
index 163167a..0000000
--- a/yui/src/todolist/meta/todolist.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "moodle-block_workflow-todolist": {
- "requires": [
- "base",
- "node",
- "event"
- ]
- }
-}
diff --git a/yui/src/userinfo/build.json b/yui/src/userinfo/build.json
deleted file mode 100644
index 0bafaf8..0000000
--- a/yui/src/userinfo/build.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "name": "moodle-block_workflow-userinfo",
- "builds": {
- "moodle-block_workflow-userinfo": {
- "jsfiles": [
- "userinfo.js"
- ]
- }
- }
-}
diff --git a/yui/src/userinfo/js/userinfo.js b/yui/src/userinfo/js/userinfo.js
deleted file mode 100644
index ff82668..0000000
--- a/yui/src/userinfo/js/userinfo.js
+++ /dev/null
@@ -1,79 +0,0 @@
-// 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
.
-
-
-/**
- * User info functionality for a popup in workflow block.
- *
- * @package block_workflow
- * @copyright 2014 The Open University
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-var CSS = {
- USERINFO: '#userinfo',
- USERINFOCLASS: '.userinfoclass'
-};
-
-var PARAMS = {
- id: 'id',
- HEADER: 'header',
- BODY: 'body',
- STEPNO: 'stepno'
-};
-
-var POPUP = function() {
- POPUP.superclass.constructor.apply(this, arguments);
-};
-
-Y.extend(POPUP, Y.Base, {
-
- initializer : function() {
- Y.all(CSS.USERINFOCLASS).each(function(node) {
- var stepno = node.getAttribute(PARAMS.STEPNO);
- var header = node.getAttribute(PARAMS.HEADER);
- var body = node.getAttribute(PARAMS.BODY);
- node.on('click', this.display_dialog, this, stepno, header, body);
- }, this);
- },
-
- display_dialog : function (e, stepno, header, body) {
- e.preventDefault();
-
- // Configure the popup.
- var config = {
- headerContent : header,
- bodyContent : body,
- draggable : true,
- modal : true,
- zIndex : 1000,
- centered: false,
- width: 'auto',
- visible: false,
- postmethod: 'form',
- footerContent: null
- };
-
- var popup = { dialog: null };
- popup.dialog = new M.core.dialogue(config);
- popup.dialog.show();
- }
-});
-
-M.block_workflow = M.block_workflow || {};
-M.block_workflow.userinfo = M.block_workflow.userinfo || {};
-M.block_workflow.userinfo.init = function() {
- return new POPUP();
-};
\ No newline at end of file
diff --git a/yui/src/userinfo/meta/userinfo.json b/yui/src/userinfo/meta/userinfo.json
deleted file mode 100644
index 609c5e7..0000000
--- a/yui/src/userinfo/meta/userinfo.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "moodle-block_workflow-userinfo": {
- "requires": [
- "base",
- "event",
- "node",
- "io"
- ]
- }
-}