diff --git a/amd/build/tablebulkactions.min.js b/amd/build/tablebulkactions.min.js
new file mode 100644
index 00000000..b899d984
--- /dev/null
+++ b/amd/build/tablebulkactions.min.js
@@ -0,0 +1,2 @@
+define ("tool_lifecycle/tablebulkactions",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=function(){var a=document.querySelectorAll("input[name=\"procerror-select\"]"),b=document.querySelectorAll("*[data-lifecycle-action]");b.forEach(function(b){b.onclick=function(c){c.preventDefault();var d=[{k:"action",v:b.getAttribute("data-lifecycle-action")},{k:"sesskey",v:M.cfg.sesskey}];if("1"===b.getAttribute("data-lifecycle-forall")){d.push({k:"all",v:"1"});e(window.location,d)}else{a.forEach(function(a){if(a.checked){d.push({k:"id[]",v:a.value})}});e(window.location,d)}}})};function b(a){if("undefined"==typeof Symbol||null==a[Symbol.iterator]){if(Array.isArray(a)||(a=c(a))){var b=0,d=function(){};return{s:d,n:function n(){if(b>=a.length)return{done:!0};return{done:!1,value:a[b++]}},e:function e(a){throw a},f:d}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var e,f=!0,g=!1,h;return{s:function s(){e=a[Symbol.iterator]()},n:function n(){var a=e.next();f=a.done;return a},e:function e(a){g=!0;h=a},f:function f(){try{if(!f&&null!=e.return)e.return()}finally{if(g)throw h}}}}function c(a,b){if(!a)return;if("string"==typeof a)return d(a,b);var c=Object.prototype.toString.call(a).slice(8,-1);if("Object"===c&&a.constructor)c=a.constructor.name;if("Map"===c||"Set"===c)return Array.from(c);if("Arguments"===c||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(c))return d(a,b)}function d(a,b){if(null==b||b>a.length)b=a.length;for(var c=0,d=Array(b);c.\n\n/**\n * Javascript controller for checkboxed table.\n * @module tool_lifecycle/tablebulkactions\n * @copyright 2021 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Helper function to redirect via POST\n * @param {String} url redirect to\n * @param {Array} data redirect with data\n */\nfunction redirectPost(url, data) {\n const form = document.createElement('form');\n document.body.appendChild(form);\n form.method = 'post';\n form.action = url;\n for (const pair of data) {\n const input = document.createElement('input');\n input.type = 'hidden';\n input.name = pair.k;\n input.value = pair.v;\n form.appendChild(input);\n }\n form.submit();\n}\n\n/**\n * Init function\n */\nexport function init() {\n const checkboxes = document.querySelectorAll('input[name=\"procerror-select\"]');\n\n const action = document.querySelectorAll('*[data-lifecycle-action]');\n action.forEach((a) => {\n a.onclick = (e) => {\n e.preventDefault();\n let data = [\n {k: 'action', v: a.getAttribute('data-lifecycle-action')},\n {k: 'sesskey', v: M.cfg.sesskey}\n ];\n if (a.getAttribute('data-lifecycle-forall') === '1') {\n data.push({k: 'all', v: '1'});\n redirectPost(window.location, data);\n } else {\n checkboxes.forEach((c) => {\n if (c.checked) {\n data.push({k: 'id[]', v: c.value});\n }\n });\n redirectPost(window.location, data);\n }\n };\n });\n}"],"file":"tablebulkactions.min.js"}
\ No newline at end of file
diff --git a/amd/src/tablebulkactions.js b/amd/src/tablebulkactions.js
new file mode 100644
index 00000000..5e0afbad
--- /dev/null
+++ b/amd/src/tablebulkactions.js
@@ -0,0 +1,70 @@
+// 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 .
+
+/**
+ * Javascript controller for checkboxed table.
+ * @module tool_lifecycle/tablebulkactions
+ * @copyright 2021 Justus Dieckmann WWU
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Helper function to redirect via POST
+ * @param {String} url redirect to
+ * @param {Array} data redirect with data
+ */
+function redirectPost(url, data) {
+ const form = document.createElement('form');
+ document.body.appendChild(form);
+ form.method = 'post';
+ form.action = url;
+ for (const pair of data) {
+ const input = document.createElement('input');
+ input.type = 'hidden';
+ input.name = pair.k;
+ input.value = pair.v;
+ form.appendChild(input);
+ }
+ form.submit();
+}
+
+/**
+ * Init function
+ */
+export function init() {
+ const checkboxes = document.querySelectorAll('input[name="procerror-select"]');
+
+ const action = document.querySelectorAll('*[data-lifecycle-action]');
+ action.forEach((a) => {
+ a.onclick = (e) => {
+ e.preventDefault();
+ let data = [
+ {k: 'action', v: a.getAttribute('data-lifecycle-action')},
+ {k: 'sesskey', v: M.cfg.sesskey}
+ ];
+ if (a.getAttribute('data-lifecycle-forall') === '1') {
+ data.push({k: 'all', v: '1'});
+ redirectPost(window.location, data);
+ } else {
+ checkboxes.forEach((c) => {
+ if (c.checked) {
+ data.push({k: 'id[]', v: c.value});
+ }
+ });
+ redirectPost(window.location, data);
+ }
+ };
+ });
+}
\ No newline at end of file
diff --git a/classes/action.php b/classes/action.php
index fe93c00d..cc55e628 100644
--- a/classes/action.php
+++ b/classes/action.php
@@ -22,8 +22,6 @@
*/
namespace tool_lifecycle;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Delivers all available action names throughout the plugin.
* @package tool_lifecycle
diff --git a/classes/event/process_proceeded.php b/classes/event/process_proceeded.php
index 0df4ac71..c3c9ac93 100644
--- a/classes/event/process_proceeded.php
+++ b/classes/event/process_proceeded.php
@@ -26,8 +26,6 @@
use moodle_url;
use tool_lifecycle\local\entity\process;
-defined('MOODLE_INTERNAL') || die();
-
/**
* The process_proceeded event class.
*
diff --git a/classes/event/process_rollback.php b/classes/event/process_rollback.php
index b83d73b3..5fadca09 100644
--- a/classes/event/process_rollback.php
+++ b/classes/event/process_rollback.php
@@ -27,8 +27,6 @@
use moodle_url;
use tool_lifecycle\local\entity\process;
-defined('MOODLE_INTERNAL') || die();
-
/**
* The process_rollback event class.
*
diff --git a/classes/event/process_triggered.php b/classes/event/process_triggered.php
index dcde2225..0648b501 100644
--- a/classes/event/process_triggered.php
+++ b/classes/event/process_triggered.php
@@ -27,8 +27,6 @@
use moodle_url;
use tool_lifecycle\local\entity\process;
-defined('MOODLE_INTERNAL') || die();
-
/**
* The process_triggered event class.
*
diff --git a/classes/local/backup/backup_lifecycle_workflow.php b/classes/local/backup/backup_lifecycle_workflow.php
index 4505fa03..4cdfa07a 100644
--- a/classes/local/backup/backup_lifecycle_workflow.php
+++ b/classes/local/backup/backup_lifecycle_workflow.php
@@ -31,8 +31,6 @@
use tool_lifecycle\local\manager\settings_manager;
use tool_lifecycle\settings_type;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Class to backup a workflow.
* @package tool_lifecycle
diff --git a/classes/local/backup/restore_lifecycle_workflow.php b/classes/local/backup/restore_lifecycle_workflow.php
index 16a4141e..8662fa2c 100644
--- a/classes/local/backup/restore_lifecycle_workflow.php
+++ b/classes/local/backup/restore_lifecycle_workflow.php
@@ -31,8 +31,6 @@
use tool_lifecycle\local\manager\settings_manager;
use tool_lifecycle\settings_type;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Class to restore a workflow.
* @package tool_lifecycle
diff --git a/classes/local/data/manual_trigger_tool.php b/classes/local/data/manual_trigger_tool.php
index 48ffa42c..d669ba82 100644
--- a/classes/local/data/manual_trigger_tool.php
+++ b/classes/local/data/manual_trigger_tool.php
@@ -25,8 +25,6 @@
use renderable;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Class representing a manual trigger tool
*
diff --git a/classes/local/entity/process.php b/classes/local/entity/process.php
index c05fea0e..3f94460e 100644
--- a/classes/local/entity/process.php
+++ b/classes/local/entity/process.php
@@ -23,8 +23,6 @@
*/
namespace tool_lifecycle\local\entity;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Life Cycle Process class
*
diff --git a/classes/local/entity/step_subplugin.php b/classes/local/entity/step_subplugin.php
index e50ecde0..711a37e1 100644
--- a/classes/local/entity/step_subplugin.php
+++ b/classes/local/entity/step_subplugin.php
@@ -23,8 +23,6 @@
*/
namespace tool_lifecycle\local\entity;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Subplugin class
*
diff --git a/classes/local/entity/subplugin.php b/classes/local/entity/subplugin.php
index 15e38098..2190ba23 100644
--- a/classes/local/entity/subplugin.php
+++ b/classes/local/entity/subplugin.php
@@ -23,8 +23,6 @@
*/
namespace tool_lifecycle\local\entity;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Subplugin class
*
@@ -32,7 +30,7 @@
* @copyright 2017 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-abstract class subplugin{
+abstract class subplugin {
/** @var int $id Id of subplugin */
public $id;
diff --git a/classes/local/entity/trigger_subplugin.php b/classes/local/entity/trigger_subplugin.php
index d4c98fab..ebc8d14d 100644
--- a/classes/local/entity/trigger_subplugin.php
+++ b/classes/local/entity/trigger_subplugin.php
@@ -23,8 +23,6 @@
*/
namespace tool_lifecycle\local\entity;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Trigger subplugin class
*
@@ -32,7 +30,7 @@
* @copyright 2017 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class trigger_subplugin extends subplugin{
+class trigger_subplugin extends subplugin {
/**
* Creates a subplugin from a db record.
diff --git a/classes/local/entity/workflow.php b/classes/local/entity/workflow.php
index 9be4f03c..11bd5afd 100644
--- a/classes/local/entity/workflow.php
+++ b/classes/local/entity/workflow.php
@@ -23,8 +23,6 @@
*/
namespace tool_lifecycle\local\entity;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Life Cycle Workflow class
*
diff --git a/classes/local/manager/delayed_courses_manager.php b/classes/local/manager/delayed_courses_manager.php
index cb989ec8..a9c40245 100644
--- a/classes/local/manager/delayed_courses_manager.php
+++ b/classes/local/manager/delayed_courses_manager.php
@@ -24,7 +24,6 @@
*/
namespace tool_lifecycle\local\manager;
-defined('MOODLE_INTERNAL') || die();
/**
* Manager for Delayed Courses.
*
diff --git a/classes/local/manager/interaction_manager.php b/classes/local/manager/interaction_manager.php
index 5dbe2d45..87ecfff8 100644
--- a/classes/local/manager/interaction_manager.php
+++ b/classes/local/manager/interaction_manager.php
@@ -27,8 +27,6 @@
use tool_lifecycle\processor;
use tool_lifecycle\local\response\step_interactive_response;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Manager to handle interactions by users
*
diff --git a/classes/local/manager/lib_manager.php b/classes/local/manager/lib_manager.php
index 7e827773..afd381ee 100644
--- a/classes/local/manager/lib_manager.php
+++ b/classes/local/manager/lib_manager.php
@@ -28,8 +28,6 @@
use tool_lifecycle\trigger\base_automatic;
use tool_lifecycle\trigger\base_manual;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Manager to retrive the lib of each subplugin.
*
diff --git a/classes/local/manager/process_data_manager.php b/classes/local/manager/process_data_manager.php
index fb3f1681..722e2a6a 100644
--- a/classes/local/manager/process_data_manager.php
+++ b/classes/local/manager/process_data_manager.php
@@ -30,8 +30,6 @@
use tool_lifecycle\local\entity\process;
use tool_lifecycle\local\entity\trigger_subplugin;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Manager for data of Life Cycle Processes.
*
diff --git a/classes/local/manager/process_manager.php b/classes/local/manager/process_manager.php
index f8b28c9f..0eba63e9 100644
--- a/classes/local/manager/process_manager.php
+++ b/classes/local/manager/process_manager.php
@@ -24,12 +24,11 @@
namespace tool_lifecycle\local\manager;
use core\event\course_deleted;
+use Exception;
use tool_lifecycle\local\entity\process;
use tool_lifecycle\event\process_proceeded;
use tool_lifecycle\event\process_rollback;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Manager for Life Cycle Processes
*
@@ -245,4 +244,69 @@ public static function abort_process($process) {
$steplib->abort_course($process);
self::remove_process($process);
}
+
+ /**
+ * Moves a process into the procerror table.
+ *
+ * @param process $process The process
+ * @param Exception $e The exception
+ * @return void
+ */
+ public static function insert_process_error(process $process, Exception $e) {
+ global $DB;
+
+ $procerror = (object) clone $process;
+ $procerror->errormessage = get_class($e) . ': ' . $e->getMessage();
+ $procerror->errortrace = $e->getTraceAsString();
+ $procerror->errortimecreated = time();
+ $m = '';
+ foreach ($e->getTrace() as $v) {
+ $m .= $v['file'] . ':' . $v['line'] . '::';
+ }
+ $procerror->errorhash = md5($m);
+ $procerror->waiting = intval($procerror->waiting);
+
+ $DB->insert_record_raw('tool_lifecycle_proc_error', $procerror, false, false, true);
+ $DB->delete_records('tool_lifecycle_process', ['id' => $process->id]);
+ }
+
+ /**
+ * Proceed process from procerror back into the process board.
+ * @param int $processid the processid
+ * @return void
+ */
+ public static function proceed_process_after_error(int $processid) {
+ global $DB;
+ $process = $DB->get_record('tool_lifecycle_proc_error', ['id' => $processid]);
+ // Unset process error entries.
+ unset($process->errormessage);
+ unset($process->errortrace);
+ unset($process->errorhash);
+ unset($process->errortimecreated);
+
+ $DB->insert_record_raw('tool_lifecycle_process', $process, false, false, true);
+ $DB->delete_records('tool_lifecycle_proc_error', ['id' => $process->id]);
+ }
+
+ /**
+ * Rolls back a process from procerror table
+ * @param int $processid the processid
+ * @return void
+ */
+ public static function rollback_process_after_error(int $processid) {
+ global $DB;
+
+ $process = $DB->get_record('tool_lifecycle_proc_error', ['id' => $processid]);
+ // Unset process error entries.
+ unset($process->errormessage);
+ unset($process->errortrace);
+ unset($process->errorhash);
+ unset($process->errortimecreated);
+
+ $DB->insert_record_raw('tool_lifecycle_process', $process, false, false, true);
+ $DB->delete_records('tool_lifecycle_proc_error', ['id' => $process->id]);
+
+ delayed_courses_manager::set_course_delayed_for_workflow($process->courseid, true, $process->workflowid);
+ self::rollback_process($process);
+ }
}
diff --git a/classes/local/manager/step_manager.php b/classes/local/manager/step_manager.php
index 4a03f4ee..cd58d1a5 100644
--- a/classes/local/manager/step_manager.php
+++ b/classes/local/manager/step_manager.php
@@ -27,8 +27,6 @@
use tool_lifecycle\local\entity\step_subplugin;
use tool_lifecycle\settings_type;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Manager for Subplugins
*
diff --git a/classes/local/manager/subplugin_manager.php b/classes/local/manager/subplugin_manager.php
index 8728582f..951cc669 100644
--- a/classes/local/manager/subplugin_manager.php
+++ b/classes/local/manager/subplugin_manager.php
@@ -23,22 +23,6 @@
*/
namespace tool_lifecycle\local\manager;
-defined('MOODLE_INTERNAL') || die();
-// 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 .
-
/**
* Manager for Subplugins
*
diff --git a/classes/local/manager/trigger_manager.php b/classes/local/manager/trigger_manager.php
index e59a8a4a..2c7d84d3 100644
--- a/classes/local/manager/trigger_manager.php
+++ b/classes/local/manager/trigger_manager.php
@@ -28,8 +28,6 @@
use tool_lifecycle\local\entity\workflow;
use tool_lifecycle\settings_type;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Manager for Trigger subplugins
*
diff --git a/classes/local/manager/workflow_manager.php b/classes/local/manager/workflow_manager.php
index 690d1397..34e721ea 100644
--- a/classes/local/manager/workflow_manager.php
+++ b/classes/local/manager/workflow_manager.php
@@ -30,8 +30,6 @@
use tool_lifecycle\local\data\manual_trigger_tool;
use tool_lifecycle\settings_type;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Manager for Life Cycle Workflows
*
diff --git a/classes/local/response/step_interactive_response.php b/classes/local/response/step_interactive_response.php
index f9c89d41..ab23fdd0 100644
--- a/classes/local/response/step_interactive_response.php
+++ b/classes/local/response/step_interactive_response.php
@@ -23,8 +23,6 @@
*/
namespace tool_lifecycle\local\response;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Possible Responses of a Subplugin for interaction handling
*
diff --git a/classes/local/response/step_response.php b/classes/local/response/step_response.php
index f6301d74..15266179 100644
--- a/classes/local/response/step_response.php
+++ b/classes/local/response/step_response.php
@@ -23,8 +23,6 @@
*/
namespace tool_lifecycle\local\response;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Possible Responses of a Subplugin
*
diff --git a/classes/local/response/trigger_response.php b/classes/local/response/trigger_response.php
index 9e4f0975..8276b096 100644
--- a/classes/local/response/trigger_response.php
+++ b/classes/local/response/trigger_response.php
@@ -23,8 +23,6 @@
*/
namespace tool_lifecycle\local\response;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Possible Responses of a Trigger Subplugin
*
diff --git a/classes/local/table/process_errors_table.php b/classes/local/table/process_errors_table.php
new file mode 100644
index 00000000..545a883d
--- /dev/null
+++ b/classes/local/table/process_errors_table.php
@@ -0,0 +1,221 @@
+.
+
+/**
+ * Table listing all process errors
+ *
+ * @package tool_lifecycle
+ * @copyright 2021 Justus Dieckmann WWU
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace tool_lifecycle\local\table;
+
+defined('MOODLE_INTERNAL') || die;
+
+require_once($CFG->libdir . '/tablelib.php');
+
+/**
+ * Table listing all process errors
+ *
+ * @package tool_lifecycle
+ * @copyright 2021 Justus Dieckmann WWU
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class process_errors_table extends \table_sql {
+
+ /**
+ * @var array "cached" lang strings
+ */
+ private $strings;
+
+ /**
+ * Constructor for delayed_courses_table.
+ *
+ * @throws \coding_exception
+ */
+ public function __construct() {
+ global $OUTPUT;
+
+ parent::__construct('tool_lifecycle-process_errors');
+
+ $this->strings = [
+ 'proceed' => get_string('proceed', 'tool_lifecycle'),
+ 'rollback' => get_string('rollback', 'tool_lifecycle')
+ ];
+
+ $fields = 'c.fullname as course, w.title as workflow, s.instancename as step, pe.*';
+
+ $from = '{tool_lifecycle_proc_error} pe ' .
+ 'JOIN {tool_lifecycle_workflow} w ON pe.workflowid = w.id ' .
+ 'JOIN {tool_lifecycle_step} s ON pe.workflowid = s.workflowid AND pe.stepindex = s.sortindex ' .
+ 'LEFT JOIN {course} c ON pe.courseid = c.id ';
+
+ $this->set_sql($fields, $from, 'TRUE');
+ $this->column_nosort = ['select', 'tools'];
+ $this->define_columns(['select', 'workflow', 'step', 'courseid', 'course', 'error', 'tools']);
+ $this->define_headers([
+ $OUTPUT->render(new \core\output\checkbox_toggleall('procerrors-table', true, [
+ 'id' => 'select-all-procerrors',
+ 'name' => 'select-all-procerrors',
+ 'label' => get_string('selectall'),
+ 'labelclasses' => 'sr-only',
+ 'classes' => 'm-1',
+ 'checked' => false,
+ ])),
+ get_string('workflow', 'tool_lifecycle'),
+ get_string('step', 'tool_lifecycle'),
+ get_string('courseid', 'tool_lifecycle'),
+ get_string('course'),
+ get_string('error'),
+ get_string('tools', 'tool_lifecycle')
+ ]);
+ }
+
+ /**
+ * Render error column.
+ *
+ * @param object $row Row data.
+ * @return string error cell
+ * @throws \coding_exception
+ * @throws \moodle_exception
+ */
+ public function col_error($row) {
+ return "" .
+ nl2br(htmlentities($row->errormessage)) .
+ "
" .
+ nl2br(htmlentities($row->errortrace)) .
+ "
";
+ }
+
+ /**
+ * Render tools column.
+ *
+ * @param object $row Row data.
+ * @return string pluginname of the subplugin
+ * @throws \coding_exception
+ * @throws \moodle_exception
+ */
+ public function col_tools($row) {
+ global $OUTPUT;
+
+ $actionmenu = new \action_menu();
+ $actionmenu->add_primary_action(
+ new \action_menu_link_primary(
+ new \moodle_url('', ['action' => 'proceed', 'id[]' => $row->id, 'sesskey' => sesskey()]),
+ new \pix_icon('e/tick', $this->strings['proceed']),
+ $this->strings['proceed']
+ )
+ );
+ $actionmenu->add_primary_action(
+ new \action_menu_link_primary(
+ new \moodle_url('', ['action' => 'rollback', 'id[]' => $row->id, 'sesskey' => sesskey()]),
+ new \pix_icon('e/undo', $this->strings['rollback']),
+ $this->strings['rollback']
+ )
+ );
+ return $OUTPUT->render($actionmenu);
+ }
+
+ /**
+ * Generate the select column.
+ *
+ * @param \stdClass $data
+ * @return string
+ */
+ public function col_select($data) {
+ global $OUTPUT;
+
+ $checkbox = new \core\output\checkbox_toggleall('procerrors-table', false, [
+ 'classes' => 'usercheckbox m-1',
+ 'id' => 'procerror' . $data->id,
+ 'name' => 'procerror-select',
+ 'value' => $data->id,
+ 'checked' => false,
+ 'label' => get_string('selectitem', 'moodle', $data->id),
+ 'labelclasses' => 'accesshide',
+ ]);
+
+ return $OUTPUT->render($checkbox);
+ }
+
+ /**
+ * Override the table show_hide_link to not show for select column.
+ *
+ * @param string $column the column name, index into various names.
+ * @param int $index numerical index of the column.
+ * @return string HTML fragment.
+ */
+ protected function show_hide_link($column, $index) {
+ if ($index > 0) {
+ return parent::show_hide_link($column, $index);
+ }
+ return '';
+ }
+
+ /**
+ * Show custom nothing to display message.
+ * @return void
+ */
+ public function print_nothing_to_display() {
+ global $OUTPUT;
+
+ // Render the dynamic table header.
+ echo $this->get_dynamic_table_html_start();
+
+ // Render button to allow user to reset table preferences.
+ echo $this->render_reset_button();
+
+ $this->print_initials_bar();
+
+ echo $OUTPUT->heading(get_string('noprocesserrors', 'tool_lifecycle'));
+
+ // Render the dynamic table footer.
+ echo $this->get_dynamic_table_html_end();
+ }
+
+ /**
+ * Hook that can be overridden in child classes to wrap a table in a form
+ * for example. Called only when there is data to display and not
+ * downloading.
+ */
+ public function wrap_html_finish() {
+ global $OUTPUT;
+ parent::wrap_html_finish();
+ echo "
";
+
+ $actionmenu = new \action_menu();
+ $actionmenu->add_secondary_action(
+ new \action_menu_link_secondary(
+ new \moodle_url(''),
+ new \pix_icon('e/tick', $this->strings['proceed']),
+ $this->strings['proceed'],
+ ['data-lifecycle-action' => 'proceed']
+ )
+ );
+
+ $actionmenu->add_secondary_action(
+ new \action_menu_link_secondary(
+ new \moodle_url(''),
+ new \pix_icon('e/undo', $this->strings['rollback']),
+ $this->strings['rollback'],
+ ['data-lifecycle-action' => 'rollback']
+ )
+ );
+
+ $actionmenu->set_menu_trigger(get_string('forselected', 'tool_lifecycle'));
+ echo $OUTPUT->render_action_menu($actionmenu);
+ }
+}
diff --git a/classes/plugininfo/lifecyclestep.php b/classes/plugininfo/lifecyclestep.php
index d8cf9b00..8fa5098a 100644
--- a/classes/plugininfo/lifecyclestep.php
+++ b/classes/plugininfo/lifecyclestep.php
@@ -27,8 +27,6 @@
use tool_lifecycle\local\manager\step_manager;
use tool_lifecycle\local\manager\workflow_manager;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Pluginfo for life cycle step
*
diff --git a/classes/plugininfo/lifecycletrigger.php b/classes/plugininfo/lifecycletrigger.php
index 2258f64e..62b7176c 100644
--- a/classes/plugininfo/lifecycletrigger.php
+++ b/classes/plugininfo/lifecycletrigger.php
@@ -30,8 +30,6 @@
use tool_lifecycle\local\manager\workflow_manager;
use tool_usertours\step;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Pluginfo for life cycle trigger
*
diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php
index 9c506dbb..d320f46c 100644
--- a/classes/privacy/provider.php
+++ b/classes/privacy/provider.php
@@ -35,8 +35,6 @@
use tool_lifecycle\local\manager\step_manager;
use tool_lifecycle\local\manager\workflow_manager;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Implementation of the privacy subsystem plugin provider for the Life Cycle tool.
*
diff --git a/classes/processor.php b/classes/processor.php
index f152055b..c1a185d9 100644
--- a/classes/processor.php
+++ b/classes/processor.php
@@ -35,9 +35,6 @@
use tool_lifecycle\local\response\step_response;
use tool_lifecycle\local\response\trigger_response;
-
-defined('MOODLE_INTERNAL') || die;
-
/**
* Offers functionality to trigger, process and finish lifecycle processes.
*
@@ -119,10 +116,15 @@ public function process_courses() {
$step = step_manager::get_step_instance_by_workflow_index($process->workflowid, $process->stepindex);
$lib = lib_manager::get_step_lib($step->subpluginname);
- if ($process->waiting) {
- $result = $lib->process_waiting_course($process->id, $step->id, $course);
- } else {
- $result = $lib->process_course($process->id, $step->id, $course);
+ try {
+ if ($process->waiting) {
+ $result = $lib->process_waiting_course($process->id, $step->id, $course);
+ } else {
+ $result = $lib->process_course($process->id, $step->id, $course);
+ }
+ } catch (\Exception $e) {
+ process_manager::insert_process_error($process, $e);
+ break;
}
if ($result == step_response::waiting()) {
process_manager::set_process_waiting($process);
@@ -220,7 +222,9 @@ public function get_course_recordset($triggers, $exclude) {
$sql = 'SELECT {course}.* from {course} '.
'left join {tool_lifecycle_process} '.
'ON {course}.id = {tool_lifecycle_process}.courseid '.
- 'WHERE {tool_lifecycle_process}.courseid is null AND ' . $where;
+ 'LEFT JOIN {tool_lifecycle_proc_error} pe ON {course}.id = pe.courseid ' .
+ 'WHERE {tool_lifecycle_process}.courseid is null AND ' .
+ 'pe.courseid IS NULL AND '. $where;
return $DB->get_recordset_sql($sql, $whereparams);
}
diff --git a/classes/settings_type.php b/classes/settings_type.php
index d63e3404..33aa445a 100644
--- a/classes/settings_type.php
+++ b/classes/settings_type.php
@@ -22,8 +22,6 @@
*/
namespace tool_lifecycle;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Defines available settings_types.
* @package tool_lifecycle
diff --git a/classes/task/lifecycle_cleanup_task.php b/classes/task/lifecycle_cleanup_task.php
index 5c31f11b..eadeadf1 100644
--- a/classes/task/lifecycle_cleanup_task.php
+++ b/classes/task/lifecycle_cleanup_task.php
@@ -23,8 +23,6 @@
*/
namespace tool_lifecycle\task;
-defined('MOODLE_INTERNAL') || die;
-
/**
* Scheduled task for cleanup past delays
*
diff --git a/classes/task/lifecycle_error_notify_task.php b/classes/task/lifecycle_error_notify_task.php
new file mode 100644
index 00000000..c20aee73
--- /dev/null
+++ b/classes/task/lifecycle_error_notify_task.php
@@ -0,0 +1,77 @@
+.
+
+/**
+ * Scheduled task for notify admin upon process errors
+ *
+ * @package tool_lifecycle
+ * @copyright 2022 Justus Dieckmann WWU
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace tool_lifecycle\task;
+
+/**
+ * Scheduled task for notify admin upon process errors
+ *
+ * @package tool_lifecycle
+ * @copyright 2022 Justus Dieckmann WWU
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class lifecycle_error_notify_task extends \core\task\scheduled_task {
+
+ /**
+ * Get a descriptive name for this task (shown to admins).
+ *
+ * @return string
+ * @throws \coding_exception
+ */
+ public function get_name() {
+ return get_string('lifecycle_error_notify_task', 'tool_lifecycle');
+ }
+
+ /**
+ * Do the job.
+ */
+ public function execute() {
+ global $DB, $CFG;
+
+ $lastrun = get_config('tool_lifecycle', 'adminerrornotifylastrun');
+ if (!$lastrun) {
+ $lastrun = 0;
+ }
+
+ $currenttime = time();
+
+ $errorcount = $DB->count_records_select('tool_lifecycle_proc_error', 'errortimecreated > :lastrun',
+ ['lastrun' => $lastrun]);
+
+ set_config('adminerrornotifylastrun', $currenttime, 'tool_lifecycle');
+
+ if (!$errorcount) {
+ return;
+ }
+
+ $obj = new \stdClass();
+ $obj->amount = $errorcount;
+ $obj->url = $CFG->wwwroot . '/admin/tool/lifecycle/errors.php';
+
+ email_to_user(get_admin(), \core_user::get_noreply_user(),
+ get_string('notifyerrorsemailsubject', 'tool_lifecycle', $obj),
+ get_string('notifyerrorsemailcontent', 'tool_lifecycle', $obj),
+ get_string('notifyerrorsemailcontenthtml', 'tool_lifecycle', $obj),
+ );
+ }
+}
diff --git a/classes/task/lifecycle_task.php b/classes/task/lifecycle_task.php
index 57fe110f..91692d9a 100644
--- a/classes/task/lifecycle_task.php
+++ b/classes/task/lifecycle_task.php
@@ -27,8 +27,6 @@
use tool_lifecycle\local\manager\step_manager;
use tool_lifecycle\processor;
-defined('MOODLE_INTERNAL') || die;
-
/**
* Scheduled task for working on lifecycle processes
*
diff --git a/classes/view_controller.php b/classes/view_controller.php
index 32e297d3..351f0a89 100644
--- a/classes/view_controller.php
+++ b/classes/view_controller.php
@@ -32,9 +32,7 @@
use tool_lifecycle\local\manager\trigger_manager;
use tool_lifecycle\local\table\interaction_log_table;
use tool_lifecycle\local\table\interaction_remaining_table;
-use tool_lifecycle\local\table\interaction_attention_table;
-
-defined('MOODLE_INTERNAL') || die();
+use tool_lifecycle\local\table\interaction_attention_table;;
/**
* Controller for view.php
diff --git a/db/install.xml b/db/install.xml
index d6877a52..c8940a4b 100644
--- a/db/install.xml
+++ b/db/install.xml
@@ -1,5 +1,5 @@
-
@@ -146,5 +146,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/db/tasks.php b/db/tasks.php
index f708e82c..d061305a 100644
--- a/db/tasks.php
+++ b/db/tasks.php
@@ -44,5 +44,14 @@
'day' => '*',
'month' => '*',
'dayofweek' => '0',
- )
+ ),
+ array(
+ 'classname' => 'tool_lifecycle\task\lifecycle_error_notify_task',
+ 'blocking' => 0,
+ 'minute' => 'R',
+ 'hour' => '5',
+ 'day' => '*',
+ 'month' => '*',
+ 'dayofweek' => '0',
+ ),
);
diff --git a/db/upgrade.php b/db/upgrade.php
index 1e5a1723..99accd3e 100644
--- a/db/upgrade.php
+++ b/db/upgrade.php
@@ -22,8 +22,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-defined('MOODLE_INTERNAL') || die();
-
/**
* Update script for tool_lifecycle.
* @param int $oldversion Version id of the previously installed version.
@@ -446,5 +444,36 @@ function xmldb_tool_lifecycle_upgrade($oldversion) {
upgrade_plugin_savepoint(true, 2020091800, 'tool', 'lifecycle');
}
+ if ($oldversion < 2021112300) {
+
+ // Define table tool_lifecycle_proc_error to be created.
+ $table = new xmldb_table('tool_lifecycle_proc_error');
+
+ // Adding fields to table tool_lifecycle_proc_error.
+ $table->add_field('id', XMLDB_TYPE_INTEGER, '20', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
+ $table->add_field('courseid', XMLDB_TYPE_INTEGER, '20', null, XMLDB_NOTNULL, null, null);
+ $table->add_field('workflowid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
+ $table->add_field('stepindex', XMLDB_TYPE_INTEGER, '5', null, XMLDB_NOTNULL, null, null);
+ $table->add_field('waiting', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
+ $table->add_field('timestepchanged', XMLDB_TYPE_INTEGER, '11', null, XMLDB_NOTNULL, null, null);
+ $table->add_field('errormessage', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
+ $table->add_field('errortrace', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
+ $table->add_field('errorhash', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
+ $table->add_field('errortimecreated', XMLDB_TYPE_INTEGER, '11', null, XMLDB_NOTNULL, null, null);
+
+ // Adding keys to table tool_lifecycle_proc_error.
+ $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
+ $table->add_key('courseid_fk', XMLDB_KEY_FOREIGN_UNIQUE, ['courseid'], 'course', ['id']);
+ $table->add_key('workflowid_fk', XMLDB_KEY_FOREIGN, ['workflowid'], 'tool_lifecycle_workflow', ['id']);
+
+ // Conditionally launch create table for tool_lifecycle_proc_error.
+ if (!$dbman->table_exists($table)) {
+ $dbman->create_table($table);
+ }
+
+ // Lifecycle savepoint reached.
+ upgrade_plugin_savepoint(true, 2021112300, 'tool', 'lifecycle');
+ }
+
return true;
}
diff --git a/errors.php b/errors.php
new file mode 100644
index 00000000..40c80bcc
--- /dev/null
+++ b/errors.php
@@ -0,0 +1,70 @@
+.
+
+/**
+ * Displays the process errors
+ *
+ * @package tool_lifecycle
+ * @copyright 2021 Justus Dieckmann WWU
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+use tool_lifecycle\local\manager\process_manager;
+use tool_lifecycle\local\table\process_errors_table;
+
+require_once(__DIR__ . '/../../../config.php');
+require_once($CFG->libdir . '/adminlib.php');
+
+$PAGE->set_context(context_system::instance());
+require_login();
+require_capability('moodle/site:config', context_system::instance());
+
+admin_externalpage_setup('tool_lifecycle_process_errors');
+
+$PAGE->set_url(new \moodle_url('/admin/tool/lifecycle/errors.php'));
+
+// Action handling (delete, bulk-delete).
+$action = optional_param('action', null, PARAM_ALPHANUMEXT);
+if ($action) {
+ global $DB;
+ require_sesskey();
+ $ids = required_param_array('id', PARAM_INT);
+ if ($action == 'proceed') {
+ foreach ($ids as $id) {
+ process_manager::proceed_process_after_error($id);
+ }
+ } else if ($action == 'rollback') {
+ foreach ($ids as $id) {
+ process_manager::rollback_process_after_error($id);
+ }
+ } else {
+ throw new coding_exception("action must be either 'proceed' or 'rollback'");
+ }
+ redirect($PAGE->url);
+}
+
+$PAGE->set_title(get_string('process_errors_header', 'tool_lifecycle'));
+$PAGE->set_heading(get_string('process_errors_header', 'tool_lifecycle'));
+
+$table = new process_errors_table();
+$table->define_baseurl($PAGE->url);
+
+$PAGE->requires->js_call_amd('tool_lifecycle/tablebulkactions', 'init');
+
+echo $OUTPUT->header();
+$table->out(100, false);
+
+echo $OUTPUT->footer();
diff --git a/lang/de/tool_lifecycle.php b/lang/de/tool_lifecycle.php
index 5ce7b49b..fa77816e 100644
--- a/lang/de/tool_lifecycle.php
+++ b/lang/de/tool_lifecycle.php
@@ -175,3 +175,14 @@
$string['process_triggered_event'] = 'Ein Prozess wurde ausgelöst';
$string['process_proceeded_event'] = 'Ein Prozess wurde fortgeführt';
$string['process_rollback_event'] = 'Ein Prozess wurde zurückgesetzt';
+
+$string['courseid'] = 'Kurs-ID';
+$string['process_errors_header'] = 'Fehlermanagement';
+$string['proceed'] = 'Fortfahren';
+$string['forselected'] = 'Für alle ausgewählten Prozesse';
+$string['noprocesserrors'] = 'Es gibt keine fehlerhaften Prozesse, die behandelt werden müssen!';
+
+$string['lifecycle_error_notify_task'] = 'Benachrichtigt die Administratoren bei Fehlern in tool_lifecycle-Prozessen.';
+$string['notifyerrorsemailsubject'] = '{$a->amount} neue fehlerhafte tool_lifecycle Prozesse warten darauf, behandelt zu werden!';
+$string['notifyerrorsemailcontent'] = '{$a->amount} neue fehlerhafte tool_lifecycle Prozesse warten darauf, behandelt zu werden!' . "\n" . 'Bitte besuchen Sie {$a->url}.';
+$string['notifyerrorsemailcontenthtml'] = '{$a->amount} neue fehlerhafte tool_lifecycle Prozesse warten darauf, behandelt zu werden!
Bitte besuchen Sie die Übersichtsseite.';
diff --git a/lang/en/tool_lifecycle.php b/lang/en/tool_lifecycle.php
index dcf69f46..420eb266 100644
--- a/lang/en/tool_lifecycle.php
+++ b/lang/en/tool_lifecycle.php
@@ -210,3 +210,15 @@
$string['globally'] = 'Global delays';
$string['delays_for_workflow'] = 'Delays for "{$a}"';
$string['delete_all_delays'] = 'Delete all delays';
+
+$string['courseid'] = 'Course ID';
+$string['process_errors_header'] = 'Error handling';
+$string['proceed'] = 'Proceed';
+$string['rollback'] = 'Rollback';
+$string['forselected'] = 'For all selected processes';
+$string['noprocesserrors'] = 'There are no process errors to handle!';
+
+$string['lifecycle_error_notify_task'] = 'Notify the admin upon errors in tool_lifecycle processes';
+$string['notifyerrorsemailsubject'] = 'There are {$a->amount} new tool_lifecycle process errors waiting to be fixed!';
+$string['notifyerrorsemailcontent'] = 'There are {$a->amount} new tool_lifecycle process errors waiting to be fixed!' . "\n" . 'Please review them at {$a->url}.';
+$string['notifyerrorsemailcontenthtml'] = 'There are {$a->amount} new tool_lifecycle process errors waiting to be fixed!
Please review them at the error handling overview.';
diff --git a/lib.php b/lib.php
index 15820fb2..fa4532ae 100644
--- a/lib.php
+++ b/lib.php
@@ -21,8 +21,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-defined('MOODLE_INTERNAL') || die();
-
/**
* Adds a tool_lifecycle link to the course admin menu.
*
diff --git a/renderer.php b/renderer.php
index 1b1ee405..d332cb3f 100644
--- a/renderer.php
+++ b/renderer.php
@@ -21,7 +21,6 @@
* @copyright 2017 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-defined('MOODLE_INTERNAL') || die();
/**
* Renderer for life cycle
diff --git a/settings.php b/settings.php
index 71a26f82..ce6ad36f 100644
--- a/settings.php
+++ b/settings.php
@@ -50,6 +50,9 @@
$ADMIN->add('lifecycle_category', new admin_externalpage('tool_lifecycle_delayed_courses',
get_string('delayed_courses_header', 'tool_lifecycle'),
new moodle_url('/admin/tool/lifecycle/delayedcourses.php')));
+ $ADMIN->add('lifecycle_category', new admin_externalpage('tool_lifecycle_process_errors',
+ get_string('process_errors_header', 'tool_lifecycle'),
+ new moodle_url('/admin/tool/lifecycle/errors.php')));
if ($ADMIN->fulltree) {
$triggers = core_component::get_plugin_list('lifecycletrigger');
diff --git a/step/createbackup/db/upgrade.php b/step/createbackup/db/upgrade.php
index bfa92b83..d1583cd7 100644
--- a/step/createbackup/db/upgrade.php
+++ b/step/createbackup/db/upgrade.php
@@ -25,8 +25,6 @@
use tool_lifecycle\local\manager\settings_manager;
use tool_lifecycle\local\manager\step_manager;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Update script for lifecycles subplugin createbackup.
* @param int $oldversion Version id of the previously installed version.
diff --git a/step/deletecourse/db/upgrade.php b/step/deletecourse/db/upgrade.php
index 668a910e..c8467c5e 100644
--- a/step/deletecourse/db/upgrade.php
+++ b/step/deletecourse/db/upgrade.php
@@ -25,8 +25,6 @@
use tool_lifecycle\local\manager\settings_manager;
use tool_lifecycle\local\manager\step_manager;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Update script for lifecycles subplugin deletecourse
*
diff --git a/step/interactionlib.php b/step/interactionlib.php
index 0958cb16..a4909a52 100644
--- a/step/interactionlib.php
+++ b/step/interactionlib.php
@@ -31,8 +31,6 @@
use tool_lifecycle\local\entity\step_subplugin;
use tool_lifecycle\local\response\step_interactive_response;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Interface for the interactions of the subplugintype step.
*
diff --git a/tests/backup_manager_test.php b/tests/backup_manager_test.php
index ab27a381..fa6a7967 100644
--- a/tests/backup_manager_test.php
+++ b/tests/backup_manager_test.php
@@ -22,7 +22,6 @@
* @copyright 2017 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-defined('MOODLE_INTERNAL') || die();
use tool_lifecycle\local\manager\backup_manager;
diff --git a/tests/generator/lib.php b/tests/generator/lib.php
index 35a4ac7e..ae963a13 100644
--- a/tests/generator/lib.php
+++ b/tests/generator/lib.php
@@ -22,7 +22,6 @@
* @copyright 2017 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-defined('MOODLE_INTERNAL') || die();
use tool_lifecycle\local\entity\process;
use tool_lifecycle\local\entity\trigger_subplugin;
diff --git a/tests/manual_trigger_tools_test.php b/tests/manual_trigger_tools_test.php
index aad0a026..3477d198 100644
--- a/tests/manual_trigger_tools_test.php
+++ b/tests/manual_trigger_tools_test.php
@@ -22,7 +22,6 @@
* @copyright 2018 Tobias Reischmann, Jan Dageforde WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-defined('MOODLE_INTERNAL') || die();
use tool_lifecycle\action;
use tool_lifecycle\local\entity\workflow;
diff --git a/tests/process_error_test.php b/tests/process_error_test.php
new file mode 100644
index 00000000..5626b899
--- /dev/null
+++ b/tests/process_error_test.php
@@ -0,0 +1,116 @@
+.
+
+/**
+ * Checks whether process errors are properly inserted into the table.
+ *
+ * @package tool_lifecycle
+ * @category test
+ * @group tool_lifecycle
+ * @copyright 2022 Justus Dieckmann WWU
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace tool_lifecycle;
+
+use tool_lifecycle\local\entity\trigger_subplugin;
+use tool_lifecycle\local\manager\settings_manager;
+use tool_lifecycle\local\manager\workflow_manager;
+use tool_lifecycle\local\manager\trigger_manager;
+use tool_lifecycle\local\manager\process_manager;
+
+/**
+ * Checks whether process errors are properly inserted into the table.
+ *
+ * @package tool_lifecycle
+ * @category test
+ * @group tool_lifecycle
+ * @copyright 2022 Justus Dieckmann WWU
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class process_error_test extends \advanced_testcase {
+ /** Icon of the manual trigger. */
+ const MANUAL_TRIGGER1_ICON = 't/up';
+ /** Display name of the manual trigger. */
+ const MANUAL_TRIGGER1_DISPLAYNAME = 'Up';
+ /** Capability of the manual trigger. */
+ const MANUAL_TRIGGER1_CAPABILITY = 'moodle/course:manageactivities';
+
+
+ /** @var trigger_subplugin $trigger Instances of the triggers under test. */
+ private $trigger;
+ /** @var array $course Instance of the course under test. */
+ private $course;
+
+ /**
+ * Setup the testcase.
+ * @throws \coding_exception
+ * @throws \moodle_exception
+ */
+ public function setUp() : void {
+ global $USER, $DB;
+
+ // We do not need a sesskey check in theses tests.
+ $USER->ignoresesskey = true;
+
+ $this->resetAfterTest(true);
+ $generator = $this->getDataGenerator()->get_plugin_generator('tool_lifecycle');
+ $triggersettings = new \stdClass();
+ $triggersettings->icon = self::MANUAL_TRIGGER1_ICON;
+ $triggersettings->displayname = self::MANUAL_TRIGGER1_DISPLAYNAME;
+ $triggersettings->capability = self::MANUAL_TRIGGER1_CAPABILITY;
+ $manualworkflow = $generator->create_manual_workflow($triggersettings);
+ $step = $generator->create_step("instance1", "deletecourse", $manualworkflow->id);
+ settings_manager::save_settings($step->id, settings_type::STEP, "deletecourse",
+ array("maximumdeletionspercron" => 10)
+ );
+
+ workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $manualworkflow->id);
+
+ $this->course = $this->getDataGenerator()->create_course();
+ $this->getDataGenerator()->create_module('page', ['course' => $this->course->id]);
+
+ // Corrupt course.
+ $DB->execute('UPDATE {course_modules} SET instance = 0');
+ $this->trigger = trigger_manager::get_triggers_for_workflow($manualworkflow->id)[0];
+ }
+
+ /**
+ * Test if the correct process error was put into the table.
+ */
+ public function test_process_error_in_table() {
+ global $DB;
+ $process = process_manager::manually_trigger_process($this->course->id, $this->trigger->id);
+
+ // The delete course step really wants to print output.
+ ob_start();
+ $processor = new processor();
+ $processor->process_courses();
+ ob_end_clean();
+
+ $records = $DB->get_records('tool_lifecycle_proc_error');
+
+ $this->assertEquals(1, count($records));
+ $this->assertEquals(0, $DB->count_records('tool_lifecycle_process'));
+
+ $record = reset($records);
+
+ $this->assertEquals($this->course->id, $record->courseid);
+ $this->assertStringContainsString("Trying to get property 'id' of non-object", $record->errormessage);
+ $this->assertEquals($process->id, $record->id);
+ }
+
+}
diff --git a/tests/process_status_message_test.php b/tests/process_status_message_test.php
index e55fbe9f..5ac9756c 100644
--- a/tests/process_status_message_test.php
+++ b/tests/process_status_message_test.php
@@ -22,7 +22,6 @@
* @copyright 2018 Tamara Gunkel, Jan Dageforde WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-defined('MOODLE_INTERNAL') || die();
use tool_lifecycle\action;
use tool_lifecycle\local\entity\workflow;
diff --git a/tests/settings_manager_test.php b/tests/settings_manager_test.php
index 4444e335..a6c389f6 100644
--- a/tests/settings_manager_test.php
+++ b/tests/settings_manager_test.php
@@ -22,7 +22,6 @@
* @copyright 2017 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-defined('MOODLE_INTERNAL') || die();
use tool_lifecycle\local\entity\step_subplugin;
use tool_lifecycle\local\entity\trigger_subplugin;
diff --git a/trigger/categories/tests/generator/lib.php b/trigger/categories/tests/generator/lib.php
index 8d3bb50f..c8d410ec 100644
--- a/trigger/categories/tests/generator/lib.php
+++ b/trigger/categories/tests/generator/lib.php
@@ -22,7 +22,6 @@
* @copyright 2018 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-defined('MOODLE_INTERNAL') || die();
use tool_lifecycle\local\entity\trigger_subplugin;
use tool_lifecycle\local\entity\workflow;
diff --git a/trigger/categories/tests/trigger_test.php b/trigger/categories/tests/trigger_test.php
index 79f9e5fd..077149e4 100644
--- a/trigger/categories/tests/trigger_test.php
+++ b/trigger/categories/tests/trigger_test.php
@@ -22,7 +22,7 @@
* @copyright 2017 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-namespace tool_lifecycle\trigger;
+namespace lifecycletrigger_categories;
use tool_lifecycle\local\entity\trigger_subplugin;
use tool_lifecycle\processor;
@@ -41,7 +41,7 @@
* @copyright 2017 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class tool_lifecycle_trigger_categories_testcase extends \advanced_testcase {
+class trigger_test extends \advanced_testcase {
/** @var trigger_subplugin $excludetrigger Trigger instance that excludes a category. */
private $excludetrigger;
diff --git a/trigger/delayedcourses/db/install.php b/trigger/delayedcourses/db/install.php
index 00f52e2f..d75f53f3 100644
--- a/trigger/delayedcourses/db/install.php
+++ b/trigger/delayedcourses/db/install.php
@@ -24,8 +24,6 @@
*/
use tool_lifecycle\local\manager\trigger_manager;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Register delayed courses as initial workflow.
*/
diff --git a/trigger/delayedcourses/tests/generator/lib.php b/trigger/delayedcourses/tests/generator/lib.php
index 1561e1dc..b3cfb2dd 100644
--- a/trigger/delayedcourses/tests/generator/lib.php
+++ b/trigger/delayedcourses/tests/generator/lib.php
@@ -22,7 +22,6 @@
* @copyright 2018 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-defined('MOODLE_INTERNAL') || die();
use tool_lifecycle\local\entity\trigger_subplugin;
use tool_lifecycle\local\entity\workflow;
diff --git a/trigger/delayedcourses/tests/trigger_test.php b/trigger/delayedcourses/tests/trigger_test.php
index fcb5e7da..89dd51d3 100644
--- a/trigger/delayedcourses/tests/trigger_test.php
+++ b/trigger/delayedcourses/tests/trigger_test.php
@@ -22,7 +22,7 @@
* @copyright 2017 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-namespace tool_lifecycle\trigger;
+namespace lifecycletrigger_delayedcourses;
use tool_lifecycle\local\entity\trigger_subplugin;
use tool_lifecycle\local\entity\workflow;
@@ -43,7 +43,7 @@
* @copyright 2017 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class tool_lifecycle_trigger_delayedcourses_testcase extends \advanced_testcase {
+class trigger_test extends \advanced_testcase {
/** @var trigger_subplugin $triggerinstance Instance of the delayedcourses trigger. */
private $triggerinstance;
diff --git a/trigger/sitecourse/db/install.php b/trigger/sitecourse/db/install.php
index ef92e5e4..c026243b 100644
--- a/trigger/sitecourse/db/install.php
+++ b/trigger/sitecourse/db/install.php
@@ -23,8 +23,6 @@
*/
use tool_lifecycle\local\manager\trigger_manager;
-defined('MOODLE_INTERNAL') || die();
-
/**
* Register site course trigger exclusion as initial workflow.
*/
diff --git a/trigger/sitecourse/tests/generator/lib.php b/trigger/sitecourse/tests/generator/lib.php
index 4942d8c6..69320242 100644
--- a/trigger/sitecourse/tests/generator/lib.php
+++ b/trigger/sitecourse/tests/generator/lib.php
@@ -22,7 +22,6 @@
* @copyright 2018 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-defined('MOODLE_INTERNAL') || die();
use tool_lifecycle\local\entity\trigger_subplugin;
use tool_lifecycle\local\entity\workflow;
diff --git a/trigger/sitecourse/tests/trigger_test.php b/trigger/sitecourse/tests/trigger_test.php
index d5f602b7..655ccfa7 100644
--- a/trigger/sitecourse/tests/trigger_test.php
+++ b/trigger/sitecourse/tests/trigger_test.php
@@ -22,10 +22,11 @@
* @copyright 2017 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-namespace tool_lifecycle\trigger;
+namespace lifecycletrigger_sitecourse;
use tool_lifecycle\local\entity\trigger_subplugin;
use tool_lifecycle\local\response\trigger_response;
+use tool_lifecycle\trigger\sitecourse;
defined('MOODLE_INTERNAL') || die();
@@ -40,7 +41,7 @@
* @copyright 2017 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class tool_lifecycle_trigger_sitecourse_testcase extends \advanced_testcase {
+class trigger_test extends \advanced_testcase {
/** @var trigger_subplugin $triggerinstance Instance of the trigger. */
private $triggerinstance;
diff --git a/trigger/startdatedelay/tests/generator/lib.php b/trigger/startdatedelay/tests/generator/lib.php
index c3bd5cee..71291d52 100644
--- a/trigger/startdatedelay/tests/generator/lib.php
+++ b/trigger/startdatedelay/tests/generator/lib.php
@@ -22,7 +22,6 @@
* @copyright 2018 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-defined('MOODLE_INTERNAL') || die();
use tool_lifecycle\local\entity\trigger_subplugin;
use tool_lifecycle\local\entity\workflow;
diff --git a/trigger/startdatedelay/tests/trigger_test.php b/trigger/startdatedelay/tests/trigger_test.php
index 7466dd9b..6ca598fd 100644
--- a/trigger/startdatedelay/tests/trigger_test.php
+++ b/trigger/startdatedelay/tests/trigger_test.php
@@ -22,7 +22,7 @@
* @copyright 2017 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-namespace tool_lifecycle\trigger;
+namespace lifecycletrigger_startdatedelay;
use tool_lifecycle\local\entity\trigger_subplugin;
use tool_lifecycle\processor;
@@ -40,7 +40,7 @@
* @copyright 2017 Tobias Reischmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class tool_lifecycle_trigger_startdatedelay_testcase extends \advanced_testcase {
+class trigger_test extends \advanced_testcase {
/** @var $triggerinstance trigger_subplugin Instance of the trigger. */
private $triggerinstance;
diff --git a/version.php b/version.php
index 46092b8c..814e1fb9 100644
--- a/version.php
+++ b/version.php
@@ -25,7 +25,7 @@
defined('MOODLE_INTERNAL') || die;
$plugin->maturity = MATURITY_BETA;
-$plugin->version = 2021051700;
+$plugin->version = 2021112300;
$plugin->component = 'tool_lifecycle';
$plugin->requires = 2017111300; // Require Moodle 3.4 (or above).
$plugin->release = 'v3.11-r1';