From 306cf73ecae2eb5c92c751edc7d7adf10dd8bba8 Mon Sep 17 00:00:00 2001 From: Nina Herrmann Date: Wed, 19 Jun 2024 15:33:01 +0200 Subject: [PATCH] Update wwu branch (#219) * Removed , * CI: Update for Moodle 4.2 * Workflow backup: Do not save attributes when they are null * Bump version * MBS-7377: Fix workflowoverview for big instances * Fix wrong calculation of courses counts in template context * fix upload workflow (#185) * fix upload workflow * inserting feedback * finally * Add check if process exists. (#191) This prevents courses to be processed which had been rescued by the teacher. * Update README.md Make Subplugin List (and link to wiki) more apparent * Improve help text for integration of icons (manual trigger) (#193) * Improved help text for the integration of icons * Improved help text for the integration of icons * Update for Moodle 4.3 (#190) * CI: Update for Moodle 4.3 * Prevent dynamic property access on classes for PHP 8.2 * phpcbf for styles etc. --------- Co-authored-by: Justus Dieckmann Co-authored-by: NinaHerrmann * Hide menu when there is no manual workflow (#195) Co-authored-by: Justus Dieckmann * Fix step and trigger reordering: only change the relevant workflow (#200) * Reorder the remaining active workflows when disabling a workflow (#201) This fixes #128. * Show menu entry when a manual or automatic workflow is active (#199) * Show menu point when a manual or automatic workflow is active * Rename reset cache function * Show menu entry if there are workflows other than the default two --------- Co-authored-by: Justus Dieckmann * Check backup consistency before importing workflow (#196) * Check backup consistency before importing workflow * Fix PHPDocs * Use existing category in backup_and_restore test * lifecycletrigger_categories: A bit of general refactoring * lifecycletrigger_categories: Don't fail if category doesn't exist * Add possibility to force import of errorneous backup * Use $force = false as default in restore_workflow:execute * Display only unique errors when Workflows causes multiple errors --------- Co-authored-by: Justus Dieckmann Co-authored-by: NinaHerrmann * CI: Update for Moodle 4.4 * Codestyle PHPCBF * Sort strings in lang files alphabetically * Fix sortindex gaps in upgrade step * Bump version * The columns in active_manual_workflows_table shouldn't be sortable * Shell escape the release notes in the release workflow (#207) Co-authored-by: Justus Dieckmann * Fix mustache * added mtrace statement for logging failed mails (#214) * Shell escape release workflow for realsies this time (#208) --------- Co-authored-by: Justus Dieckmann Co-authored-by: Philipp Memmel Co-authored-by: Justus Dieckmann <45795270+justusdieckmann@users.noreply.github.com> Co-authored-by: Melanie Treitinger <66598405+melanietreitinger@users.noreply.github.com> Co-authored-by: KerstinSc Co-authored-by: Kata <35190838+olivabigyo@users.noreply.github.com> --- .github/workflows/moodle-ci.yml | 77 ++-- .github/workflows/moodle-release.yml | 11 +- README.md | 9 +- activeprocesses.php | 1 + activeworkflows.php | 2 +- classes/event/process_proceeded.php | 10 +- classes/event/process_rollback.php | 10 +- classes/event/process_triggered.php | 10 +- .../backup/backup_lifecycle_workflow.php | 20 +- .../backup/restore_lifecycle_workflow.php | 50 ++- classes/local/form/form_courses_filter.php | 4 +- classes/local/form/form_delays_filter.php | 2 +- classes/local/form/form_step_instance.php | 4 +- classes/local/form/form_trigger_instance.php | 7 +- classes/local/form/form_upload_workflow.php | 8 +- classes/local/manager/backup_manager.php | 6 +- .../local/manager/delayed_courses_manager.php | 16 +- .../local/manager/process_data_manager.php | 8 +- classes/local/manager/process_manager.php | 14 +- classes/local/manager/settings_manager.php | 14 +- classes/local/manager/step_manager.php | 34 +- classes/local/manager/trigger_manager.php | 28 +- classes/local/manager/workflow_manager.php | 63 ++- .../table/active_manual_workflows_table.php | 2 +- .../local/table/active_processes_table.php | 2 +- .../local/table/active_workflows_table.php | 18 +- classes/local/table/course_backups_table.php | 6 +- classes/local/table/courses_in_step_table.php | 2 +- .../table/deactivated_workflows_table.php | 18 +- classes/local/table/delayed_courses_table.php | 16 +- .../table/interaction_attention_table.php | 8 +- .../table/interaction_remaining_table.php | 8 +- classes/local/table/process_errors_table.php | 8 +- .../local/table/workflow_definition_table.php | 10 +- classes/local/table/workflow_table.php | 18 +- classes/privacy/provider.php | 16 +- classes/processor.php | 4 +- classes/task/lifecycle_cleanup_task.php | 4 +- classes/task/lifecycle_error_notify_task.php | 2 +- classes/task/lifecycle_task.php | 2 +- classes/view_controller.php | 4 +- coursebackups.php | 1 + db/access.php | 14 +- db/caches.php | 15 +- db/events.php | 8 +- db/tasks.php | 16 +- db/upgrade.php | 39 +- delayedcourses.php | 8 +- downloadbackup.php | 3 +- editelement.php | 2 +- lang/de/tool_lifecycle.php | 337 +++++++-------- lang/en/tool_lifecycle.php | 400 ++++++++---------- lib.php | 23 +- renderer.php | 8 +- restore.php | 1 + settings.php | 5 + .../createbackup/classes/privacy/provider.php | 2 +- step/createbackup/db/upgrade.php | 2 +- .../lang/de/lifecyclestep_createbackup.php | 2 +- .../lang/en/lifecyclestep_createbackup.php | 2 +- step/createbackup/lib.php | 4 +- .../deletecourse/classes/privacy/provider.php | 2 +- step/deletecourse/db/upgrade.php | 2 +- .../lang/de/lifecyclestep_deletecourse.php | 2 +- .../lang/en/lifecyclestep_deletecourse.php | 2 +- step/deletecourse/lib.php | 4 +- step/duplicate/classes/privacy/provider.php | 2 +- step/duplicate/db/access.php | 14 +- step/duplicate/interactionlib.php | 12 +- .../lang/de/lifecyclestep_duplicate.php | 8 +- .../lang/en/lifecyclestep_duplicate.php | 8 +- step/duplicate/lib.php | 24 +- step/email/classes/privacy/provider.php | 4 +- step/email/db/access.php | 14 +- step/email/interactionlib.php | 8 +- step/email/lang/de/lifecyclestep_email.php | 41 +- step/email/lang/en/lifecyclestep_email.php | 49 ++- step/email/lib.php | 43 +- step/email/tests/privacy/provider_test.php | 10 +- step/lib.php | 12 +- templates/workflowoverview.mustache | 16 +- tests/active_workflow_is_manual_test.php | 8 +- .../active_workflow_sortindex_updown_test.php | 14 +- tests/backup_and_restore_workflow_test.php | 15 +- tests/backup_manager_test.php | 8 +- tests/behat/manual_trigger.feature | 2 +- tests/behat/upload_workflow.feature | 11 + tests/fixtures/simpleworkflow.xml | 15 + tests/generator/lib.php | 10 +- tests/manual_trigger_tools_test.php | 8 +- tests/manually_triggered_process_test.php | 8 +- .../persistence/persist_process_data_test.php | 6 +- tests/persistence/persist_process_test.php | 12 +- tests/persistence/persist_step_test.php | 12 +- tests/persistence/persist_workflow_test.php | 6 +- tests/privacy_test.php | 20 +- tests/process_error_test.php | 8 +- tests/process_status_message_test.php | 6 +- tests/settings_manager_test.php | 26 +- tests/workflow_actions_testcase.php | 2 +- ...rkflow_activate_disable_duplicate_test.php | 12 +- .../categories/classes/privacy/provider.php | 2 +- .../lang/de/lifecycletrigger_categories.php | 6 +- .../lang/en/lifecycletrigger_categories.php | 6 +- trigger/categories/lib.php | 47 +- trigger/categories/tests/trigger_test.php | 20 +- .../classes/privacy/provider.php | 2 +- .../de/lifecycletrigger_delayedcourses.php | 2 +- .../en/lifecycletrigger_delayedcourses.php | 2 +- trigger/delayedcourses/tests/trigger_test.php | 14 +- trigger/lib.php | 13 +- trigger/manual/classes/privacy/provider.php | 2 +- .../lang/de/lifecycletrigger_manual.php | 4 +- .../lang/en/lifecycletrigger_manual.php | 4 +- trigger/manual/lib.php | 2 +- .../sitecourse/classes/privacy/provider.php | 2 +- .../lang/de/lifecycletrigger_sitecourse.php | 2 +- .../lang/en/lifecycletrigger_sitecourse.php | 2 +- trigger/sitecourse/lib.php | 2 +- trigger/sitecourse/tests/trigger_test.php | 8 +- .../specificdate/classes/privacy/provider.php | 2 +- .../lang/de/lifecycletrigger_specificdate.php | 6 +- .../lang/en/lifecycletrigger_specificdate.php | 6 +- trigger/specificdate/lib.php | 16 +- .../classes/privacy/provider.php | 2 +- .../de/lifecycletrigger_startdatedelay.php | 4 +- .../en/lifecycletrigger_startdatedelay.php | 4 +- trigger/startdatedelay/lib.php | 12 +- trigger/startdatedelay/tests/trigger_test.php | 12 +- uploadworkflow.php | 22 +- version.php | 6 +- view.php | 1 + workflowoverview.php | 69 +-- 133 files changed, 1206 insertions(+), 1032 deletions(-) create mode 100644 tests/behat/upload_workflow.feature create mode 100644 tests/fixtures/simpleworkflow.xml diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 8adbd0f6..cc8943b7 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -8,8 +8,8 @@ jobs: strategy: matrix: - php: ['8.0'] - moodle-branch: ['MOODLE_401_STABLE'] + php: ['8.2'] + moodle-branch: ['MOODLE_404_STABLE'] database: ['pgsql'] steps: @@ -17,7 +17,7 @@ jobs: run: docker run -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_HOST_AUTH_METHOD=trust -d postgres:14 - name: Check out repository code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: plugin @@ -28,29 +28,9 @@ jobs: ini-values: max_input_vars=5000 coverage: none - - name: Get composer cache directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Composer cache - uses: actions/cache@v3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - - name: npm cache - uses: actions/cache@v3 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - name: Initialise moodle-plugin-ci run: | - composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3 + 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 sudo locale-gen en_AU.UTF-8 @@ -107,16 +87,21 @@ jobs: strategy: fail-fast: false matrix: - php: ['8.0'] - moodle-branch: ['MOODLE_311_STABLE', 'MOODLE_400_STABLE', 'MOODLE_401_STABLE'] + php: ['8.0', '8.1', '8.2'] + moodle-branch: ['MOODLE_401_STABLE', 'MOODLE_402_STABLE', 'MOODLE_403_STABLE', 'MOODLE_404_STABLE'] database: ['mariadb', 'pgsql'] + exclude: + - php: '8.0' + moodle-branch: 'MOODLE_404_STABLE' + - php: '8.2' + moodle-branch: 'MOODLE_401_STABLE' include: - php: '7.4' - moodle-branch: 'MOODLE_39_STABLE' - database: 'mariadb' - - php: '7.4' - moodle-branch: 'MOODLE_39_STABLE' + moodle-branch: 'MOODLE_401_STABLE' database: 'pgsql' + - php: '7.4' + moodle-branch: 'MOODLE_401_STABLE' + database: 'mariadb' steps: - name: Start MariaDB @@ -128,7 +113,7 @@ jobs: run: docker run -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_HOST_AUTH_METHOD=trust -d postgres:14 - name: Check out repository code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: plugin @@ -139,24 +124,6 @@ jobs: ini-values: max_input_vars=5000 coverage: none - - name: Get composer cache directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - name: Composer cache - uses: actions/cache@v3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - name: npm cache - uses: actions/cache@v3 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - name: Initialise moodle-plugin-ci run: | composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3 @@ -179,3 +146,15 @@ jobs: - name: Behat features if: ${{ always() }} run: moodle-plugin-ci behat --profile chrome --auto-rerun 0 + + # This step allows to upload Behat faildump (screenshots) as workflow artifact, + # so it can be downloaded and inspected. You don't need this step if you + # are not running Behat test. Artifact will be retained for 7 days. + - name: Upload Behat Faildump + if: ${{ failure() && steps.behat.outcome == 'failure' }} + uses: actions/upload-artifact@v4 + with: + name: Behat Faildump (${{ join(matrix.*, ', ') }}) + path: ${{ github.workspace }}/moodledata/behat_dump + retention-days: 7 + if-no-files-found: ignore diff --git a/.github/workflows/moodle-release.yml b/.github/workflows/moodle-release.yml index 8d1c5bab..1e0fa321 100644 --- a/.github/workflows/moodle-release.yml +++ b/.github/workflows/moodle-release.yml @@ -28,10 +28,11 @@ jobs: steps: - name: Call the service function id: add-version + env: + TAGNAME: ${{ github.event.release.tag_name }} + BODY: ${{ github.event.release.body }} + ZIPURL: ${{ github.event.release.zipball_url }} run: | - TAGNAME="${{ github.event.release.tag_name }}" - BODY="${{ github.event.release.body }}" - ZIPURL="${{ github.event.release.zipball_url }}" RESPONSE=$(${CURL} ${ENDPOINT} --data-urlencode "wstoken=${TOKEN}" \ --data-urlencode "wsfunction=${FUNCTION}" \ --data-urlencode "moodlewsrestformat=json" \ @@ -42,9 +43,9 @@ jobs: --data-urlencode "vcstag=${TAGNAME}" \ --data-urlencode "changelogurl=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/commits/${TAGNAME}" \ --data-urlencode "altdownloadurl=${ZIPURL}" \ - --data-urlencode "releasenotes=${BODY}" \ + --data-urlencode "releasenotes=${BODY@Q}" \ --data-urlencode "releasenotesformat=4") - echo "::set-output name=response::${RESPONSE}" + echo "response=${RESPONSE}" >> $GITHUB_OUTPUT - name: Evaluate the response id: evaluate-response env: diff --git a/README.md b/README.md index 8e4c64c3..7c8bf9a2 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,14 @@ Possible use cases are (not limited to): To be adaptable to the needs of different institutions the plugin provides two subplugin types: -**Trigger**: These subplugins control the conditions a course have to meet so that a specific process is started for it. +**Trigger**: These subplugins control the conditions a course must meet so that a specific process is started. **Step**: These subplugins represent atomic, reusable tasks that should be executed for a specific course. +## Subplugins Requirements that are specific to your institution can be added through additional subplugins. -For more information please have a look at the [wiki](https://github.com/learnweb/moodle-tool_lifecycle/wiki). -It provides instructions for administrators as well as for developers to implement own requirements into subplugins. +A list of all subplugins and more information can be found in the [Wiki](https://github.com/learnweb/moodle-tool_lifecycle/wiki/List-of-Additional-Subplugins) ([subpluginslist](https://github.com/learnweb/moodle-tool_lifecycle/wiki/List-of-Additional-Subplugins)). +It provides instructions for administrators as well as for developers to implement their own requirements into subplugins. Installation ============ @@ -31,7 +32,7 @@ Moodle version ============== The plugin is continously tested with all moodle versions, which are security supported by the moodle headquarter. Therefore, Travis uses the most current release to build a test instance and run the behat and unit tests on them. -In addition to all stable branches the version is also tested against the master branch to support early adopters. +In addition to all stable branches the version is tested against the master branch to support early adopters. Changelog ========= diff --git a/activeprocesses.php b/activeprocesses.php index 7efdd38d..1f49b72b 100644 --- a/activeprocesses.php +++ b/activeprocesses.php @@ -21,6 +21,7 @@ * @copyright 2017 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + require_once(__DIR__ . '/../../../config.php'); require_once($CFG->libdir . '/adminlib.php'); require_login(); diff --git a/activeworkflows.php b/activeworkflows.php index 9ce9c0a2..aca0133d 100644 --- a/activeworkflows.php +++ b/activeworkflows.php @@ -56,7 +56,7 @@ 'inputname' => 'search', 'extraclasses' => 'mb-3', 'inform' => false, - 'searchstring' => 'Search for courses' + 'searchstring' => 'Search for courses', ]); echo $OUTPUT->heading(get_string('active_automatic_workflows_heading', 'tool_lifecycle')); diff --git a/classes/event/process_proceeded.php b/classes/event/process_proceeded.php index c3c9ac93..5aada6de 100644 --- a/classes/event/process_proceeded.php +++ b/classes/event/process_proceeded.php @@ -53,15 +53,15 @@ class process_proceeded extends \core\event\base { * @throws \dml_exception */ public static function event_from_process($process) { - $data = array( + $data = [ 'context' => \context_system::instance(), - 'other' => array( + 'other' => [ 'processid' => $process->id, 'workflowid' => $process->workflowid, 'stepindex' => $process->stepindex, - 'courseid' => $process->courseid - ) - ); + 'courseid' => $process->courseid, + ], + ]; return self::create($data); } diff --git a/classes/event/process_rollback.php b/classes/event/process_rollback.php index 5fadca09..cafc1031 100644 --- a/classes/event/process_rollback.php +++ b/classes/event/process_rollback.php @@ -53,15 +53,15 @@ class process_rollback extends \core\event\base { * @throws \dml_exception */ public static function event_from_process($process) { - $data = array( + $data = [ 'context' => \context_system::instance(), - 'other' => array( + 'other' => [ 'processid' => $process->id, 'workflowid' => $process->workflowid, 'stepindex' => $process->stepindex, - 'courseid' => $process->courseid - ) - ); + 'courseid' => $process->courseid, + ], + ]; return self::create($data); } diff --git a/classes/event/process_triggered.php b/classes/event/process_triggered.php index 0648b501..a71507ad 100644 --- a/classes/event/process_triggered.php +++ b/classes/event/process_triggered.php @@ -52,14 +52,14 @@ class process_triggered extends \core\event\base { * @throws \dml_exception */ public static function event_from_process($process) { - $data = array( + $data = [ 'context' => \context_system::instance(), - 'other' => array( + 'other' => [ 'processid' => $process->id, 'workflowid' => $process->workflowid, - 'courseid' => $process->courseid - ) - ); + 'courseid' => $process->courseid, + ], + ]; return self::create($data); } diff --git a/classes/local/backup/backup_lifecycle_workflow.php b/classes/local/backup/backup_lifecycle_workflow.php index 743a0561..2e768894 100644 --- a/classes/local/backup/backup_lifecycle_workflow.php +++ b/classes/local/backup/backup_lifecycle_workflow.php @@ -107,7 +107,9 @@ public function send_temp_file() { */ private function write_workflow() { foreach (get_object_vars($this->workflow) as $prop => $value) { - $this->writer->writeAttribute($prop, $value); + if (!is_null($value)) { + $this->writer->writeAttribute($prop, $value); + } } } @@ -118,13 +120,17 @@ private function write_triggers() { foreach ($this->trigger as $trigger) { $this->writer->startElement("trigger"); foreach (get_object_vars($trigger) as $prop => $value) { - $this->writer->writeAttribute($prop, $value); + if (!is_null($value)) { + $this->writer->writeAttribute($prop, $value); + } } $settings = settings_manager::get_settings($trigger->id, settings_type::TRIGGER); foreach ($settings as $name => $value) { $this->writer->startElement("setting"); $this->writer->writeAttribute('name', $name); - $this->writer->writeAttribute('value', $value); + if (!is_null($value)) { + $this->writer->writeAttribute('value', $value); + } $this->writer->endElement(); } $this->writer->endElement(); @@ -139,13 +145,17 @@ private function write_steps() { foreach ($this->steps as $step) { $this->writer->startElement("step"); foreach (get_object_vars($step) as $prop => $value) { - $this->writer->writeAttribute($prop, $value); + if (!is_null($value)) { + $this->writer->writeAttribute($prop, $value); + } } $settings = settings_manager::get_settings($step->id, settings_type::STEP); foreach ($settings as $name => $value) { $this->writer->startElement("setting"); $this->writer->writeAttribute('name', $name); - $this->writer->writeAttribute('value', $value); + if (!is_null($value)) { + $this->writer->writeAttribute('value', $value); + } $this->writer->endElement(); } $this->writer->endElement(); diff --git a/classes/local/backup/restore_lifecycle_workflow.php b/classes/local/backup/restore_lifecycle_workflow.php index 1cb3ff1c..5e9b1fe9 100644 --- a/classes/local/backup/restore_lifecycle_workflow.php +++ b/classes/local/backup/restore_lifecycle_workflow.php @@ -25,6 +25,7 @@ use tool_lifecycle\local\entity\step_subplugin; use tool_lifecycle\local\entity\trigger_subplugin; use tool_lifecycle\local\entity\workflow; +use tool_lifecycle\local\manager\lib_manager; use tool_lifecycle\local\manager\workflow_manager; use tool_lifecycle\local\manager\step_manager; use tool_lifecycle\local\manager\trigger_manager; @@ -59,27 +60,35 @@ class restore_lifecycle_workflow { public function __construct($xmldata) { $this->reader = new \XMLReader(); $this->reader->XML($xmldata); - } /** * Executes the restore process. It loads the workflow with all steps and triggers from the xml data. * If all data is valid, it restores the workflow with all subplugins and settings. * Otherwise an array with error strings is returned. + * @param bool $force force import, even if there are errors. * @return string[] Errors, which occurred during the restore process. * @throws \coding_exception * @throws \moodle_exception */ - public function execute() { + public function execute(bool $force = false) { $this->reader->read(); $this->load_workflow(); // If the workflow could be loaded continue with the subplugins. if ($this->workflow) { $this->load_subplugins(); + + if (!$this->all_subplugins_installed()) { + return $this->errors; + } + // Validate the subplugin data. - if (empty($this->errors) && $this->all_subplugins_installed()) { + $this->check_subplugin_validity(); + if (empty($this->errors) || $force) { // If all loaded data is valid, the new workflow and the steps can be stored in the database. + // If we force the import, we empty the errors; + $this->errors = []; $this->persist(); } } @@ -174,6 +183,41 @@ private function all_subplugins_installed() { return true; } + /** + * Calls the subplugins to check the consistency and validity of the step and trigger settings. + */ + private function check_subplugin_validity() { + foreach ($this->steps as $step) { + $steplib = lib_manager::get_step_lib($step->subpluginname); + $filteredsettings = []; + foreach ($this->settings as $setting) { + if ($setting->pluginid === $step->id) { + $filteredsettings[$setting->name] = $setting->value; + } + } + $errors = array_map( + fn($x) => get_string('restore_error_in_step', 'tool_lifecycle', $step->instancename) . $x, + $steplib->ensure_validity($filteredsettings) + ); + $this->errors = array_merge($this->errors, $errors); + } + + foreach ($this->trigger as $trigger) { + $steplib = lib_manager::get_trigger_lib($trigger->subpluginname); + $filteredsettings = []; + foreach ($this->settings as $setting) { + if ($setting->pluginid === $trigger->id) { + $filteredsettings[$setting->name] = $setting->value; + } + } + $errors = array_map( + fn($x) => get_string('restore_error_in_trigger', 'tool_lifecycle', $trigger->instancename) . $x, + $steplib->ensure_validity($filteredsettings) + ); + $this->errors = array_merge($this->errors, $errors); + } + } + /** * Stores all loaded data in the database. * @throws \moodle_exception diff --git a/classes/local/form/form_courses_filter.php b/classes/local/form/form_courses_filter.php index f589bcea..a7b52ba9 100644 --- a/classes/local/form/form_courses_filter.php +++ b/classes/local/form/form_courses_filter.php @@ -53,11 +53,11 @@ public function definition() { $mform->setType('fullname', PARAM_TEXT); // Edited from $this->add_action_buttons to allow custom cancel text. - $buttonarray = array(); + $buttonarray = []; $buttonarray[] = &$mform->createElement('submit', 'submitbutton', get_string('apply', 'tool_lifecycle')); $buttonarray[] = &$mform->createElement('cancel', 'cancel', get_string('reset')); - $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false); + $mform->addGroup($buttonarray, 'buttonar', '', [' '], false); $mform->closeHeaderBefore('buttonar'); } diff --git a/classes/local/form/form_delays_filter.php b/classes/local/form/form_delays_filter.php index 845e2163..3abcf120 100644 --- a/classes/local/form/form_delays_filter.php +++ b/classes/local/form/form_delays_filter.php @@ -48,7 +48,7 @@ public function definition() { $activeworkflows = workflow_manager::get_active_workflows(); $workflowoptions = [ '' => get_string('all_delays', 'tool_lifecycle'), - 'global' => get_string('globally', 'tool_lifecycle') + 'global' => get_string('globally', 'tool_lifecycle'), ]; foreach ($activeworkflows as $activeworkflow) { // Only show non-static workflows. diff --git a/classes/local/form/form_step_instance.php b/classes/local/form/form_step_instance.php index f080413d..647df64c 100644 --- a/classes/local/form/form_step_instance.php +++ b/classes/local/form/form_step_instance.php @@ -139,9 +139,9 @@ private function add_cancel_button() { $mform =& $this->_form; // Add a group 'buttonar' to allow excluding it from freezing. - $buttonarray = array(); + $buttonarray = []; $buttonarray[] = &$mform->createElement('cancel'); - $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false); + $mform->addGroup($buttonarray, 'buttonar', '', [' '], false); $mform->closeHeaderBefore('buttonar'); } diff --git a/classes/local/form/form_trigger_instance.php b/classes/local/form/form_trigger_instance.php index 0ac8f901..3646a6af 100644 --- a/classes/local/form/form_trigger_instance.php +++ b/classes/local/form/form_trigger_instance.php @@ -144,9 +144,9 @@ public function definition() { private function add_cancel_button() { $mform =& $this->_form; - $buttonarray = array(); + $buttonarray = []; $buttonarray[] = &$mform->createElement('cancel'); - $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false); + $mform->addGroup($buttonarray, 'buttonar', '', [' '], false); $mform->closeHeaderBefore('buttonar'); } @@ -191,7 +191,8 @@ public function definition_after_data() { } } - /** Validate the form. + /** + * Validate the form. * @param array $data array of ("fieldname"=>value) of submitted data * @param array $files array of uploaded files "element_name"=>tmp_file_path * @return array of "element_name"=>"error_description" if there are errors, diff --git a/classes/local/form/form_upload_workflow.php b/classes/local/form/form_upload_workflow.php index 5ce328c7..ee30d441 100644 --- a/classes/local/form/form_upload_workflow.php +++ b/classes/local/form/form_upload_workflow.php @@ -42,7 +42,13 @@ public function definition() { $mform = $this->_form; $mform->addElement('filepicker', 'backupfile', get_string('file'), null, - array('accepted_types' => 'xml')); + ['accepted_types' => 'xml']); + + $showforce = isset($this->_customdata['showforce']) && $this->_customdata['showforce']; + $mform->addElement($showforce ? 'checkbox' : 'hidden', 'force', get_string('force_import', 'tool_lifecycle')); + $mform->setDefault('force', 0); + $mform->setType('force', PARAM_BOOL); + $this->add_action_buttons('true', get_string('upload')); } diff --git a/classes/local/manager/backup_manager.php b/classes/local/manager/backup_manager.php index f7752b45..4ad70e31 100644 --- a/classes/local/manager/backup_manager.php +++ b/classes/local/manager/backup_manager.php @@ -102,7 +102,7 @@ public static function create_course_backup($courseid) { */ public static function restore_course_backup($backupid) { global $DB, $CFG; - $backuprecord = $DB->get_record('tool_lifecycle_backups', array('id' => $backupid)); + $backuprecord = $DB->get_record('tool_lifecycle_backups', ['id' => $backupid]); // Check if backup tmp dir exists. $backuptmpdir = $CFG->tempdir . DIRECTORY_SEPARATOR . 'backup'; @@ -125,10 +125,10 @@ public static function restore_course_backup($backupid) { $context = \context_system::instance(); $restoreurl = new \moodle_url('/backup/restore.php', - array( + [ 'contextid' => $context->id, 'filename' => $targetfilename, - ) + ] ); redirect($restoreurl); diff --git a/classes/local/manager/delayed_courses_manager.php b/classes/local/manager/delayed_courses_manager.php index b2520a9b..37d112f5 100644 --- a/classes/local/manager/delayed_courses_manager.php +++ b/classes/local/manager/delayed_courses_manager.php @@ -60,7 +60,7 @@ public static function set_course_delayed_for_workflow($courseid, $becauserollba } else { $delayeduntil = time() + $duration; $record = $DB->get_record('tool_lifecycle_delayed_workf', - array('courseid' => $courseid, 'workflowid' => $workflow->id)); + ['courseid' => $courseid, 'workflowid' => $workflow->id]); if (!$record) { $record = new \stdClass(); $record->courseid = $courseid; @@ -86,7 +86,7 @@ public static function set_course_delayed_for_workflow($courseid, $becauserollba public static function get_delayed_courses_for_workflow($workflowid) { global $DB; $sql = 'SELECT courseid FROM {tool_lifecycle_delayed_workf} WHERE delayeduntil > :now AND workflowid = :workflowid'; - return $DB->get_fieldset_sql($sql, array('now' => time(), 'workflowid' => $workflowid)); + return $DB->get_fieldset_sql($sql, ['now' => time(), 'workflowid' => $workflowid]); } /** @@ -98,7 +98,7 @@ public static function get_delayed_courses_for_workflow($workflowid) { public static function set_course_delayed($courseid, $duration) { global $DB; $delayeduntil = time() + $duration; - $record = $DB->get_record('tool_lifecycle_delayed', array('courseid' => $courseid)); + $record = $DB->get_record('tool_lifecycle_delayed', ['courseid' => $courseid]); if (!$record) { $record = new \stdClass(); $record->courseid = $courseid; @@ -120,7 +120,7 @@ public static function set_course_delayed($courseid, $duration) { */ public static function get_course_delayed($courseid) { global $DB; - $record = $DB->get_record('tool_lifecycle_delayed', array('courseid' => $courseid)); + $record = $DB->get_record('tool_lifecycle_delayed', ['courseid' => $courseid]); if ($record) { return $record->delayeduntil; } else { @@ -134,8 +134,8 @@ public static function get_course_delayed($courseid) { */ public static function get_course_delayed_wheresql() { $where = "{course}.id IN (SELECT courseid FROM {tool_lifecycle_delayed} WHERE delayeduntil > :now)"; - $params = array("now" => time()); - return array($where, $params); + $params = ["now" => time()]; + return [$where, $params]; } /** @@ -146,7 +146,7 @@ public static function get_course_delayed_wheresql() { public static function get_globally_delayed_courses() { global $DB; $sql = 'SELECT courseid FROM {tool_lifecycle_delayed} WHERE delayeduntil > :now'; - return $DB->get_fieldset_sql($sql, array('now' => time())); + return $DB->get_fieldset_sql($sql, ['now' => time()]); } /** @@ -156,6 +156,6 @@ public static function get_globally_delayed_courses() { */ public static function remove_delay_entry($courseid) { global $DB; - $DB->delete_records('tool_lifecycle_delayed', array('courseid' => $courseid)); + $DB->delete_records('tool_lifecycle_delayed', ['courseid' => $courseid]); } } diff --git a/classes/local/manager/process_data_manager.php b/classes/local/manager/process_data_manager.php index 722e2a6a..ce06ae64 100644 --- a/classes/local/manager/process_data_manager.php +++ b/classes/local/manager/process_data_manager.php @@ -53,10 +53,10 @@ class process_data_manager { */ public static function get_process_data($processid, $stepid, $key) { global $DB; - $params = array( + $params = [ 'processid' => $processid, 'keyname' => $key, - ); + ]; if (step_manager::is_process_data_instance_dependent($stepid)) { $params['stepid'] = $stepid; } else { @@ -78,10 +78,10 @@ public static function get_process_data($processid, $stepid, $key) { */ public static function set_process_data($processid, $stepid, $key, $value) { global $DB; - $entry = array( + $entry = [ 'processid' => $processid, 'keyname' => $key, - ); + ]; if (step_manager::is_process_data_instance_dependent($stepid)) { $entry['stepid'] = $stepid; } else { diff --git a/classes/local/manager/process_manager.php b/classes/local/manager/process_manager.php index b0b92039..ca92f0de 100644 --- a/classes/local/manager/process_manager.php +++ b/classes/local/manager/process_manager.php @@ -88,7 +88,7 @@ public static function manually_trigger_process($courseid, $triggerid) { public static function get_processes() { global $DB; $records = $DB->get_records('tool_lifecycle_process'); - $processes = array(); + $processes = []; foreach ($records as $record) { $processes[] = process::from_record($record); } @@ -103,7 +103,7 @@ public static function get_processes() { */ public static function get_process_by_id($processid) { global $DB; - $record = $DB->get_record('tool_lifecycle_process', array('id' => $processid)); + $record = $DB->get_record('tool_lifecycle_process', ['id' => $processid]); if ($record) { return process::from_record($record); } else { @@ -119,7 +119,7 @@ public static function get_process_by_id($processid) { */ public static function count_processes_by_workflow($workflowid) { global $DB; - return $DB->count_records('tool_lifecycle_process', array('workflowid' => $workflowid)); + return $DB->count_records('tool_lifecycle_process', ['workflowid' => $workflowid]); } /** @@ -130,8 +130,8 @@ public static function count_processes_by_workflow($workflowid) { */ public static function get_processes_by_workflow($workflowid) { global $DB; - $records = $DB->get_records('tool_lifecycle_process', array('workflowid' => $workflowid)); - $processes = array(); + $records = $DB->get_records('tool_lifecycle_process', ['workflowid' => $workflowid]); + $processes = []; foreach ($records as $record) { $processes[] = process::from_record($record); } @@ -201,7 +201,7 @@ public static function rollback_process($process) { */ private static function remove_process($process) { global $DB; - $DB->delete_records('tool_lifecycle_procdata', array('processid' => $process->id)); + $DB->delete_records('tool_lifecycle_procdata', ['processid' => $process->id]); $DB->delete_records('tool_lifecycle_process', (array) $process); } @@ -213,7 +213,7 @@ private static function remove_process($process) { */ public static function get_process_by_course_id($courseid) { global $DB; - $record = $DB->get_record('tool_lifecycle_process', array('courseid' => $courseid)); + $record = $DB->get_record('tool_lifecycle_process', ['courseid' => $courseid]); if ($record) { return process::from_record($record); } else { diff --git a/classes/local/manager/settings_manager.php b/classes/local/manager/settings_manager.php index 4db7be7e..6f0aade4 100644 --- a/classes/local/manager/settings_manager.php +++ b/classes/local/manager/settings_manager.php @@ -109,10 +109,10 @@ public static function save_settings($instanceid, $type, $subpluginname, $data, $cleanedvalue = clean_param($value, $setting->paramtype); } $record = $DB->get_record('tool_lifecycle_settings', - array( + [ 'instanceid' => $instanceid, 'type' => $type, - 'name' => $setting->name) + 'name' => $setting->name, ] ); if ($record) { if ($record->value != $cleanedvalue) { @@ -164,11 +164,11 @@ public static function get_settings($instanceid, $type) { $lib = lib_manager::get_step_lib($instance->subpluginname); } - $settingsvalues = array(); + $settingsvalues = []; foreach ($lib->instance_settings() as $setting) { - $record = $DB->get_record('tool_lifecycle_settings', array('instanceid' => $instanceid, + $record = $DB->get_record('tool_lifecycle_settings', ['instanceid' => $instanceid, 'type' => $type, - 'name' => $setting->name)); + 'name' => $setting->name, ]); if ($record) { $value = clean_param($record->value, $setting->paramtype); $settingsvalues[$setting->name] = $value; @@ -189,8 +189,8 @@ public static function remove_settings($instanceid, $type) { self::validate_type($type); $DB->delete_records('tool_lifecycle_settings', - array('instanceid' => $instanceid, - 'type' => $type)); + ['instanceid' => $instanceid, + 'type' => $type, ]); } /** diff --git a/classes/local/manager/step_manager.php b/classes/local/manager/step_manager.php index cd58d1a5..3158cd40 100644 --- a/classes/local/manager/step_manager.php +++ b/classes/local/manager/step_manager.php @@ -44,7 +44,7 @@ class step_manager extends subplugin_manager { */ public static function get_step_instance($stepinstanceid) { global $DB; - $record = $DB->get_record('tool_lifecycle_step', array('id' => $stepinstanceid)); + $record = $DB->get_record('tool_lifecycle_step', ['id' => $stepinstanceid]); if ($record) { $subplugin = step_subplugin::from_record($record); return $subplugin; @@ -63,9 +63,9 @@ public static function get_step_instance($stepinstanceid) { public static function get_step_instance_by_workflow_index($workflowid, $sortindex) { global $DB; $record = $DB->get_record('tool_lifecycle_step', - array( + [ 'workflowid' => $workflowid, - 'sortindex' => $sortindex) + 'sortindex' => $sortindex, ] ); if ($record) { $subplugin = step_subplugin::from_record($record); @@ -118,7 +118,7 @@ public static function remove_all_instances($subpluginname) { private static function remove($stepinstanceid) { global $DB; $transaction = $DB->start_delegated_transaction(); - if ($record = $DB->get_record('tool_lifecycle_step', array('id' => $stepinstanceid))) { + if ($record = $DB->get_record('tool_lifecycle_step', ['id' => $stepinstanceid])) { $step = step_subplugin::from_record($record); self::remove_from_sortindex($step); settings_manager::remove_settings($step->id, settings_type::STEP); @@ -137,8 +137,8 @@ private static function remove_from_sortindex(&$toberemoved) { global $DB; if (isset($toberemoved->sortindex)) { $subplugins = $DB->get_records_select('tool_lifecycle_step', - "sortindex > $toberemoved->sortindex", - array('workflowid' => $toberemoved->workflowid)); + 'workflowid = :workflowid AND sortindex > :sortindex', + ['workflowid' => $toberemoved->workflowid, 'sortindex' => $toberemoved->sortindex]); foreach ($subplugins as $record) { $subplugin = step_subplugin::from_record($record); $subplugin->sortindex--; @@ -174,9 +174,9 @@ public static function change_sortindex($stepid, $up) { $transaction = $DB->start_delegated_transaction(); $otherrecord = $DB->get_record('tool_lifecycle_step', - array( + [ 'sortindex' => $otherindex, - 'workflowid' => $step->workflowid) + 'workflowid' => $step->workflowid, ] ); $otherstep = step_subplugin::from_record($otherrecord); @@ -196,10 +196,10 @@ public static function change_sortindex($stepid, $up) { */ public static function get_step_instances($workflowid) { global $DB; - $records = $DB->get_records('tool_lifecycle_step', array( - 'workflowid' => $workflowid - ), 'sortindex'); - $steps = array(); + $records = $DB->get_records('tool_lifecycle_step', [ + 'workflowid' => $workflowid, + ], 'sortindex'); + $steps = []; foreach ($records as $id => $record) { $steps[$id] = step_subplugin::from_record($record); } @@ -214,8 +214,8 @@ public static function get_step_instances($workflowid) { */ public static function get_step_instances_by_subpluginname($subpluginname) { global $DB; - $records = $DB->get_records('tool_lifecycle_step', array('subpluginname' => $subpluginname)); - $steps = array(); + $records = $DB->get_records('tool_lifecycle_step', ['subpluginname' => $subpluginname]); + $steps = []; foreach ($records as $id => $record) { $steps[$id] = step_subplugin::from_record($record); } @@ -229,7 +229,7 @@ public static function get_step_instances_by_subpluginname($subpluginname) { */ public static function get_step_types() { $subplugins = \core_component::get_plugin_list('lifecyclestep'); - $result = array(); + $result = []; foreach (array_keys($subplugins) as $plugin) { $result[$plugin] = get_string('pluginname', 'lifecyclestep_' . $plugin); } @@ -291,7 +291,7 @@ public static function is_process_data_instance_dependent($stepid) { public static function count_steps_of_workflow($workflowid) { global $DB; return $DB->count_records('tool_lifecycle_step', - array('workflowid' => $workflowid) + ['workflowid' => $workflowid] ); } @@ -307,7 +307,7 @@ public static function remove_instances_of_workflow($workflowid) { foreach ($instances as $instance) { settings_manager::remove_settings($instance->id, settings_type::STEP); } - $DB->delete_records('tool_lifecycle_step', array('workflowid' => $workflowid)); + $DB->delete_records('tool_lifecycle_step', ['workflowid' => $workflowid]); } /** diff --git a/classes/local/manager/trigger_manager.php b/classes/local/manager/trigger_manager.php index dc33b086..656d4233 100644 --- a/classes/local/manager/trigger_manager.php +++ b/classes/local/manager/trigger_manager.php @@ -74,8 +74,8 @@ public static function get_instance($instanceid) { */ public static function get_instances($subpluginname) { global $DB; - $result = array(); - $records = $DB->get_records('tool_lifecycle_trigger', array('subpluginname' => $subpluginname)); + $result = []; + $records = $DB->get_records('tool_lifecycle_trigger', ['subpluginname' => $subpluginname]); foreach ($records as $record) { $subplugin = trigger_subplugin::from_record($record); $result[] = $subplugin; @@ -91,7 +91,7 @@ public static function get_instances($subpluginname) { */ private static function get_subplugin_by_id($subpluginid) { global $DB; - $record = $DB->get_record('tool_lifecycle_trigger', array('id' => $subpluginid)); + $record = $DB->get_record('tool_lifecycle_trigger', ['id' => $subpluginid]); if ($record) { $subplugin = trigger_subplugin::from_record($record); return $subplugin; @@ -142,7 +142,7 @@ public static function remove_all_instances($subpluginname) { private static function remove($triggerinstanceid) { global $DB; $transaction = $DB->start_delegated_transaction(); - if ($record = $DB->get_record('tool_lifecycle_trigger', array('id' => $triggerinstanceid))) { + if ($record = $DB->get_record('tool_lifecycle_trigger', ['id' => $triggerinstanceid])) { $trigger = trigger_subplugin::from_record($record); self::remove_from_sortindex($trigger); settings_manager::remove_settings($trigger->id, settings_type::TRIGGER); @@ -160,8 +160,8 @@ private static function remove($triggerinstanceid) { */ public static function get_triggers_for_workflow($workflowid) { global $DB; - $records = $DB->get_records('tool_lifecycle_trigger', array('workflowid' => $workflowid), 'sortindex'); - $output = array(); + $records = $DB->get_records('tool_lifecycle_trigger', ['workflowid' => $workflowid], 'sortindex'); + $output = []; foreach ($records as $record) { $subplugin = trigger_subplugin::from_record($record); $output[] = $subplugin; @@ -179,8 +179,8 @@ private static function remove_from_sortindex(&$toberemoved) { global $DB; if (isset($toberemoved->sortindex)) { $subplugins = $DB->get_records_select('tool_lifecycle_trigger', - "sortindex > $toberemoved->sortindex", - array('workflowid' => $toberemoved->workflowid)); + 'workflowid = :workflowid AND sortindex > :sortindex', + ['workflowid' => $toberemoved->workflowid, 'sortindex' => $toberemoved->sortindex]); foreach ($subplugins as $record) { $subplugin = trigger_subplugin::from_record($record); $subplugin->sortindex--; @@ -216,9 +216,9 @@ public static function change_sortindex($triggerid, $up) { $transaction = $DB->start_delegated_transaction(); $otherrecord = $DB->get_record('tool_lifecycle_trigger', - array( + [ 'sortindex' => $otherindex, - 'workflowid' => $trigger->workflowid) + 'workflowid' => $trigger->workflowid, ] ); $othertrigger = trigger_subplugin::from_record($otherrecord); @@ -237,7 +237,7 @@ public static function change_sortindex($triggerid, $up) { */ public static function get_trigger_types() { $subplugins = \core_component::get_plugin_list('lifecycletrigger'); - $result = array(); + $result = []; foreach (array_keys($subplugins) as $plugin) { $result[$plugin] = get_string('pluginname', 'lifecycletrigger_' . $plugin); } @@ -251,7 +251,7 @@ public static function get_trigger_types() { */ public static function get_chooseable_trigger_types() { $triggers = self::get_trigger_types(); - $result = array(); + $result = []; foreach ($triggers as $id => $trigger) { $lib = lib_manager::get_trigger_lib($id); if ($lib->has_multiple_instances()) { @@ -300,7 +300,7 @@ public static function handle_action($action, $subpluginid, $workflowid) { public static function count_triggers_of_workflow($workflowid) { global $DB; return $DB->count_records('tool_lifecycle_trigger', - array('workflowid' => $workflowid) + ['workflowid' => $workflowid] ); } @@ -316,7 +316,7 @@ public static function remove_instances_of_workflow($workflowid) { foreach ($instances as $instance) { settings_manager::remove_settings($instance->id, settings_type::TRIGGER); } - $DB->delete_records('tool_lifecycle_trigger', array('workflowid' => $workflowid)); + $DB->delete_records('tool_lifecycle_trigger', ['workflowid' => $workflowid]); } /** diff --git a/classes/local/manager/workflow_manager.php b/classes/local/manager/workflow_manager.php index 9a107aa1..4d395090 100644 --- a/classes/local/manager/workflow_manager.php +++ b/classes/local/manager/workflow_manager.php @@ -55,6 +55,7 @@ public static function insert_or_update(workflow &$workflow) { $workflow->id = $DB->insert_record('tool_lifecycle_workflow', $workflow); } $transaction->allow_commit(); + return $workflow->id; } /** @@ -67,9 +68,11 @@ public static function insert_or_update(workflow &$workflow) { public static function remove($workflowid, $hard = false) { global $DB; if ($hard || self::is_removable($workflowid)) { + $workflow = self::get_workflow($workflowid); + self::remove_from_sortindex($workflow); trigger_manager::remove_instances_of_workflow($workflowid); step_manager::remove_instances_of_workflow($workflowid); - $DB->delete_records('tool_lifecycle_workflow', array('id' => $workflowid)); + $DB->delete_records('tool_lifecycle_workflow', ['id' => $workflowid]); } } @@ -81,12 +84,36 @@ public static function remove($workflowid, $hard = false) { * @throws \dml_transaction_exception */ public static function disable($workflowid) { + global $DB; + $transaction = $DB->start_delegated_transaction(); $workflow = self::get_workflow($workflowid); if ($workflow && self::is_disableable($workflowid)) { $workflow->timeactive = null; + self::remove_from_sortindex($workflow); $workflow->sortindex = null; $workflow->timedeactive = time(); - self::insert_or_update($workflow); + $DB->update_record('tool_lifecycle_workflow', $workflow); + } + $transaction->allow_commit(); + } + + /** + * Removes a workflow from the sortindex. + * + * @param workflow $toberemoved + * @throws \dml_exception + * @throws \dml_transaction_exception + */ + public static function remove_from_sortindex($toberemoved) { + global $DB; + if (isset($toberemoved->sortindex)) { + $workflows = self::get_active_automatic_workflows(); + foreach ($workflows as $workflow) { + if ($workflow->sortindex > $toberemoved->sortindex) { + $workflow->sortindex--; + $DB->update_record('tool_lifecycle_workflow', $workflow); + } + } } } @@ -113,7 +140,7 @@ public static function abortprocesses($workflowid) { */ public static function get_workflow($workflowid) { global $DB; - $record = $DB->get_record('tool_lifecycle_workflow', array('id' => $workflowid)); + $record = $DB->get_record('tool_lifecycle_workflow', ['id' => $workflowid]); if ($record) { $workflow = workflow::from_record($record); return $workflow; @@ -130,7 +157,7 @@ public static function get_workflow($workflowid) { */ public static function get_workflows() { global $DB; - $result = array(); + $result = []; $records = $DB->get_records('tool_lifecycle_workflow'); foreach ($records as $record) { $result[] = workflow::from_record($record); @@ -149,7 +176,7 @@ public static function get_active_workflows() { $records = $DB->get_records_sql( 'SELECT * FROM {tool_lifecycle_workflow} WHERE timeactive IS NOT NULL ORDER BY sortindex'); - $result = array(); + $result = []; foreach ($records as $record) { $result[] = workflow::from_record($record); } @@ -167,8 +194,8 @@ public static function get_active_automatic_workflows() { $records = $DB->get_records_sql( 'SELECT * FROM {tool_lifecycle_workflow} WHERE timeactive IS NOT NULL AND - manual = ? ORDER BY sortindex', array(false)); - $result = array(); + manual = ? ORDER BY sortindex', [false]); + $result = []; foreach ($records as $record) { $result[] = workflow::from_record($record); } @@ -185,8 +212,8 @@ public static function get_active_manual_workflow_triggers() { global $DB; $sql = 'SELECT t.* FROM {tool_lifecycle_workflow} w JOIN {tool_lifecycle_trigger} t ON t.workflowid = w.id' . ' WHERE w.timeactive IS NOT NULL AND w.manual = ?'; - $records = $DB->get_records_sql($sql, array(true)); - $result = array(); + $records = $DB->get_records_sql($sql, [true]); + $result = []; foreach ($records as $record) { $result[] = trigger_subplugin::from_record($record); } @@ -203,7 +230,7 @@ public static function get_active_manual_workflow_triggers() { */ public static function get_manual_trigger_tools_for_active_workflows() { $triggers = self::get_active_manual_workflow_triggers(); - $tools = array(); + $tools = []; foreach ($triggers as $trigger) { $settings = settings_manager::get_settings($trigger->id, settings_type::TRIGGER); $tools[] = new manual_trigger_tool($trigger->id, $settings['icon'], $settings['displayname'], $settings['capability']); @@ -243,6 +270,14 @@ public static function activate_workflow($workflowid) { $transaction->allow_commit(); } + /** + * Resets the 'does a manual workflow exist?'-cache. + */ + private static function reset_has_workflow_cache() { + $cache = \cache::make('tool_lifecycle', 'application'); + $cache->delete('workflowactive'); + } + /** * Handles an action of the subplugin_settings. * @@ -259,6 +294,7 @@ public static function handle_action($action, $workflowid) { } if ($action === action::WORKFLOW_ACTIVATE) { self::activate_workflow($workflowid); + self::reset_has_workflow_cache(); } else if ($action === action::UP_WORKFLOW) { self::change_sortindex($workflowid, true); } else if ($action === action::DOWN_WORKFLOW) { @@ -269,10 +305,12 @@ public static function handle_action($action, $workflowid) { self::backup_workflow($workflowid); } else if ($action === action::WORKFLOW_DISABLE) { self::disable($workflowid); + self::reset_has_workflow_cache(); return; // Return, since we do not want to redirect outside to deactivated workflows. } else if ($action === action::WORKFLOW_ABORTDISABLE) { self::disable($workflowid); self::abortprocesses($workflowid); + self::reset_has_workflow_cache(); return; // Return, since we do not want to redirect outside to deactivated workflows. } else if ($action === action::WORKFLOW_ABORT) { self::abortprocesses($workflowid); @@ -282,6 +320,7 @@ public static function handle_action($action, $workflowid) { if (self::get_workflow($workflowid) && self::is_removable($workflowid)) { self::remove($workflowid); + self::reset_has_workflow_cache(); } else { \core\notification::add(get_string('workflow_not_removeable', 'tool_lifecycle') , \core\notification::WARNING); @@ -324,8 +363,8 @@ public static function change_sortindex($workflowid, $up) { $transaction = $DB->start_delegated_transaction(); $otherrecord = $DB->get_record('tool_lifecycle_workflow', - array( - 'sortindex' => $otherindex) + [ + 'sortindex' => $otherindex, ] ); $otherworkflow = workflow::from_record($otherrecord); diff --git a/classes/local/table/active_manual_workflows_table.php b/classes/local/table/active_manual_workflows_table.php index 90c95e5f..32faf8a3 100644 --- a/classes/local/table/active_manual_workflows_table.php +++ b/classes/local/table/active_manual_workflows_table.php @@ -73,7 +73,7 @@ public function init() { get_string('workflow_processes', 'tool_lifecycle'), get_string('workflow_tools', 'tool_lifecycle'), ]); - $this->sortable(true, 'title'); + $this->sortable(false, 'title'); $this->setup(); } diff --git a/classes/local/table/active_processes_table.php b/classes/local/table/active_processes_table.php index 2c2a3c70..3e3a7a40 100644 --- a/classes/local/table/active_processes_table.php +++ b/classes/local/table/active_processes_table.php @@ -89,7 +89,7 @@ public function __construct($uniqueid, $filterdata) { get_string('fullnamecourse'), get_string('workflow', 'tool_lifecycle'), get_string('step', 'tool_lifecycle'), - get_string('tools', 'tool_lifecycle')]); + get_string('tools', 'tool_lifecycle'), ]); $this->column_nosort = ['tools']; } diff --git a/classes/local/table/active_workflows_table.php b/classes/local/table/active_workflows_table.php index c3142d03..d0bd1222 100644 --- a/classes/local/table/active_workflows_table.php +++ b/classes/local/table/active_workflows_table.php @@ -56,9 +56,9 @@ public function col_tools($row) { $alt = get_string('viewsteps', 'tool_lifecycle'); $icon = 't/viewdetails'; $overviewurl = new \moodle_url(urls::WORKFLOW_DETAILS, - array('wf' => $row->id)); - $output .= $OUTPUT->action_icon($overviewurl, new \pix_icon($icon, $alt, 'moodle', array('title' => $alt)), - null, array('title' => $alt)); + ['wf' => $row->id]); + $output .= $OUTPUT->action_icon($overviewurl, new \pix_icon($icon, $alt, 'moodle', ['title' => $alt]), + null, ['title' => $alt]); if (workflow_manager::is_disableable($row->id)) { $action = action::WORKFLOW_BACKUP; @@ -69,22 +69,22 @@ public function col_tools($row) { $alt = get_string('disableworkflow', 'tool_lifecycle'); $icon = 't/disable'; $url = new \moodle_url(urls::DEACTIVATED_WORKFLOWS, - array('workflowid' => $row->id, 'action' => action::WORKFLOW_DISABLE, 'sesskey' => sesskey())); + ['workflowid' => $row->id, 'action' => action::WORKFLOW_DISABLE, 'sesskey' => sesskey()]); $confirmaction = new \confirm_action(get_string('disableworkflow_confirm', 'tool_lifecycle')); $output .= $OUTPUT->action_icon($url, - new \pix_icon($icon, $alt, 'tool_lifecycle', array('title' => $alt)), + new \pix_icon($icon, $alt, 'tool_lifecycle', ['title' => $alt]), $confirmaction, - array('title' => $alt)); + ['title' => $alt]); $alt = get_string('abortdisableworkflow', 'tool_lifecycle'); $icon = 't/stop'; $url = new \moodle_url(urls::DEACTIVATED_WORKFLOWS, - array('workflowid' => $row->id, 'action' => action::WORKFLOW_ABORTDISABLE, 'sesskey' => sesskey())); + ['workflowid' => $row->id, 'action' => action::WORKFLOW_ABORTDISABLE, 'sesskey' => sesskey()]); $confirmaction = new \confirm_action(get_string('abortdisableworkflow_confirm', 'tool_lifecycle')); $output .= $OUTPUT->action_icon($url, - new \pix_icon($icon, $alt, 'moodle', array('title' => $alt)), + new \pix_icon($icon, $alt, 'moodle', ['title' => $alt]), $confirmaction, - array('title' => $alt) + ['title' => $alt] ); } diff --git a/classes/local/table/course_backups_table.php b/classes/local/table/course_backups_table.php index 6444969a..0739ab3c 100644 --- a/classes/local/table/course_backups_table.php +++ b/classes/local/table/course_backups_table.php @@ -86,7 +86,7 @@ public function init() { get_string('fullnamecourse'), get_string('backupcreated', 'tool_lifecycle'), get_string('download', 'tool_lifecycle'), - get_string('restore', 'tool_lifecycle')]); + get_string('restore', 'tool_lifecycle'), ]); $this->setup(); } @@ -147,7 +147,7 @@ public function col_backupcreated($row) { */ public function col_download($row) { return \html_writer::link( - new \moodle_url('/admin/tool/lifecycle/downloadbackup.php', array('backupid' => $row->id)), + new \moodle_url('/admin/tool/lifecycle/downloadbackup.php', ['backupid' => $row->id]), get_string('download', 'tool_lifecycle') ); } @@ -161,7 +161,7 @@ public function col_download($row) { */ public function col_restore($row) { return \html_writer::link( - new \moodle_url('/admin/tool/lifecycle/restore.php', array('backupid' => $row->id)), + new \moodle_url('/admin/tool/lifecycle/restore.php', ['backupid' => $row->id]), get_string('restore', 'tool_lifecycle') ); } diff --git a/classes/local/table/courses_in_step_table.php b/classes/local/table/courses_in_step_table.php index f23d1ef0..d14a57ae 100644 --- a/classes/local/table/courses_in_step_table.php +++ b/classes/local/table/courses_in_step_table.php @@ -73,7 +73,7 @@ public function __construct($step, $courseid) { $where = "p.stepindex = :stepindex AND p.workflowid = :wfid"; - $this->column_nosort = array('status', 'tools'); + $this->column_nosort = ['status', 'tools']; $this->set_sql($fields, $from, $where, ['stepindex' => $step->sortindex, 'wfid' => $step->workflowid]); if ($courseid) { $this->set_sortdata([]); diff --git a/classes/local/table/deactivated_workflows_table.php b/classes/local/table/deactivated_workflows_table.php index e6d3d182..37f867e5 100644 --- a/classes/local/table/deactivated_workflows_table.php +++ b/classes/local/table/deactivated_workflows_table.php @@ -89,20 +89,20 @@ public function col_tools($row) { $alt = get_string('viewsteps', 'tool_lifecycle'); $icon = 't/viewdetails'; $url = new \moodle_url(urls::WORKFLOW_DETAILS, - array('wf' => $row->id)); - $output .= $OUTPUT->action_icon($url, new \pix_icon($icon, $alt, 'moodle', array('title' => $alt)), - null, array('title' => $alt)); + ['wf' => $row->id]); + $output .= $OUTPUT->action_icon($url, new \pix_icon($icon, $alt, 'moodle', ['title' => $alt]), + null, ['title' => $alt]); if (workflow_manager::is_abortable($row->id)) { $alt = get_string('abortprocesses', 'tool_lifecycle'); $icon = 't/stop'; $url = new \moodle_url(urls::DEACTIVATED_WORKFLOWS, - array('workflowid' => $row->id, 'action' => action::WORKFLOW_ABORT, 'sesskey' => sesskey())); + ['workflowid' => $row->id, 'action' => action::WORKFLOW_ABORT, 'sesskey' => sesskey()]); $confirmaction = new \confirm_action(get_string('abortprocesses_confirm', 'tool_lifecycle')); $output .= $OUTPUT->action_icon($url, - new \pix_icon($icon, $alt, 'moodle', array('title' => $alt)), + new \pix_icon($icon, $alt, 'moodle', ['title' => $alt]), $confirmaction, - array('title' => $alt) + ['title' => $alt] ); } @@ -110,12 +110,12 @@ public function col_tools($row) { $alt = get_string('deleteworkflow', 'tool_lifecycle'); $icon = 't/delete'; $url = new \moodle_url(urls::DEACTIVATED_WORKFLOWS, - array('workflowid' => $row->id, 'action' => action::WORKFLOW_DELETE, 'sesskey' => sesskey())); + ['workflowid' => $row->id, 'action' => action::WORKFLOW_DELETE, 'sesskey' => sesskey()]); $confirmaction = new \confirm_action(get_string('deleteworkflow_confirm', 'tool_lifecycle')); $output .= $OUTPUT->action_icon($url, - new \pix_icon($icon, $alt, 'moodle', array('title' => $alt)), + new \pix_icon($icon, $alt, 'moodle', ['title' => $alt]), $confirmaction, - array('title' => $alt) + ['title' => $alt] ); } diff --git a/classes/local/table/delayed_courses_table.php b/classes/local/table/delayed_courses_table.php index fe2c1e9b..b87e9c7c 100644 --- a/classes/local/table/delayed_courses_table.php +++ b/classes/local/table/delayed_courses_table.php @@ -145,7 +145,7 @@ public function __construct($filterdata) { get_string('coursename', 'tool_lifecycle'), get_string('category'), get_string('delays', 'tool_lifecycle'), - get_string('tools', 'tool_lifecycle') + get_string('tools', 'tool_lifecycle'), ]); } @@ -175,13 +175,13 @@ public function col_workflow($row) { $dateformat = get_string('strftimedatetimeshort', 'core_langconfig'); $date = userdate($row->workflowdelay, $dateformat); $text = get_string('delayed_for_workflow_until', 'tool_lifecycle', - array('name' => $row->workflow, 'date' => $date)); + ['name' => $row->workflow, 'date' => $date]); } else { $text = get_string('delayed_for_workflows', 'tool_lifecycle', $row->workflowcount); } } - return \html_writer::start_span('tool_lifecycle-hint', array('title' => $this->get_mouseover($row))) . + return \html_writer::start_span('tool_lifecycle-hint', ['title' => $this->get_mouseover($row)]) . $text . \html_writer::end_span(); } @@ -205,7 +205,7 @@ private function get_mouseover($row) { if ($row->workflowcount == 1) { $date = userdate($row->workflowdelay, $dateformat); $text .= get_string('name_until_date', 'tool_lifecycle', - array('name' => $row->workflow, 'date' => $date)) . ' '; + ['name' => $row->workflow, 'date' => $date]) . ' '; } else if ($row->workflowcount > 1) { $sql = 'SELECT dw.id, dw.delayeduntil, w.title FROM {tool_lifecycle_delayed_workf} dw @@ -216,7 +216,7 @@ private function get_mouseover($row) { foreach ($records as $record) { $date = userdate($record->delayeduntil, $dateformat); $text .= get_string('name_until_date', 'tool_lifecycle', - array('name' => $record->title, 'date' => $date)) . ' '; + ['name' => $record->title, 'date' => $date]) . ' '; } } return $text; @@ -233,11 +233,11 @@ private function get_mouseover($row) { public function col_tools($row) { global $PAGE, $OUTPUT; - $params = array( + $params = [ 'action' => 'delete', 'cid' => $row->courseid, - 'sesskey' => sesskey() - ); + 'sesskey' => sesskey(), + ]; if ($this->workflow) { $params['workflow'] = $this->workflow; diff --git a/classes/local/table/interaction_attention_table.php b/classes/local/table/interaction_attention_table.php index 6cf8c504..2624831d 100644 --- a/classes/local/table/interaction_attention_table.php +++ b/classes/local/table/interaction_attention_table.php @@ -84,7 +84,7 @@ public function __construct($uniqueid, $courseids, $filterdata = null) { } } - $this->column_nosort = array('status', 'tools'); + $this->column_nosort = ['status', 'tools']; $this->set_sql($fields, $from, join(" AND ", $where), $params); $this->define_baseurl($PAGE->url); $this->init(); @@ -155,12 +155,12 @@ private function format_icon_link($action, $processid, $stepinstanceid, $alt) { global $PAGE, $OUTPUT; $button = new \single_button(new \moodle_url($PAGE->url, - array( + [ 'stepid' => $stepinstanceid, 'action' => $action, 'processid' => $processid, - 'sesskey' => sesskey() - )), $alt + 'sesskey' => sesskey(), + ]), $alt ); return $OUTPUT->render($button); } diff --git a/classes/local/table/interaction_remaining_table.php b/classes/local/table/interaction_remaining_table.php index 039dc7e5..710ffa68 100644 --- a/classes/local/table/interaction_remaining_table.php +++ b/classes/local/table/interaction_remaining_table.php @@ -89,7 +89,7 @@ public function __construct($uniqueid, $courseids) { $where = 'c.id IN ('. $ids . ')'; } - $this->column_nosort = array('status', 'tools'); + $this->column_nosort = ['status', 'tools']; $this->sortable(true, 'lastmodified', 'DESC'); $this->set_sql($fields, $from, $where, []); $this->set_count_sql("SELECT COUNT(1) FROM {course} c WHERE $where"); @@ -131,9 +131,9 @@ public function col_tools($row) { foreach ($this->availabletools as $tool) { if (has_capability($tool->capability, \context_course::instance($row->courseid), null, false)) { $actions[$tool->triggerid] = new \action_menu_link_secondary( - new \moodle_url($PAGE->url, array('triggerid' => $tool->triggerid, - 'courseid' => $row->courseid, 'sesskey' => sesskey())), - new \pix_icon($tool->icon, $tool->displayname, 'moodle', array('class' => 'iconsmall', 'title' => '')), + new \moodle_url($PAGE->url, ['triggerid' => $tool->triggerid, + 'courseid' => $row->courseid, 'sesskey' => sesskey(), ]), + new \pix_icon($tool->icon, $tool->displayname, 'moodle', ['class' => 'iconsmall', 'title' => '']), $tool->displayname ); } diff --git a/classes/local/table/process_errors_table.php b/classes/local/table/process_errors_table.php index 545a883d..d7463d17 100644 --- a/classes/local/table/process_errors_table.php +++ b/classes/local/table/process_errors_table.php @@ -53,7 +53,7 @@ public function __construct() { $this->strings = [ 'proceed' => get_string('proceed', 'tool_lifecycle'), - 'rollback' => get_string('rollback', 'tool_lifecycle') + 'rollback' => get_string('rollback', 'tool_lifecycle'), ]; $fields = 'c.fullname as course, w.title as workflow, s.instancename as step, pe.*'; @@ -80,7 +80,7 @@ public function __construct() { get_string('courseid', 'tool_lifecycle'), get_string('course'), get_string('error'), - get_string('tools', 'tool_lifecycle') + get_string('tools', 'tool_lifecycle'), ]); } @@ -94,9 +94,9 @@ public function __construct() { */ public function col_error($row) { return "
" . - nl2br(htmlentities($row->errormessage)) . + nl2br(htmlentities($row->errormessage, ENT_COMPAT)) . "" . - nl2br(htmlentities($row->errortrace)) . + nl2br(htmlentities($row->errortrace, ENT_COMPAT)) . "
"; } diff --git a/classes/local/table/workflow_definition_table.php b/classes/local/table/workflow_definition_table.php index b394d3bb..e2db1356 100644 --- a/classes/local/table/workflow_definition_table.php +++ b/classes/local/table/workflow_definition_table.php @@ -87,9 +87,9 @@ public function col_timeactive($row) { } if (workflow_manager::is_valid($row->id)) { return $OUTPUT->single_button(new \moodle_url(urls::ACTIVE_WORKFLOWS, - array('action' => action::WORKFLOW_ACTIVATE, + ['action' => action::WORKFLOW_ACTIVATE, 'sesskey' => sesskey(), - 'workflowid' => $row->id)), + 'workflowid' => $row->id, ]), get_string('activateworkflow', 'tool_lifecycle')); } else { return $OUTPUT->pix_icon('i/warning', get_string('invalid_workflow_details', 'tool_lifecycle')) . @@ -111,9 +111,9 @@ public function col_tools($row) { $alt = get_string('viewsteps', 'tool_lifecycle'); $icon = 't/viewdetails'; $url = new \moodle_url(urls::WORKFLOW_DETAILS, - array('wf' => $row->id)); - $output .= $OUTPUT->action_icon($url, new \pix_icon($icon, $alt, 'moodle', array('title' => $alt)), - null, array('title' => $alt)); + ['wf' => $row->id]); + $output .= $OUTPUT->action_icon($url, new \pix_icon($icon, $alt, 'moodle', ['title' => $alt]), + null, ['title' => $alt]); $trigger = trigger_manager::get_triggers_for_workflow($row->id); if (!empty($trigger)) { diff --git a/classes/local/table/workflow_table.php b/classes/local/table/workflow_table.php index 88e237d9..1763c0a5 100644 --- a/classes/local/table/workflow_table.php +++ b/classes/local/table/workflow_table.php @@ -73,9 +73,9 @@ public function col_timeactive($row) { return userdate($row->timeactive, get_string('strftimedatetime'), 0); } return $OUTPUT->single_button(new \moodle_url($PAGE->url, - array('action' => action::WORKFLOW_ACTIVATE, + ['action' => action::WORKFLOW_ACTIVATE, 'sesskey' => sesskey(), - 'workflowid' => $row->id)), + 'workflowid' => $row->id, ]), get_string('activateworkflow', 'tool_lifecycle')); } @@ -133,9 +133,9 @@ public function col_tools($row) { $alt = get_string('viewsteps', 'tool_lifecycle'); $icon = 't/viewdetails'; $url = new \moodle_url(urls::WORKFLOW_DETAILS, - array('wf' => $row->id)); - $output .= $OUTPUT->action_icon($url, new \pix_icon($icon, $alt, 'moodle', array('title' => $alt)), - null, array('title' => $alt)); + ['wf' => $row->id]); + $output .= $OUTPUT->action_icon($url, new \pix_icon($icon, $alt, 'moodle', ['title' => $alt]), + null, ['title' => $alt]); return $output; } @@ -154,11 +154,11 @@ protected function format_icon_link($action, $workflowid, $icon, $alt) { global $OUTPUT, $PAGE; return $OUTPUT->action_icon(new \moodle_url($PAGE->url, - array('action' => $action, + ['action' => $action, 'workflowid' => $workflowid, - 'sesskey' => sesskey())), - new \pix_icon($icon, $alt, 'moodle', array('title' => $alt)), - null , array('title' => $alt)) . ' '; + 'sesskey' => sesskey(), ]), + new \pix_icon($icon, $alt, 'moodle', ['title' => $alt]), + null , ['title' => $alt]) . ' '; } } diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index d320f46c..96745bb4 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -59,15 +59,15 @@ class provider implements */ public static function get_metadata(collection $collection): collection { $collection->add_database_table('tool_lifecycle_action_log', - array( + [ 'processid' => 'privacy:metadata:tool_lifecycle_action_log:processid', 'workflowid' => 'privacy:metadata:tool_lifecycle_action_log:workflowid', 'courseid' => 'privacy:metadata:tool_lifecycle_action_log:courseid', 'stepindex' => 'privacy:metadata:tool_lifecycle_action_log:stepindex', 'time' => 'privacy:metadata:tool_lifecycle_action_log:time', 'userid' => 'privacy:metadata:tool_lifecycle_action_log:userid', - 'action' => 'privacy:metadata:tool_lifecycle_action_log:action' - ), + 'action' => 'privacy:metadata:tool_lifecycle_action_log:action', + ], 'privacy:metadata:tool_lifecycle_action_log'); return $collection; } @@ -81,7 +81,7 @@ public static function get_metadata(collection $collection): collection { public static function get_contexts_for_userid(int $userid): contextlist { global $DB; $contextlist = new contextlist(); - if ($DB->record_exists('tool_lifecycle_action_log', array('userid' => $userid))) { + if ($DB->record_exists('tool_lifecycle_action_log', ['userid' => $userid])) { $contextlist->add_system_context(); } return $contextlist; @@ -96,7 +96,7 @@ public static function export_user_data(approved_contextlist $contextlist) { global $DB; foreach ($contextlist->get_contexts() as $context) { if ($context instanceof context_system) { - $records = $DB->get_records('tool_lifecycle_action_log', array('userid' => $contextlist->get_user()->id)); + $records = $DB->get_records('tool_lifecycle_action_log', ['userid' => $contextlist->get_user()->id]); $writer = writer::with_context($contextlist->current()); foreach ($records as $record) { $step = step_manager::get_step_instance_by_workflow_index($record->workflowid, $record->stepindex); @@ -105,7 +105,7 @@ public static function export_user_data(approved_contextlist $contextlist) { $record->step = $step->instancename; $record->workflow = $workflow->displaytitle; $subcontext = ['tool_lifecycle', 'action_log', "process_$record->processid", $step->instancename, - "action_$record->action"]; + "action_$record->action", ]; $writer->export_data($subcontext, $record); } } @@ -139,7 +139,7 @@ public static function delete_data_for_user(approved_contextlist $contextlist) { $sql = "UPDATE {tool_lifecycle_action_log} SET userid = -1 WHERE userid = :userid"; - $DB->execute($sql, array('userid' => $contextlist->get_user()->id)); + $DB->execute($sql, ['userid' => $contextlist->get_user()->id]); } } } @@ -154,7 +154,7 @@ public static function get_users_in_context(userlist $userlist) { if ($context instanceof context_system) { $sql = "SELECT userid FROM {tool_lifecycle_action_log}"; - $userlist->add_from_sql('userid', $sql, array()); + $userlist->add_from_sql('userid', $sql, []); } } diff --git a/classes/processor.php b/classes/processor.php index bf4f9ce4..81a0e73f 100644 --- a/classes/processor.php +++ b/classes/processor.php @@ -49,7 +49,7 @@ class processor { */ public function call_trigger() { $activeworkflows = workflow_manager::get_active_automatic_workflows(); - $exclude = array(); + $exclude = []; foreach ($activeworkflows as $workflow) { $countcourses = 0; @@ -203,7 +203,7 @@ public function get_course_recordset($triggers, $exclude) { global $DB; $where = 'true'; - $whereparams = array(); + $whereparams = []; foreach ($triggers as $trigger) { $lib = lib_manager::get_automatic_trigger_lib($trigger->subpluginname); list($sql, $params) = $lib->get_course_recordset_where($trigger->id); diff --git a/classes/task/lifecycle_cleanup_task.php b/classes/task/lifecycle_cleanup_task.php index eadeadf1..19455eaf 100644 --- a/classes/task/lifecycle_cleanup_task.php +++ b/classes/task/lifecycle_cleanup_task.php @@ -48,7 +48,7 @@ public function get_name() { public function execute() { global $DB; $twomonthago = time() - 60 * 24 * 60 * 60; - $DB->delete_records_select('tool_lifecycle_delayed', 'delayeduntil <= :time', array('time' => $twomonthago)); - $DB->delete_records_select('tool_lifecycle_delayed_workf', 'delayeduntil <= :time', array('time' => $twomonthago)); + $DB->delete_records_select('tool_lifecycle_delayed', 'delayeduntil <= :time', ['time' => $twomonthago]); + $DB->delete_records_select('tool_lifecycle_delayed_workf', 'delayeduntil <= :time', ['time' => $twomonthago]); } } diff --git a/classes/task/lifecycle_error_notify_task.php b/classes/task/lifecycle_error_notify_task.php index c20aee73..c2a76ca7 100644 --- a/classes/task/lifecycle_error_notify_task.php +++ b/classes/task/lifecycle_error_notify_task.php @@ -71,7 +71,7 @@ public function execute() { 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), + get_string('notifyerrorsemailcontenthtml', 'tool_lifecycle', $obj) ); } } diff --git a/classes/task/lifecycle_task.php b/classes/task/lifecycle_task.php index 91692d9a..a8ffb669 100644 --- a/classes/task/lifecycle_task.php +++ b/classes/task/lifecycle_task.php @@ -55,7 +55,7 @@ public function execute() { $steps = step_manager::get_step_types(); /* @var \tool_lifecycle\step\libbase[] $steplibs stores the lib classes of all step subplugins.*/ - $steplibs = array(); + $steplibs = []; foreach ($steps as $id => $step) { $steplibs[$id] = lib_manager::get_step_lib($id); $steplibs[$id]->pre_processing_bulk_operation(); diff --git a/classes/view_controller.php b/classes/view_controller.php index ea62ba6e..b0696515 100644 --- a/classes/view_controller.php +++ b/classes/view_controller.php @@ -61,7 +61,7 @@ public function handle_view($renderer, $filterdata) { return; } - $arrayofcourseids = array(); + $arrayofcourseids = []; foreach ($courses as $course) { $arrayofcourseids[$course->id] = $course->id; } @@ -75,7 +75,7 @@ public function handle_view($renderer, $filterdata) { "on p.workflowid = s.workflowid AND p.stepindex = s.sortindex " . "WHERE p.courseid IN (". $listofcourseids . ")"); - $requiresinteraction = array(); + $requiresinteraction = []; $remainingcourses = $arrayofcourseids; foreach ($processes as $process) { diff --git a/coursebackups.php b/coursebackups.php index 711b524d..c0d97220 100644 --- a/coursebackups.php +++ b/coursebackups.php @@ -21,6 +21,7 @@ * @copyright 2017 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + require_once(__DIR__ . '/../../../config.php'); require_once($CFG->libdir . '/adminlib.php'); diff --git a/db/access.php b/db/access.php index 37c42da5..f6751c5b 100644 --- a/db/access.php +++ b/db/access.php @@ -22,20 +22,20 @@ */ defined('MOODLE_INTERNAL') || die(); -$capabilities = array( +$capabilities = [ - 'tool/lifecycle:managecourses' => array( + 'tool/lifecycle:managecourses' => [ 'contextlevel' => CONTEXT_COURSE, 'captype' => 'write', - 'archetypes' => array( + 'archetypes' => [ 'manager' => CAP_PREVENT, 'editingteacher' => CAP_ALLOW, 'teacher' => CAP_PREVENT, 'students' => CAP_PREVENT, - ), - 'clonepermissionsfrom' => 'moodle/course:update' - ), -); + ], + 'clonepermissionsfrom' => 'moodle/course:update', + ], +]; diff --git a/db/caches.php b/db/caches.php index 0daffb47..40b6edce 100644 --- a/db/caches.php +++ b/db/caches.php @@ -24,8 +24,13 @@ defined('MOODLE_INTERNAL') || die(); -$definitions = array( - 'mformdata' => array( - 'mode' => cache_store::MODE_SESSION - ) -); +$definitions = [ + 'mformdata' => [ + 'mode' => cache_store::MODE_SESSION, + ], + 'application' => [ + 'mode' => cache_store::MODE_APPLICATION, + 'simplekeys' => true, + 'simpledata' => true, + ], +]; diff --git a/db/events.php b/db/events.php index fa9c6449..5642f2ef 100644 --- a/db/events.php +++ b/db/events.php @@ -24,9 +24,9 @@ defined('MOODLE_INTERNAL') || die(); -$observers = array( - array( +$observers = [ + [ 'eventname' => 'core\event\course_deleted', 'callback' => 'tool_lifecycle\local\manager\process_manager::course_deletion_observed', - ) -); + ], +]; diff --git a/db/tasks.php b/db/tasks.php index d061305a..3af80c91 100644 --- a/db/tasks.php +++ b/db/tasks.php @@ -25,8 +25,8 @@ defined('MOODLE_INTERNAL') || die(); -$tasks = array( - array( +$tasks = [ + [ 'classname' => 'tool_lifecycle\task\lifecycle_task', 'blocking' => 0, 'minute' => '*', @@ -35,8 +35,8 @@ 'month' => '*', 'dayofweek' => '*', 'faildelay' => 1, - ), - array( + ], + [ 'classname' => 'tool_lifecycle\task\lifecycle_cleanup_task', 'blocking' => 0, 'minute' => '0', @@ -44,8 +44,8 @@ 'day' => '*', 'month' => '*', 'dayofweek' => '0', - ), - array( + ], + [ 'classname' => 'tool_lifecycle\task\lifecycle_error_notify_task', 'blocking' => 0, 'minute' => 'R', @@ -53,5 +53,5 @@ 'day' => '*', 'month' => '*', 'dayofweek' => '0', - ), -); + ], +]; diff --git a/db/upgrade.php b/db/upgrade.php index 99accd3e..85871e4f 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -22,6 +22,20 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +/** + * Fix any gaps in the workflows sortindex. + */ +function tool_lifecycle_fix_workflow_sortindex() { + $workflows = \tool_lifecycle\local\manager\workflow_manager::get_active_workflows(); + for ($i = 1; $i <= count($workflows); $i++) { + $workflow = $workflows[$i - 1]; + if ($workflow->sortindex != $i) { + $workflow->sortindex = $i; + \tool_lifecycle\local\manager\workflow_manager::insert_or_update($workflow); + } + } +} + /** * Update script for tool_lifecycle. * @param int $oldversion Version id of the previously installed version. @@ -46,7 +60,7 @@ function xmldb_tool_lifecycle_upgrade($oldversion) { $table->add_field('title', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'id'); $table->add_field('active', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'title'); $table->add_field('timeactive', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'active'); - $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); + $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); // Conditionally create the table. if (!$dbman->table_exists($table)) { @@ -63,7 +77,7 @@ function xmldb_tool_lifecycle_upgrade($oldversion) { } $field = new xmldb_field('workflowid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'subpluginname'); - $key = new xmldb_key('workflowid_fk', XMLDB_KEY_FOREIGN, array('workflowid'), 'tool_lifecycle_workflow', array('id')); + $key = new xmldb_key('workflowid_fk', XMLDB_KEY_FOREIGN, ['workflowid'], 'tool_lifecycle_workflow', ['id']); // Conditionally create the field. if (!$dbman->field_exists($table, $field)) { @@ -89,7 +103,7 @@ function xmldb_tool_lifecycle_upgrade($oldversion) { // Add workflowfield to trigger. $field = new xmldb_field('workflowid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'enabled'); - $key = new xmldb_key('workflowid_fk', XMLDB_KEY_FOREIGN, array('workflowid'), 'tool_lifecycle_workflow', array('id')); + $key = new xmldb_key('workflowid_fk', XMLDB_KEY_FOREIGN, ['workflowid'], 'tool_lifecycle_workflow', ['id']); // Conditionally create the field. if (!$dbman->field_exists($table, $field)) { @@ -107,7 +121,7 @@ function xmldb_tool_lifecycle_upgrade($oldversion) { } $field = new xmldb_field('workflowid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'courseid'); - $key = new xmldb_key('workflowid_fk', XMLDB_KEY_FOREIGN, array('workflowid'), 'tool_lifecycle_workflow', array('id')); + $key = new xmldb_key('workflowid_fk', XMLDB_KEY_FOREIGN, ['workflowid'], 'tool_lifecycle_workflow', ['id']); // Conditionally create the field. if (!$dbman->field_exists($table, $field)) { @@ -207,7 +221,7 @@ function xmldb_tool_lifecycle_upgrade($oldversion) { // Define key workflowid_fk (foreign) to be added to tool_lifecycle_trigger. $table = new xmldb_table('tool_lifecycle_trigger'); - $key = new xmldb_key('workflowid_fk', XMLDB_KEY_FOREIGN, array('workflowid'), 'tool_lifecycle_workflow', array('id')); + $key = new xmldb_key('workflowid_fk', XMLDB_KEY_FOREIGN, ['workflowid'], 'tool_lifecycle_workflow', ['id']); // Launch add key workflowid_fk. $dbman->add_key($table, $key); @@ -262,13 +276,13 @@ function xmldb_tool_lifecycle_upgrade($oldversion) { // Define key courseid_fk (foreign) to be dropped form tool_lifecycle_process. $table = new xmldb_table('tool_lifecycle_process'); - $key = new xmldb_key('courseid_fk', XMLDB_KEY_FOREIGN, array('courseid'), 'course', array('id')); + $key = new xmldb_key('courseid_fk', XMLDB_KEY_FOREIGN, ['courseid'], 'course', ['id']); // Launch drop key courseid_fk. $dbman->drop_key($table, $key); // Define key courseid_fk (foreign-unique) to be added to tool_lifecycle_process. - $key = new xmldb_key('courseid_fk', XMLDB_KEY_FOREIGN_UNIQUE, array('courseid'), 'course', array('id')); + $key = new xmldb_key('courseid_fk', XMLDB_KEY_FOREIGN_UNIQUE, ['courseid'], 'course', ['id']); // Launch add key courseid_fk. $dbman->add_key($table, $key); @@ -365,7 +379,7 @@ function xmldb_tool_lifecycle_upgrade($oldversion) { $dbman->add_field($table, $field); } - $params = array($duration, $duration); + $params = [$duration, $duration]; $DB->execute('UPDATE {tool_lifecycle_workflow} SET finishdelay = ?, rollbackdelay = ?', $params); @@ -475,5 +489,14 @@ function xmldb_tool_lifecycle_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2021112300, 'tool', 'lifecycle'); } + if ($oldversion < 2024042300) { + + tool_lifecycle_fix_workflow_sortindex(); + + // Lifecycle savepoint reached. + upgrade_plugin_savepoint(true, 2024042300, 'tool', 'lifecycle'); + + } + return true; } diff --git a/delayedcourses.php b/delayedcourses.php index 923cd36b..634c4e44 100644 --- a/delayedcourses.php +++ b/delayedcourses.php @@ -44,15 +44,15 @@ $workflow = optional_param('workflow', null, PARAM_ALPHANUM); if ($workflow) { if (is_number($workflow)) { - $DB->delete_records('tool_lifecycle_delayed_workf', array('courseid' => $cid, 'workflowid' => $workflow)); + $DB->delete_records('tool_lifecycle_delayed_workf', ['courseid' => $cid, 'workflowid' => $workflow]); } else if ($workflow == 'global') { - $DB->delete_records('tool_lifecycle_delayed', array('courseid' => $cid)); + $DB->delete_records('tool_lifecycle_delayed', ['courseid' => $cid]); } else { throw new \coding_exception('workflow has to be "global" or a int value'); } } else { - $DB->delete_records('tool_lifecycle_delayed', array('courseid' => $cid)); - $DB->delete_records('tool_lifecycle_delayed_workf', array('courseid' => $cid)); + $DB->delete_records('tool_lifecycle_delayed', ['courseid' => $cid]); + $DB->delete_records('tool_lifecycle_delayed_workf', ['courseid' => $cid]); } } else if ($action == 'bulk-delete') { $workflow = optional_param('workflow', null, PARAM_ALPHANUM); diff --git a/downloadbackup.php b/downloadbackup.php index c2877e7f..00ee5c78 100644 --- a/downloadbackup.php +++ b/downloadbackup.php @@ -21,6 +21,7 @@ * @copyright 2019 Justus Dieckmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + require_once(__DIR__ . '/../../../config.php'); require_login(); @@ -28,7 +29,7 @@ $backupid = required_param('backupid', PARAM_INT); -$backuprecord = $DB->get_record('tool_lifecycle_backups', array('id' => $backupid), 'backupfile', MUST_EXIST); +$backuprecord = $DB->get_record('tool_lifecycle_backups', ['id' => $backupid], 'backupfile', MUST_EXIST); $source = get_config('tool_lifecycle', 'backup_path') . DIRECTORY_SEPARATOR . $backuprecord->backupfile; if (!file_exists($source)) { diff --git a/editelement.php b/editelement.php index de3ac303..9864e63a 100644 --- a/editelement.php +++ b/editelement.php @@ -71,7 +71,7 @@ \tool_lifecycle\permission_and_navigation::setup_workflow($workflow); $params = [ - 'type' => $type + 'type' => $type, ]; if ($elementid) { $params['elementid'] = $element->id; diff --git a/lang/de/tool_lifecycle.php b/lang/de/tool_lifecycle.php index 986f7b4b..a92d11a1 100644 --- a/lang/de/tool_lifecycle.php +++ b/lang/de/tool_lifecycle.php @@ -22,211 +22,184 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - -$string['pluginname'] = 'Kurs-Lebenszyklus'; -$string['plugintitle'] = 'Kurs-Lebenszyklus'; - -$string['lifecycle:managecourses'] = 'Darf Kurse in tool_lifecycle verwalten.'; -$string['managecourses_link'] = 'Kurse verwalten'; - -$string['general_config_header'] = "Allgemein & Subplugins"; +$string['abortdisableworkflow'] = 'Workfow deaktivieren (Prozesse werden abgebrochen, eventuell unsicher!)'; +$string['abortdisableworkflow_confirm'] = 'Sie sind dabei, den Workflow zu deaktivieren. Alle laufenden Prozesse werden abgebrochen. Sind Sie sicher?'; +$string['abortprocesses'] = 'Laufende Prozesse abbrechen (eventuell unsicher!)'; +$string['abortprocesses_confirm'] = 'Alle laufenden Prozesse dieses Workflows werden abgebrochen. Sind Sie sicher?'; +$string['activateworkflow'] = 'Aktivieren'; +$string['active'] = 'Aktiv'; +$string['active_automatic_workflows_heading'] = 'Aktive automatische Workflows'; +$string['active_manual_workflows_heading'] = 'Aktive manuelle Workflows'; +$string['active_workflow_not_changeable'] = 'Die Workflow-Instanz wurde bereits aktiviert. Je nach Schritt-Typ können dessen Einstellungen eventuell noch geändert werden. Änderungen an Trigger-Instanzen wirken sich nicht auf bereits getriggerte Kurse aus.'; +$string['active_workflow_not_removeable'] = 'Die Workflow-Instanz ist aktiv. Es ist nicht möglich, sie zu entfernen.'; +$string['active_workflows_header'] = 'Aktive Workflows'; +$string['active_workflows_list'] = 'Zeige aktive Workflows'; +$string['add_new_step_instance'] = 'Füge neue Schritt-Instanz hinzu...'; +$string['add_new_trigger_instance'] = 'Füge neue Trigger-Instanz...'; +$string['add_workflow'] = 'Neuen Workflow hinzufügen'; +$string['adminsettings_edit_step_instance_heading'] = 'Schritt-Instanz für Workflow \'{$a}\''; +$string['adminsettings_edit_trigger_instance_heading'] = 'Trigger-Instanz für Workflow \'{$a}\''; +$string['adminsettings_edit_workflow_definition_heading'] = 'Workflowdefinition'; +$string['adminsettings_heading'] = 'Workflow-Einstellungen'; +$string['adminsettings_workflow_definition_steps_heading'] = 'Workflowschritte'; +$string['backupcreated'] = 'Erstellt am'; +$string['backupworkflow'] = 'Workflow sichern'; +$string['cannot_trigger_workflow_manually'] = 'Der Workflow konnte nicht manuell ausgelöst werden.'; $string['config_delay_duration'] = 'Standardlänge eines Kursausschlusses'; $string['config_delay_duration_desc'] = 'Diese Einstellung definiert den Standardlänge einer Kursausschlusses in einem Workflow falls ein Prozess des Workflows zurückgesetzt oder beendigt wird. Die Länge des Kursausschlusses besagt, wie lange es dauert, bis der Kurs wieder vom Workflow bearbeitet wird.'; +$string['config_showcoursecounts'] = 'Zeige Anzahl der Kurse, die getriggert werden'; +$string['config_showcoursecounts_desc'] = 'Die Workflow-Konfigurationsseite zeigt normalerweise die Anzahl an Kursen, die durch +die konfigurierten Trigger getriggert werden, was Performance-Probleme verursachen kann. Bei Performance-Problemen kann dies hiermit +deaktiviert werden'; +$string['course_backups_list_header'] = 'Kurssicherungen'; +$string['courseid'] = 'Kurs-ID'; +$string['coursename'] = 'Kursname'; +$string['courses_excluded'] = 'Kurse insgesamt ausgeschlossen: {$a}'; +$string['courses_size'] = 'Kurse insgesamt genauer betrachtet: {$a}'; +$string['courses_triggered'] = 'Kurse insgesamt getriggered: {$a}'; +$string['courses_will_be_excluded'] = '{$a} Kurse werden ausgeschlossen'; +$string['courses_will_be_excluded_total'] = '{$a} Kurse werden insgesamt ausgeschlossen'; +$string['courses_will_be_triggered'] = '{$a} Kurse werden getriggert'; +$string['courses_will_be_triggered_total'] = '{$a} Kurse werden insgesamt getriggert'; +$string['create_copy'] = 'Kopie erstellen'; +$string['create_step'] = 'Step erstellen'; +$string['create_trigger'] = 'Trigger erstellen'; +$string['create_workflow_from_existing'] = 'Kopie von bestehendem Workflow erstellen'; +$string['date'] = 'Fällligkeitsdatum'; +$string['deactivated'] = 'Deaktiviert'; +$string['deactivated_workflows_list'] = 'Zeige deaktivierte Workflows'; +$string['deactivated_workflows_list_header'] = 'Deaktivierte Workflows'; +$string['deleteworkflow'] = 'Workflow löschen'; +$string['deleteworkflow_confirm'] = 'Sie sind dabei, den Workflow zu löschen. Das kann nicht rückgängig gemacht werden. Sind Sie sicher?'; +$string['details:displaytitle'] = 'Wird Lehrenden als {$a} angezeigt.'; +$string['details:finishdelay'] = 'Nachdem ein Kurs einen Workflow beendet, wird er für {$a} verzögert.'; +$string['details:globaldelay_no'] = 'Diese Verzögerungen gelten nur für diesen Workflow.'; +$string['details:globaldelay_yes'] = 'Diese Verzögerungen gelten für alle Workflows.'; +$string['details:rollbackdelay'] = 'Nachdem ein Kurs zurückgesetzt wird, wird er für {$a} verzögert.'; +$string['disableworkflow'] = 'Workflow deaktivieren (Prozesse laufen weiter)'; +$string['disableworkflow_confirm'] = 'Sie sind dabei, den Workflow zu deaktivieren. Sind Sie sicher?'; +$string['download'] = 'Herunterladen'; +$string['draft'] = 'Entwurf'; +$string['duplicateworkflow'] = 'Workflow duplizieren'; +$string['edit_step'] = 'Step bearbeiten'; +$string['edit_trigger'] = 'Trigger bearbeiten'; +$string['editworkflow'] = 'Allgemeine Einstellungen bearbeiten'; +$string['error_wrong_trigger_selected'] = 'Sie haben einen nichtmanuellen Trigger ausgewählt.'; +$string['errorbackuppath'] = "Ein Fehler ist aufgetreten beim Versuchen das Backup Verzeichnis zu erstellen. +Ihnen fehlen wahrscheinlich die Berechtigung dazu. Bitte überprüfen Sie den Pfad unter +Seitenadministration/Plugins/Dienstprogramme/Kurs-Lebenszyklus/Allgemein & Subplugins."; +$string['errornobackup'] = "Es wurde kein Backup in dem angegebenen Pfad erstellt."; $string['find_course_list_header'] = 'Kurse finden'; -$string['adminsettings_heading'] = 'Workflow-Einstellungen'; -$string['active_manual_workflows_heading'] = 'Aktive manuelle Workflows'; -$string['active_automatic_workflows_heading'] = 'Aktive automatische Workflows'; -$string['see_in_workflow'] = 'In Workflow ansehen'; -$string['workflow_definition_heading'] = 'Workflowdefinitionen'; -$string['adminsettings_edit_workflow_definition_heading'] = 'Workflowdefinition'; -$string['adminsettings_workflow_definition_steps_heading'] = 'Workflowschritte'; -$string['adminsettings_edit_trigger_instance_heading'] = 'Trigger-Instanz für Workflow \'{$a}\''; -$string['adminsettings_edit_step_instance_heading'] = 'Schritt-Instanz für Workflow \'{$a}\''; -$string['add_new_step_instance'] = 'Füge neue Schritt-Instanz hinzu...'; -$string['add_new_trigger_instance'] = 'Füge neue Trigger-Instanz...'; -$string['step_settings_header'] = 'Spezifische Einstellungen des Schritttypen'; -$string['trigger_settings_header'] = 'Spezifische Einstellungen des Triggertypen'; -$string['general_settings_header'] = 'Allgemeine Einstellungen'; $string['followedby_none'] = 'Keine'; +$string['forselected'] = 'Für alle ausgewählten Prozesse'; +$string['general_config_header'] = "Allgemein & Subplugins"; +$string['general_settings_header'] = 'Allgemeine Einstellungen'; +$string['interaction_success'] = 'Aktion erfolgreich gespeichert.'; $string['invalid_workflow'] = 'Ungültige Workflowkonfiguration'; -$string['invalid_workflow_details'] = 'Gehe zur Detailanzeige, um einen Trigger für diesen Workflow zu erstellen.'; -$string['active_workflow_not_changeable'] = 'Die Workflow-Instanz wurde bereits aktiviert. Je nach Schritt-Typ können dessen Einstellungen eventuell noch geändert werden. Änderungen an Trigger-Instanzen wirken sich nicht auf bereits getriggerte Kurse aus.'; -$string['active_workflow_not_removeable'] = 'Die Workflow-Instanz ist aktiv. Es ist nicht möglich, sie zu entfernen.'; -$string['workflow_not_removeable'] = 'Es ist nicht möglich, diese Workflow-Instanz zu entfernen. Vielleicht hat sie noch laufende Prozesse?'; $string['invalid_workflow_cannot_be_activated'] = 'Der Workflow kann nicht aktiviert werden, da die Workflowdefinition ungültig ist'; -$string['trigger_does_not_exist'] = 'Der Trigger existiert nicht.'; -$string['cannot_trigger_workflow_manually'] = 'Der Workflow konnte nicht manuell ausgelöst werden.'; -$string['error_wrong_trigger_selected'] = 'Sie haben einen nichtmanuellen Trigger ausgewählt.'; - +$string['invalid_workflow_details'] = 'Gehe zur Detailanzeige, um einen Trigger für diesen Workflow zu erstellen.'; +$string['lastaction'] = 'Letzte Aktion am'; +$string['lifecycle:managecourses'] = 'Darf Kurse in tool_lifecycle verwalten.'; +$string['lifecycle_error_notify_task'] = 'Benachrichtigt die Administratoren bei Fehlern in tool_lifecycle-Prozessen.'; $string['lifecycle_task'] = 'Führt den Lifecycle-Prozess aus.'; - -$string['trigger_subpluginname'] = 'Subplugin Name'; -$string['trigger_subpluginname_help'] = 'Name des Schritt/Trigger-Subplugins (nur für Admins sichtbar).'; +$string['lifecyclestep'] = 'Schritt'; +$string['lifecycletrigger'] = 'Trigger'; +$string['managecourses_link'] = 'Kurse verwalten'; +$string['manual_trigger_process_existed'] = 'Es existiert bereits ein Workflow für diesen Kurs.'; +$string['manual_trigger_success'] = 'Workflow erfolgreich gestartet.'; +$string['move_down'] = 'Nach unten bewegen'; +$string['move_up'] = 'Nach oben bewegen'; +$string['nocoursestodisplay'] = 'Es gibt derzeit keine Kurse, die Ihre Aufmerksamkeit erfordern!'; +$string['nointeractioninterface'] = 'Keine Interaktionsschnittstelle verfügbar!'; +$string['noprocesserrors'] = 'Es gibt keine fehlerhaften Prozesse, die behandelt werden müssen!'; +$string['noprocessfound'] = 'Es konnte kein Prozess mit der gegebenen Prozessid gefunden werden!'; +$string['noremainingcoursestodisplay'] = 'Es gibt derzeit keine verbleibenden Kurse!'; +$string['nostepfound'] = 'Es konnte kein Schritt mit der gegeben Schrittid gefunden 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.'; +$string['notifyerrorsemailsubject'] = '{$a->amount} neue fehlerhafte tool_lifecycle Prozesse warten darauf, behandelt zu werden!'; +$string['overview:add_trigger'] = 'Trigger hinzufügen'; +$string['overview:add_trigger_help'] = 'Es kann nur eine Instanz jedes Triggertyps hinzugefügt werden.'; +$string['overview:trigger'] = 'Trigger'; +$string['overview:trigger_help'] = 'Ein Kurs fängt nur dann an, einen Workflow zu durchlaufen, wenn alle Trigger des Workflows dies übereinstimmend (UND-Verknüpfung) aussagen.

+In den hier genannten Zahlen werden Kurse, die verzögert werden oder sich bereits in anderen Workflows befinden, nicht mitgezählt.
+Trotzdem sind die Zahlen nur approximiert, da es sein könnte, dass die Kurse vor diesem einen anderen Workflow auslösen.'; +$string['pluginname'] = 'Kurs-Lebenszyklus'; +$string['plugintitle'] = 'Kurs-Lebenszyklus'; +$string['proceed'] = 'Fortfahren'; +$string['process_errors_header'] = 'Fehlermanagement'; +$string['process_proceeded_event'] = 'Ein Prozess wurde fortgeführt'; +$string['process_rollback_event'] = 'Ein Prozess wurde zurückgesetzt'; +$string['process_triggered_event'] = 'Ein Prozess wurde ausgelöst'; +$string['restore'] = 'Wiederherstellen'; +$string['restore_step_does_not_exist'] = 'Der Schritt {$a} ist nicht installiert, aber in der Sicherungsdatei enthalten. Bitte installieren Sie ihn zuerst und versuchen es dann erneut.'; +$string['restore_subplugins_invalid'] = 'Falsches Format der Sicherungsdatei. Das Format der Subpluginelemente ist nicht wie erwartet.'; +$string['restore_trigger_does_not_exist'] = 'Der Trigger {$a} ist nicht installiert, aber in der Sicherungsdatei enthalten. Bitte installieren Sie ihn zuerst und versuchen es dann erneut.'; +$string['restore_workflow_not_found'] = 'Falsches Format der Sicherungsdatei. Der Workflow konnte nicht gefunden werden.'; +$string['see_in_workflow'] = 'In Workflow ansehen'; +$string['status'] = 'Status'; +$string['step'] = 'Schritt'; +$string['step_delete'] = 'Entfernen'; +$string['step_edit'] = 'Bearbeiten'; +$string['step_instancename'] = 'Instanzname'; +$string['step_instancename_help'] = 'Titel der Schritt/Trigger-Instanz (nur für Admins sichtbar).'; +$string['step_settings_header'] = 'Spezifische Einstellungen des Schritttypen'; +$string['step_show'] = 'Anzeigen'; +$string['step_sortindex'] = 'Hoch/Runter'; +$string['step_subpluginname'] = 'Subpluginname'; +$string['step_subpluginname_help'] = 'Name des Schritt/Trigger-Subplugins (nur für Admins sichtbar).'; +$string['step_type'] = 'Typ'; +$string['subplugintype_lifecyclestep'] = 'Schritt eines Lifecycle-Prozesses'; +$string['subplugintype_lifecyclestep_plural'] = 'Schritte eines Lifecycle-Prozesses'; +$string['subplugintype_lifecycletrigger'] = 'Trigger zum Starten eines Lifecycle-Prozesses'; +$string['subplugintype_lifecycletrigger_plural'] = 'Trigger zum Starten eines Lifecycle-Prozesses'; +$string['tablecourseslog'] = 'Vergangene Aktionen'; +$string['tablecoursesremaining'] = 'Restliche Kurse'; +$string['tablecoursesrequiringattention'] = 'Kurse, die Ihre Aufmerksamkeit erfordern!'; +$string['tools'] = 'Aktionen'; +$string['trigger'] = 'Trigger'; +$string['trigger_does_not_exist'] = 'Der Trigger existiert nicht.'; +$string['trigger_enabled'] = 'Aktiviert'; $string['trigger_instancename'] = 'Instanzname'; $string['trigger_instancename_help'] = 'Titel der Trigger-Instanz (nur sichtbar für Admins).'; -$string['trigger_enabled'] = 'Aktiviert'; +$string['trigger_settings_header'] = 'Spezifische Einstellungen des Triggertypen'; $string['trigger_sortindex'] = 'Hoch/Runter'; +$string['trigger_subpluginname'] = 'Subplugin Name'; +$string['trigger_subpluginname_help'] = 'Name des Schritt/Trigger-Subplugins (nur für Admins sichtbar).'; $string['trigger_workflow'] = 'Workflow'; - -$string['workflow'] = 'Workflow'; -$string['workflow_drafts_header'] = 'Workflow-Entwürfe'; -$string['active_workflows_header'] = 'Aktive Workflows'; -$string['add_workflow'] = 'Neuen Workflow hinzufügen'; $string['upload_workflow'] = 'Workflow hochladen'; -$string['create_workflow_from_existing'] = 'Kopie von bestehendem Workflow erstellen'; -$string['workflow_title'] = 'Titel'; -$string['workflow_title_help'] = 'Titel des Workflows (nur sichtbar für Admins).'; +$string['viewheading'] = 'Kurse verwalten'; +$string['viewsteps'] = 'Zeige Workflowschritte'; +$string['workflow'] = 'Workflow'; +$string['workflow_active'] = 'Aktiv'; +$string['workflow_definition_heading'] = 'Workflowdefinitionen'; +$string['workflow_delayforallworkflows'] = 'Ausschluss für alle Workflows?'; +$string['workflow_delayforallworkflows_help'] = 'Falls ja, wird ein Kurs für die oben genannte Zeit nicht nur von diesem, sondern + von allen Workflows ausgeschlossen. Das heißt, bis die Zeit abgelaufen ist, kann kein Prozess für den Kurs gestartet werden.'; $string['workflow_displaytitle'] = 'Angezeigter Titel des Workflows'; $string['workflow_displaytitle_help'] = 'Dieser Titel wird Nutzern beim Verwalten ihrer Kurse angezeigt.'; -$string['workflow_rollbackdelay'] = 'Kursauschluss beim Zurücksetzen'; -$string['workflow_rollbackdelay_help'] = 'Dieser Wert beschreibt die Zeit, bis wieder ein Prozess für diesen Workflow und einen Kurs - gestartet werden kann, nachdem der Kurs innerhalb eines Prozesses dieses Workflows zurückgesetzt wurde.'; +$string['workflow_drafts_header'] = 'Workflow-Entwürfe'; +$string['workflow_drafts_list'] = 'Zeige Workflow-Entwürfe'; +$string['workflow_duplicate_title'] = '{$a} (Kopie)'; $string['workflow_finishdelay'] = 'Kursauschluss bei Beendigung'; $string['workflow_finishdelay_help'] = 'Dieser Wert beschreibt die Zeit, bis wieder ein Prozess für diesen Workflow und einen Kurs gestartet werden kann, nachdem der Kurs einen Prozess dieses Workflows beendingt hat.'; -$string['workflow_delayforallworkflows'] = 'Ausschluss für alle Workflows?'; -$string['workflow_delayforallworkflows_help'] = 'Falls ja, wird ein Kurs für die oben genannte Zeit nicht nur von diesem, sondern - von allen Workflows ausgeschlossen. Das heißt, bis die Zeit abgelaufen ist, kann kein Prozess für den Kurs gestartet werden.'; -$string['workflow_active'] = 'Aktiv'; +$string['workflow_is_running'] = 'Workflow läuft.'; +$string['workflow_not_removeable'] = 'Es ist nicht möglich, diese Workflow-Instanz zu entfernen. Vielleicht hat sie noch laufende Prozesse?'; $string['workflow_processes'] = 'Aktive Prozesse'; -$string['workflow_timeactive'] = 'Aktiv seit'; +$string['workflow_rollbackdelay'] = 'Kursauschluss beim Zurücksetzen'; +$string['workflow_rollbackdelay_help'] = 'Dieser Wert beschreibt die Zeit, bis wieder ein Prozess für diesen Workflow und einen Kurs + gestartet werden kann, nachdem der Kurs innerhalb eines Prozesses dieses Workflows zurückgesetzt wurde.'; $string['workflow_sortindex'] = 'Hoch/RUnter'; -$string['workflow_tools'] = 'Aktionen'; -$string['viewsteps'] = 'Zeige Workflowschritte'; -$string['editworkflow'] = 'Allgemeine Einstellungen bearbeiten'; -$string['backupworkflow'] = 'Workflow sichern'; -$string['duplicateworkflow'] = 'Workflow duplizieren'; -$string['deleteworkflow'] = 'Workflow löschen'; -$string['deleteworkflow_confirm'] = 'Sie sind dabei, den Workflow zu löschen. Das kann nicht rückgängig gemacht werden. Sind Sie sicher?'; -$string['activateworkflow'] = 'Aktivieren'; -$string['disableworkflow'] = 'Workflow deaktivieren (Prozesse laufen weiter)'; -$string['disableworkflow_confirm'] = 'Sie sind dabei, den Workflow zu deaktivieren. Sind Sie sicher?'; -$string['abortdisableworkflow'] = 'Workfow deaktivieren (Prozesse werden abgebrochen, eventuell unsicher!)'; -$string['abortdisableworkflow_confirm'] = 'Sie sind dabei, den Workflow zu deaktivieren. Alle laufenden Prozesse werden abgebrochen. Sind Sie sicher?'; -$string['abortprocesses'] = 'Laufende Prozesse abbrechen (eventuell unsicher!)'; -$string['abortprocesses_confirm'] = 'Alle laufenden Prozesse dieses Workflows werden abgebrochen. Sind Sie sicher?'; -$string['workflow_duplicate_title'] = '{$a} (Kopie)'; - -// Deactivated workflows. -$string['deactivated_workflows_list'] = 'Zeige deaktivierte Workflows'; -$string['deactivated_workflows_list_header'] = 'Deaktivierte Workflows'; +$string['workflow_started'] = 'Workflow gestartet.'; +$string['workflow_timeactive'] = 'Aktiv seit'; $string['workflow_timedeactive'] = 'Deaktiviert seit'; -$string['active_workflows_list'] = 'Zeige aktive Workflows'; -$string['workflow_drafts_list'] = 'Zeige Workflow-Entwürfe'; - -$string['step_type'] = 'Typ'; -$string['step_subpluginname'] = 'Subpluginname'; -$string['step_subpluginname_help'] = 'Name des Schritt/Trigger-Subplugins (nur für Admins sichtbar).'; -$string['step_instancename'] = 'Instanzname'; -$string['step_instancename_help'] = 'Titel der Schritt/Trigger-Instanz (nur für Admins sichtbar).'; -$string['step_sortindex'] = 'Hoch/Runter'; -$string['step_edit'] = 'Bearbeiten'; -$string['step_show'] = 'Anzeigen'; -$string['step_delete'] = 'Entfernen'; - -$string['trigger'] = 'Trigger'; -$string['step'] = 'Schritt'; - +$string['workflow_title'] = 'Titel'; +$string['workflow_title_help'] = 'Titel des Workflows (nur sichtbar für Admins).'; +$string['workflow_tools'] = 'Aktionen'; $string['workflow_trigger'] = 'Trigger für den Workflow'; - -$string['lifecycletrigger'] = 'Trigger'; -$string['lifecyclestep'] = 'Schritt'; - -$string['subplugintype_lifecycletrigger'] = 'Trigger zum Starten eines Lifecycle-Prozesses'; -$string['subplugintype_lifecycletrigger_plural'] = 'Trigger zum Starten eines Lifecycle-Prozesses'; -$string['subplugintype_lifecyclestep'] = 'Schritt eines Lifecycle-Prozesses'; -$string['subplugintype_lifecyclestep_plural'] = 'Schritte eines Lifecycle-Prozesses'; - -$string['nointeractioninterface'] = 'Keine Interaktionsschnittstelle verfügbar!'; -$string['tools'] = 'Aktionen'; -$string['status'] = 'Status'; -$string['date'] = 'Fällligkeitsdatum'; - -$string['nostepfound'] = 'Es konnte kein Schritt mit der gegeben Schrittid gefunden werden!'; -$string['noprocessfound'] = 'Es konnte kein Prozess mit der gegebenen Prozessid gefunden werden!'; - -$string['nocoursestodisplay'] = 'Es gibt derzeit keine Kurse, die Ihre Aufmerksamkeit erfordern!'; -$string['noremainingcoursestodisplay'] = 'Es gibt derzeit keine verbleibenden Kurse!'; - -$string['course_backups_list_header'] = 'Kurssicherungen'; -$string['backupcreated'] = 'Erstellt am'; -$string['restore'] = 'Wiederherstellen'; -$string['download'] = 'Herunterladen'; - $string['workflownotfound'] = 'Es konnte kein Workflow mit der ID {$a} gefunden werden!'; - -// View.php. -$string['tablecoursesrequiringattention'] = 'Kurse, die Ihre Aufmerksamkeit erfordern!'; -$string['tablecoursesremaining'] = 'Restliche Kurse'; -$string['tablecourseslog'] = 'Vergangene Aktionen'; -$string['viewheading'] = 'Kurse verwalten'; -$string['interaction_success'] = 'Aktion erfolgreich gespeichert.'; -$string['manual_trigger_success'] = 'Workflow erfolgreich gestartet.'; -$string['manual_trigger_process_existed'] = 'Es existiert bereits ein Workflow für diesen Kurs.'; - -$string['coursename'] = 'Kursname'; -$string['lastaction'] = 'Letzte Aktion am'; - -$string['workflow_started'] = 'Workflow gestartet.'; -$string['workflow_is_running'] = 'Workflow läuft.'; - -// Backup & Restore. -$string['restore_workflow_not_found'] = 'Falsches Format der Sicherungsdatei. Der Workflow konnte nicht gefunden werden.'; -$string['restore_subplugins_invalid'] = 'Falsches Format der Sicherungsdatei. Das Format der Subpluginelemente ist nicht wie erwartet.'; -$string['restore_step_does_not_exist'] = 'Der Schritt {$a} ist nicht installiert, aber in der Sicherungsdatei enthalten. Bitte installieren Sie ihn zuerst und versuchen es dann erneut.'; -$string['restore_trigger_does_not_exist'] = 'Der Trigger {$a} ist nicht installiert, aber in der Sicherungsdatei enthalten. Bitte installieren Sie ihn zuerst und versuchen es dann erneut.'; - -$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.'; -$string['errorbackuppath'] = "Ein Fehler ist aufgetreten beim Versuchen das Backup Verzeichnis zu erstellen. -Ihnen fehlen wahrscheinlich die Berechtigung dazu. Bitte überprüfen Sie den Pfad unter -Seitenadministration/Plugins/Dienstprogramme/Kurs-Lebenszyklus/Allgemein & Subplugins."; -$string['errornobackup'] = "Es wurde kein Backup in dem angegebenen Pfad erstellt."; - -// Workflowoverview. $string['workflowoverview'] = 'Workflow ansehen'; $string['workflowoverview_list_header'] = 'Details zu Workflows'; -$string['create_step'] = 'Step erstellen'; -$string['create_trigger'] = 'Trigger erstellen'; -$string['edit_step'] = 'Step bearbeiten'; -$string['edit_trigger'] = 'Trigger bearbeiten'; -$string['move_up'] = 'Nach oben bewegen'; -$string['move_down'] = 'Nach unten bewegen'; -$string['courses_triggered'] = 'Kurse insgesamt getriggered: {$a}'; -$string['courses_excluded'] = 'Kurse insgesamt ausgeschlossen: {$a}'; -$string['courses_size'] = 'Kurse insgesamt genauer betrachtet: {$a}'; -$string['details:displaytitle'] = 'Wird Lehrenden als {$a} angezeigt.'; -$string['details:rollbackdelay'] = 'Nachdem ein Kurs zurückgesetzt wird, wird er für {$a} verzögert.'; -$string['details:finishdelay'] = 'Nachdem ein Kurs einen Workflow beendet, wird er für {$a} verzögert.'; -$string['details:globaldelay_yes'] = 'Diese Verzögerungen gelten für alle Workflows.'; -$string['details:globaldelay_no'] = 'Diese Verzögerungen gelten nur für diesen Workflow.'; -$string['courses_will_be_triggered_total'] = '{$a} Kurse werden insgesamt getriggert'; -$string['courses_will_be_excluded_total'] = '{$a} Kurse werden insgesamt ausgeschlossen'; -$string['courses_will_be_triggered'] = '{$a} Kurse werden getriggert'; -$string['courses_will_be_excluded'] = '{$a} Kurse werden ausgeschlossen'; -$string['overview:trigger'] = 'Trigger'; -$string['overview:trigger_help'] = 'Ein Kurs fängt nur dann an, einen Workflow zu durchlaufen, wenn alle Trigger des Workflows dies übereinstimmend (UND-Verknüpfung) aussagen.

-In den hier genannten Zahlen werden Kurse, die verzögert werden oder sich bereits in anderen Workflows befinden, nicht mitgezählt.
-Trotzdem sind die Zahlen nur approximiert, da es sein könnte, dass die Kurse vor diesem einen anderen Workflow auslösen.'; -$string['overview:add_trigger'] = 'Trigger hinzufügen'; -$string['overview:add_trigger_help'] = 'Es kann nur eine Instanz jedes Triggertyps hinzugefügt werden.'; - -// Create copy from existing. -$string['create_copy'] = 'Kopie erstellen'; -$string['active'] = 'Aktiv'; -$string['deactivated'] = 'Deaktiviert'; -$string['draft'] = 'Entwurf'; diff --git a/lang/en/tool_lifecycle.php b/lang/en/tool_lifecycle.php index 9d0bb75e..1d96728d 100644 --- a/lang/en/tool_lifecycle.php +++ b/lang/en/tool_lifecycle.php @@ -22,244 +22,216 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - -$string['pluginname'] = 'Life Cycle'; -$string['plugintitle'] = 'Course Life Cycle'; +$string['abortdisableworkflow'] = 'Disable workflow (abort processes, maybe unsafe!)'; +$string['abortdisableworkflow_confirm'] = 'The workflow is going to be disabled and all running processes of this workflow will be aborted. Are you sure?'; +$string['abortprocesses'] = 'Abort running processes (maybe unsafe!)'; +$string['abortprocesses_confirm'] = 'All running processes of this workflow will be aborted. Are you sure?'; +$string['activateworkflow'] = 'Activate'; +$string['active'] = 'Active'; +$string['active_automatic_workflows_heading'] = 'Active automatic workflows'; +$string['active_manual_workflows_heading'] = 'Active manual workflows'; +$string['active_workflow_not_changeable'] = 'The workflow instance was already activated. Depending on the step type, some of its settings might be still editable. Changes to triggers will not affect already triggered courses.'; +$string['active_workflow_not_removeable'] = 'The workflow instance is active. It is not possible to remove it.'; +$string['active_workflows_header'] = 'Active workflows'; +$string['active_workflows_list'] = 'List active workflows'; +$string['add_new_step_instance'] = 'Add new step instance...'; +$string['add_new_trigger_instance'] = 'Add new trigger instance...'; +$string['add_workflow'] = 'Create new workflow'; +$string['adminsettings_edit_step_instance_heading'] = 'Step instance for workflow \'{$a}\''; +$string['adminsettings_edit_trigger_instance_heading'] = 'Trigger for workflow \'{$a}\''; +$string['adminsettings_edit_workflow_definition_heading'] = 'Workflow definition'; +$string['adminsettings_heading'] = 'Workflow settings'; +$string['adminsettings_workflow_definition_steps_heading'] = 'Workflow steps'; +$string['all_delays'] = 'All delays'; +$string['anonymous_user'] = 'Anonymous User'; +$string['apply'] = 'Apply'; +$string['backupcreated'] = 'Created at'; +$string['backupworkflow'] = 'Backup workflow'; $string['cachedef_mformdata'] = 'Caches the mform data.'; - -$string['lifecycle:managecourses'] = 'May manage courses in tool_lifecycle'; -$string['managecourses_link'] = 'Manage courses'; - -$string['general_config_header'] = "General & subplugins"; +$string['cannot_trigger_workflow_manually'] = 'The requested workflow could not be triggered manually.'; +$string['config_backup_path'] = 'Path of the lifecycle backup folder'; +$string['config_backup_path_desc'] = 'This settings defines the storage location of the backups created by the backup step. +The path has to be specified as an absolute path on your server.'; $string['config_delay_duration'] = 'Default duration of a course delay'; $string['config_delay_duration_desc'] = 'This setting defines the default delay duration of a workflow in case one of its processes is rolled back or finishes. The delay duration determines how long a course will be excepted from being processed again in either of the cases.'; -$string['config_backup_path'] = 'Path of the lifecycle backup folder'; -$string['config_backup_path_desc'] = 'This settings defines the storage location of the backups created by the backup step. -The path has to be specified as an absolute path on your server.'; +$string['config_showcoursecounts'] = 'Show amount of courses which will be triggered'; +$string['config_showcoursecounts_desc'] = 'The workflow overview page by default shows the amount of courses which will be +triggered by the configured triggers which can be load heavy. Disable this option if you experience issues loading the workflow +overview.'; +$string['course_backups_list_header'] = 'Course backups'; +$string['courseid'] = 'Course ID'; +$string['coursename'] = 'Course name'; +$string['courses_will_be_excluded'] = '{$a} Courses will be excluded'; +$string['courses_will_be_excluded_total'] = '{$a} courses will be excluded in total'; +$string['courses_will_be_triggered'] = '{$a} Courses will be triggered'; +$string['courses_will_be_triggered_total'] = '{$a} courses will be triggered in total'; +$string['create_copy'] = 'Create copy'; +$string['create_step'] = 'Create step'; +$string['create_trigger'] = 'Create trigger'; +$string['create_workflow_from_existing'] = 'Copy new workflow from existing'; +$string['date'] = 'Due date'; +$string['deactivated'] = 'Deactivated'; +$string['deactivated_workflows_list'] = 'List deactivated workflows'; +$string['deactivated_workflows_list_header'] = 'Deactivated workflows'; +$string['delayed_courses_header'] = 'Delayed courses'; +$string['delayed_for_workflow_until'] = 'Delayed for "{$a->name}" until {$a->date}'; +$string['delayed_for_workflows'] = 'Delayed for {$a} workflows'; +$string['delayed_globally'] = 'Delayed globally until {$a}'; +$string['delayed_globally_and_seperately'] = 'Delayed globally and seperately for {$a} workflows'; +$string['delayed_globally_and_seperately_for_one'] = 'Delayed globally and seperately for 1 workflow'; +$string['delays'] = 'Delays'; +$string['delays_for_workflow'] = 'Delays for "{$a}"'; +$string['delete_all_delays'] = 'Delete all delays'; +$string['delete_delay'] = 'Delete delay'; +$string['deleteworkflow'] = 'Delete workflow'; +$string['deleteworkflow_confirm'] = 'The workflow is going to be deleted. This can\'t be undone. Are you sure?'; +$string['details:displaytitle'] = 'Displayed to teachers as {$a}.'; +$string['details:finishdelay'] = 'When a course has finished the workflow, it will be delayed for {$a}.'; +$string['details:globaldelay_no'] = 'These delays apply only to this workflow.'; +$string['details:globaldelay_yes'] = 'These delays apply to all workflows.'; +$string['details:rollbackdelay'] = 'When a course is rolled back, it will be delayed for {$a}.'; +$string['disableworkflow'] = 'Disable workflow (processes keep running)'; +$string['disableworkflow_confirm'] = 'The workflow is going to be disabled. Are you sure?'; +$string['download'] = 'Download'; +$string['draft'] = 'Draft'; +$string['duplicateworkflow'] = 'Duplicate workflow'; +$string['edit_step'] = 'Edit step'; +$string['edit_trigger'] = 'Edit trigger'; +$string['editworkflow'] = 'Edit general settings'; +$string['error_wrong_trigger_selected'] = 'You tried to request a non-manual trigger.'; +$string['errorbackuppath'] = "Error while trying to create the backup directory. You might be missing the permission to do so. +Please check your path at Site administration/Plugins/Admin tools/Life Cycle/General & subplugins/backup_path."; +$string['errornobackup'] = "No backup was created at the specified directory, reasons unknown."; $string['find_course_list_header'] = 'Find courses'; -$string['adminsettings_heading'] = 'Workflow settings'; -$string['active_manual_workflows_heading'] = 'Active manual workflows'; -$string['active_automatic_workflows_heading'] = 'Active automatic workflows'; -$string['see_in_workflow'] = 'See in workflow'; -$string['workflow_definition_heading'] = 'Workflow definitions'; -$string['adminsettings_edit_workflow_definition_heading'] = 'Workflow definition'; -$string['adminsettings_workflow_definition_steps_heading'] = 'Workflow steps'; -$string['adminsettings_edit_trigger_instance_heading'] = 'Trigger for workflow \'{$a}\''; -$string['adminsettings_edit_step_instance_heading'] = 'Step instance for workflow \'{$a}\''; -$string['add_new_step_instance'] = 'Add new step instance...'; -$string['add_new_trigger_instance'] = 'Add new trigger instance...'; -$string['step_settings_header'] = 'Specific settings of the step type'; -$string['trigger_settings_header'] = 'Specific settings of the trigger type'; -$string['general_settings_header'] = 'General settings'; $string['followedby_none'] = 'None'; +$string['force_import'] = 'Try ignoring errors and import the workflow anyway. Use this at your own risk!'; +$string['forselected'] = 'For all selected processes'; +$string['general_config_header'] = "General & subplugins"; +$string['general_settings_header'] = 'General settings'; +$string['globally'] = 'Global delays'; +$string['globally_until_date'] = 'Globally until {$a}'; +$string['interaction_success'] = 'Action successfully saved.'; $string['invalid_workflow'] = 'Invalid workflow configuration'; -$string['invalid_workflow_details'] = 'Go to details view, to create a trigger for this workflow'; -$string['active_workflow_not_changeable'] = 'The workflow instance was already activated. Depending on the step type, some of its settings might be still editable. Changes to triggers will not affect already triggered courses.'; -$string['active_workflow_not_removeable'] = 'The workflow instance is active. It is not possible to remove it.'; -$string['workflow_not_removeable'] = 'It is not possible to remove this workflow instance. Maybe it still has running processes?'; $string['invalid_workflow_cannot_be_activated'] = 'The workflow definition is invalid, thus it cannot be activated.'; -$string['trigger_does_not_exist'] = 'The requested trigger could not be found.'; -$string['cannot_trigger_workflow_manually'] = 'The requested workflow could not be triggered manually.'; -$string['error_wrong_trigger_selected'] = 'You tried to request a non-manual trigger.'; - -$string['lifecycle_task'] = 'Run the life cycle processes'; +$string['invalid_workflow_details'] = 'Go to details view, to create a trigger for this workflow'; +$string['lastaction'] = 'Last action on'; +$string['lifecycle:managecourses'] = 'May manage courses in tool_lifecycle'; $string['lifecycle_cleanup_task'] = 'Delete old delay entries for life cycle workflows'; - -$string['trigger_subpluginname'] = 'Subplugin name'; -$string['trigger_subpluginname_help'] = 'Step subplugin/trigger title (visible for admins only).'; +$string['lifecycle_error_notify_task'] = 'Notify the admin upon errors in tool_lifecycle processes'; +$string['lifecycle_task'] = 'Run the life cycle processes'; +$string['lifecyclestep'] = 'Process step'; +$string['lifecycletrigger'] = 'Trigger'; +$string['managecourses_link'] = 'Manage courses'; +$string['manual_trigger_process_existed'] = 'A workflow for this course already exists.'; +$string['manual_trigger_success'] = 'Workflow started successfully.'; +$string['move_down'] = 'Move down'; +$string['move_up'] = 'Move up'; +$string['name_until_date'] = '"{$a->name}" until {$a->date}'; +$string['nocoursestodisplay'] = 'There are currently no courses which require your attention!'; +$string['nointeractioninterface'] = 'No interaction interface available!'; +$string['noprocesserrors'] = 'There are no process errors to handle!'; +$string['noprocessfound'] = 'A process with the given processid could not be found!'; +$string['noremainingcoursestodisplay'] = 'There are currently no remaining courses!'; +$string['nostepfound'] = 'A step with the given stepid could not be found!'; +$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.'; +$string['notifyerrorsemailsubject'] = 'There are {$a->amount} new tool_lifecycle process errors waiting to be fixed!'; +$string['overview:add_trigger'] = 'Add trigger'; +$string['overview:add_trigger_help'] = 'You can only add one instance of each trigger type.'; +$string['overview:trigger'] = 'Trigger'; +$string['overview:trigger_help'] = 'A course will only trigger a workflow, if all triggers agree on it (AND operation).

+Courses which are delayed, or already in another workflow are not included in the displayed counts.
+Still, these numbers are only approximates, since it could be that a course is excluded by another workflow, or will trigger another workflow before this one.'; +$string['pluginname'] = 'Life Cycle'; +$string['plugintitle'] = 'Course Life Cycle'; +$string['privacy:metadata:tool_lifecycle_action_log'] = 'A log of actions done by course managers.'; +$string['privacy:metadata:tool_lifecycle_action_log:action'] = 'Identifier of the action that was done.'; +$string['privacy:metadata:tool_lifecycle_action_log:courseid'] = 'ID of the Course the action was done for'; +$string['privacy:metadata:tool_lifecycle_action_log:processid'] = 'ID of the Process the action was done in.'; +$string['privacy:metadata:tool_lifecycle_action_log:stepindex'] = 'Index of the Step in the Workflow, the action was done for.'; +$string['privacy:metadata:tool_lifecycle_action_log:time'] = 'Time when the action was done.'; +$string['privacy:metadata:tool_lifecycle_action_log:userid'] = 'ID of the user that did the action.'; +$string['privacy:metadata:tool_lifecycle_action_log:workflowid'] = 'ID of the Workflow the action was done in.'; +$string['proceed'] = 'Proceed'; +$string['process_errors_header'] = 'Error handling'; +$string['process_proceeded_event'] = 'A process has been proceeded'; +$string['process_rollback_event'] = 'A process has been rolled back'; +$string['process_triggered_event'] = 'A process has been triggered'; +$string['restore'] = 'Restore'; +$string['restore_error_in_step'] = 'An error occurred when importing step "{$a}": '; +$string['restore_error_in_trigger'] = 'An error occurred when importing trigger "{$a}": '; +$string['restore_step_does_not_exist'] = 'The step {$a} is not installed, but is included in the backup file. Please installed it first and try again.'; +$string['restore_subplugins_invalid'] = 'Wrong format of the backup file. The structure of the subplugin elements is not as expected.'; +$string['restore_trigger_does_not_exist'] = 'The trigger {$a} is not installed, but is included in the backup file. Please installed it first and try again.'; +$string['restore_workflow_not_found'] = 'Wrong format of the backup file. The workflow could not be found.'; +$string['rollback'] = 'Rollback'; +$string['see_in_workflow'] = 'See in workflow'; +$string['show_delays'] = 'Kind of view'; +$string['status'] = 'Status'; +$string['step'] = 'Process step'; +$string['step_delete'] = 'Delete'; +$string['step_edit'] = 'Edit'; +$string['step_instancename'] = 'Instance name'; +$string['step_instancename_help'] = 'Step instance title (visible for admins only).'; +$string['step_settings_header'] = 'Specific settings of the step type'; +$string['step_show'] = 'Show'; +$string['step_sortindex'] = 'Up/Down'; +$string['step_subpluginname'] = 'Subplugin name'; +$string['step_subpluginname_help'] = 'Step subplugin/trigger title (visible for admins only).'; +$string['step_type'] = 'Type'; +$string['subplugintype_lifecyclestep'] = 'Step within a lifecycle process'; +$string['subplugintype_lifecyclestep_plural'] = 'Steps within a lifecycle process'; +$string['subplugintype_lifecycletrigger'] = 'Trigger for starting a lifecycle process'; +$string['subplugintype_lifecycletrigger_plural'] = 'Triggers for starting a lifecycle process'; +$string['tablecourseslog'] = 'Past actions'; +$string['tablecoursesremaining'] = 'Remaining courses'; +$string['tablecoursesrequiringattention'] = 'Courses that require your attention'; +$string['tools'] = 'Tools'; +$string['trigger'] = 'Trigger'; +$string['trigger_does_not_exist'] = 'The requested trigger could not be found.'; +$string['trigger_enabled'] = 'Enabled'; $string['trigger_instancename'] = 'Instance name'; $string['trigger_instancename_help'] = 'Trigger instance title (visible for admins only).'; -$string['trigger_enabled'] = 'Enabled'; +$string['trigger_settings_header'] = 'Specific settings of the trigger type'; $string['trigger_sortindex'] = 'Up/Down'; +$string['trigger_subpluginname'] = 'Subplugin name'; +$string['trigger_subpluginname_help'] = 'Step subplugin/trigger title (visible for admins only).'; $string['trigger_workflow'] = 'Workflow'; - -$string['workflow'] = 'Workflow'; -$string['workflow_drafts_header'] = 'Workflow drafts'; -$string['active_workflows_header'] = 'Active workflows'; -$string['add_workflow'] = 'Create new workflow'; $string['upload_workflow'] = 'Upload workflow'; -$string['create_workflow_from_existing'] = 'Copy new workflow from existing'; -$string['workflow_title'] = 'Title'; -$string['workflow_title_help'] = 'Workflow title (visible for admins only).'; +$string['viewheading'] = 'Manage courses'; +$string['viewsteps'] = 'View workflow steps'; +$string['workflow'] = 'Workflow'; +$string['workflow_active'] = 'Active'; +$string['workflow_definition_heading'] = 'Workflow definitions'; +$string['workflow_delayforallworkflows'] = 'Delay for all workflows?'; +$string['workflow_delayforallworkflows_help'] = 'If ticked, the durations on top do not only delay the execution +of this workflow for a course, but for all other workflows as well. Thus, until the time passes no process can be started +for the respective course.'; $string['workflow_displaytitle'] = 'Displayed workflow title'; $string['workflow_displaytitle_help'] = 'This title is displayed to users when managing their courses.'; -$string['workflow_rollbackdelay'] = 'Delay in case of rollback'; -$string['workflow_rollbackdelay_help'] = 'If a course was rolled back within a process instance of this workflow, -this value describes the time until a process for this combination of course and workflow can be started again.'; +$string['workflow_drafts_header'] = 'Workflow drafts'; +$string['workflow_drafts_list'] = 'List workflow drafts'; +$string['workflow_duplicate_title'] = '{$a} (Copy)'; $string['workflow_finishdelay'] = 'Delay in case of finished course'; $string['workflow_finishdelay_help'] = 'If a course has finished a process instance of this workflow, this value describes the time until a process for this combination of course and workflow can be started again.'; -$string['workflow_delayforallworkflows'] = 'Delay for all workflows?'; -$string['workflow_delayforallworkflows_help'] = 'If ticked, the durations on top do not only delay the execution -of this workflow for a course, but for all other workflows as well. Thus, until the time passes no process can be started -for the respective course.'; -$string['workflow_active'] = 'Active'; +$string['workflow_is_running'] = 'Workflow is running.'; +$string['workflow_not_removeable'] = 'It is not possible to remove this workflow instance. Maybe it still has running processes?'; $string['workflow_processes'] = 'Active processes'; -$string['workflow_timeactive'] = 'Active since'; +$string['workflow_rollbackdelay'] = 'Delay in case of rollback'; +$string['workflow_rollbackdelay_help'] = 'If a course was rolled back within a process instance of this workflow, +this value describes the time until a process for this combination of course and workflow can be started again.'; $string['workflow_sortindex'] = 'Up/Down'; -$string['workflow_tools'] = 'Actions'; -$string['viewsteps'] = 'View workflow steps'; -$string['editworkflow'] = 'Edit general settings'; -$string['backupworkflow'] = 'Backup workflow'; -$string['duplicateworkflow'] = 'Duplicate workflow'; -$string['deleteworkflow'] = 'Delete workflow'; -$string['deleteworkflow_confirm'] = 'The workflow is going to be deleted. This can\'t be undone. Are you sure?'; -$string['activateworkflow'] = 'Activate'; -$string['disableworkflow'] = 'Disable workflow (processes keep running)'; -$string['disableworkflow_confirm'] = 'The workflow is going to be disabled. Are you sure?'; -$string['abortdisableworkflow'] = 'Disable workflow (abort processes, maybe unsafe!)'; -$string['abortdisableworkflow_confirm'] = 'The workflow is going to be disabled and all running processes of this workflow will be aborted. Are you sure?'; -$string['abortprocesses'] = 'Abort running processes (maybe unsafe!)'; -$string['abortprocesses_confirm'] = 'All running processes of this workflow will be aborted. Are you sure?'; -$string['workflow_duplicate_title'] = '{$a} (Copy)'; - -// Deactivated workflows. -$string['deactivated_workflows_list'] = 'List deactivated workflows'; -$string['deactivated_workflows_list_header'] = 'Deactivated workflows'; +$string['workflow_started'] = 'Workflow started.'; +$string['workflow_timeactive'] = 'Active since'; $string['workflow_timedeactive'] = 'Deactivated since'; -$string['active_workflows_list'] = 'List active workflows'; -$string['workflow_drafts_list'] = 'List workflow drafts'; - -$string['step_type'] = 'Type'; -$string['step_subpluginname'] = 'Subplugin name'; -$string['step_subpluginname_help'] = 'Step subplugin/trigger title (visible for admins only).'; -$string['step_instancename'] = 'Instance name'; -$string['step_instancename_help'] = 'Step instance title (visible for admins only).'; -$string['step_sortindex'] = 'Up/Down'; -$string['step_edit'] = 'Edit'; -$string['step_show'] = 'Show'; -$string['step_delete'] = 'Delete'; - -$string['trigger'] = 'Trigger'; -$string['step'] = 'Process step'; - +$string['workflow_title'] = 'Title'; +$string['workflow_title_help'] = 'Workflow title (visible for admins only).'; +$string['workflow_tools'] = 'Actions'; $string['workflow_trigger'] = 'Trigger for the workflow'; - -$string['lifecycletrigger'] = 'Trigger'; -$string['lifecyclestep'] = 'Process step'; - -$string['subplugintype_lifecycletrigger'] = 'Trigger for starting a lifecycle process'; -$string['subplugintype_lifecycletrigger_plural'] = 'Triggers for starting a lifecycle process'; -$string['subplugintype_lifecyclestep'] = 'Step within a lifecycle process'; -$string['subplugintype_lifecyclestep_plural'] = 'Steps within a lifecycle process'; - -$string['nointeractioninterface'] = 'No interaction interface available!'; -$string['tools'] = 'Tools'; -$string['status'] = 'Status'; -$string['date'] = 'Due date'; - -$string['nostepfound'] = 'A step with the given stepid could not be found!'; -$string['noprocessfound'] = 'A process with the given processid could not be found!'; - -$string['nocoursestodisplay'] = 'There are currently no courses which require your attention!'; -$string['noremainingcoursestodisplay'] = 'There are currently no remaining courses!'; - -$string['course_backups_list_header'] = 'Course backups'; -$string['backupcreated'] = 'Created at'; -$string['restore'] = 'Restore'; -$string['download'] = 'Download'; - +$string['workflow_was_not_imported'] = 'The workflow was not imported!'; $string['workflownotfound'] = 'Workflow with id {$a} could not be found'; - -// View.php. -$string['tablecoursesrequiringattention'] = 'Courses that require your attention'; -$string['tablecoursesremaining'] = 'Remaining courses'; -$string['tablecourseslog'] = 'Past actions'; -$string['viewheading'] = 'Manage courses'; -$string['interaction_success'] = 'Action successfully saved.'; -$string['manual_trigger_success'] = 'Workflow started successfully.'; -$string['manual_trigger_process_existed'] = 'A workflow for this course already exists.'; - -$string['coursename'] = 'Course name'; -$string['lastaction'] = 'Last action on'; -$string['anonymous_user'] = 'Anonymous User'; - -$string['workflow_started'] = 'Workflow started.'; -$string['workflow_is_running'] = 'Workflow is running.'; - -// Backup & Restore. -$string['restore_workflow_not_found'] = 'Wrong format of the backup file. The workflow could not be found.'; -$string['restore_subplugins_invalid'] = 'Wrong format of the backup file. The structure of the subplugin elements is not as expected.'; -$string['restore_step_does_not_exist'] = 'The step {$a} is not installed, but is included in the backup file. Please installed it first and try again.'; -$string['restore_trigger_does_not_exist'] = 'The trigger {$a} is not installed, but is included in the backup file. Please installed it first and try again.'; - -// Events. -$string['process_triggered_event'] = 'A process has been triggered'; -$string['process_proceeded_event'] = 'A process has been proceeded'; -$string['process_rollback_event'] = 'A process has been rolled back'; - -// Privacy API. -$string['privacy:metadata:tool_lifecycle_action_log'] = 'A log of actions done by course managers.'; -$string['privacy:metadata:tool_lifecycle_action_log:processid'] = 'ID of the Process the action was done in.'; -$string['privacy:metadata:tool_lifecycle_action_log:workflowid'] = 'ID of the Workflow the action was done in.'; -$string['privacy:metadata:tool_lifecycle_action_log:courseid'] = 'ID of the Course the action was done for'; -$string['privacy:metadata:tool_lifecycle_action_log:stepindex'] = 'Index of the Step in the Workflow, the action was done for.'; -$string['privacy:metadata:tool_lifecycle_action_log:time'] = 'Time when the action was done.'; -$string['privacy:metadata:tool_lifecycle_action_log:userid'] = 'ID of the user that did the action.'; -$string['privacy:metadata:tool_lifecycle_action_log:action'] = 'Identifier of the action that was done.'; - -// Delays. -$string['delayed_courses_header'] = 'Delayed courses'; -$string['delete_delay'] = 'Delete delay'; -$string['globally_until_date'] = 'Globally until {$a}'; -$string['name_until_date'] = '"{$a->name}" until {$a->date}'; -$string['delayed_globally_and_seperately'] = 'Delayed globally and seperately for {$a} workflows'; -$string['delayed_globally_and_seperately_for_one'] = 'Delayed globally and seperately for 1 workflow'; -$string['delayed_globally'] = 'Delayed globally until {$a}'; -$string['delayed_for_workflow_until'] = 'Delayed for "{$a->name}" until {$a->date}'; -$string['delayed_for_workflows'] = 'Delayed for {$a} workflows'; -$string['delays'] = 'Delays'; -$string['apply'] = 'Apply'; -$string['show_delays'] = 'Kind of view'; -$string['all_delays'] = 'All delays'; -$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.'; -$string['errorbackuppath'] = "Error while trying to create the backup directory. You might be missing the permission to do so. -Please check your path at Site administration/Plugins/Admin tools/Life Cycle/General & subplugins/backup_path."; -$string['errornobackup'] = "No backup was created at the specified directory, reasons unknown."; - -// Workflowoverview. $string['workflowoverview'] = 'View workflow'; $string['workflowoverview_list_header'] = 'Details of Workflows'; -$string['create_step'] = 'Create step'; -$string['create_trigger'] = 'Create trigger'; -$string['edit_step'] = 'Edit step'; -$string['edit_trigger'] = 'Edit trigger'; -$string['move_up'] = 'Move up'; -$string['move_down'] = 'Move down'; -$string['details:displaytitle'] = 'Displayed to teachers as {$a}.'; -$string['details:rollbackdelay'] = 'When a course is rolled back, it will be delayed for {$a}.'; -$string['details:finishdelay'] = 'When a course has finished the workflow, it will be delayed for {$a}.'; -$string['details:globaldelay_yes'] = 'These delays apply to all workflows.'; -$string['details:globaldelay_no'] = 'These delays apply only to this workflow.'; -$string['courses_will_be_triggered_total'] = '{$a} courses will be triggered in total'; -$string['courses_will_be_excluded_total'] = '{$a} courses will be excluded in total'; -$string['courses_will_be_triggered'] = '{$a} Courses will be triggered'; -$string['courses_will_be_excluded'] = '{$a} Courses will be excluded'; -$string['overview:trigger'] = 'Trigger'; -$string['overview:trigger_help'] = 'A course will only trigger a workflow, if all triggers agree on it (AND operation).

-Courses which are delayed, or already in another workflow are not included in the displayed counts.
-Still, these numbers are only approximates, since it could be that a course is excluded by another workflow, or will trigger another workflow before this one.'; -$string['overview:add_trigger'] = 'Add trigger'; -$string['overview:add_trigger_help'] = 'You can only add one instance of each trigger type.'; - -// Create copy from existing workflow. -$string['create_copy'] = 'Create copy'; -$string['active'] = 'Active'; -$string['deactivated'] = 'Deactivated'; -$string['draft'] = 'Draft'; diff --git a/lib.php b/lib.php index fa4532ae..072cff6c 100644 --- a/lib.php +++ b/lib.php @@ -32,7 +32,7 @@ * @throws moodle_exception */ function tool_lifecycle_extend_navigation_course($navigation, $course, $context) { - global $PAGE; + global $DB, $PAGE; // Only add this settings item on non-site course pages. if (!$PAGE->course || $PAGE->course->id == SITEID) { @@ -43,12 +43,23 @@ function tool_lifecycle_extend_navigation_course($navigation, $course, $context) return null; } - $url = null; - $settingnode = null; + $cache = cache::make('tool_lifecycle', 'application'); + if ($cache->has('workflowactive')) { + $wfexists = $cache->get('workflowactive'); + } else { + $wfexists = $DB->record_exists_sql("SELECT 'yes' FROM {tool_lifecycle_workflow} wf " . + "JOIN {tool_lifecycle_trigger} t ON wf.id = t.workflowid " . + "WHERE wf.timeactive IS NOT NULL AND t.subpluginname NOT IN ('sitecourse', 'delayedcourses')"); + $cache->set('workflowactive', $wfexists); + } + + if (!$wfexists) { + return null; + } - $url = new moodle_url('/admin/tool/lifecycle/view.php', array( - 'contextid' => $context->id - )); + $url = new moodle_url('/admin/tool/lifecycle/view.php', [ + 'contextid' => $context->id, + ]); // Add the course life cycle link. $linktext = get_string('managecourses_link', 'tool_lifecycle'); diff --git a/renderer.php b/renderer.php index f17197d3..6d3db9e7 100644 --- a/renderer.php +++ b/renderer.php @@ -53,15 +53,11 @@ public function header($title = null) { /** * Renders the workflow upload form including errors, which occured during upload. * @param \tool_lifecycle\local\form\form_upload_workflow $form - * @param array $errors * @throws coding_exception */ - public function render_workflow_upload_form($form, $errors = array()) { + public function render_workflow_upload_form($form) { $this->header(get_string('adminsettings_edit_workflow_definition_heading', 'tool_lifecycle')); - foreach ($errors as $error) { - \core\notification::add($error, \core\notification::ERROR); - } - echo $form->render(); + $form->display(); $this->footer(); } diff --git a/restore.php b/restore.php index 48551f0d..40ee3367 100644 --- a/restore.php +++ b/restore.php @@ -21,6 +21,7 @@ * @copyright 2017 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + require_once(__DIR__ . '/../../../config.php'); use tool_lifecycle\local\manager\backup_manager; diff --git a/settings.php b/settings.php index f1d37919..3f37c086 100644 --- a/settings.php +++ b/settings.php @@ -42,6 +42,11 @@ get_string('config_backup_path_desc', 'tool_lifecycle'), $CFG->dataroot . DIRECTORY_SEPARATOR . 'lifecycle_backups')); + $settings->add(new admin_setting_configcheckbox('tool_lifecycle/showcoursecounts', + get_string('config_showcoursecounts', 'tool_lifecycle'), + get_string('config_showcoursecounts_desc', 'tool_lifecycle'), + 1)); + $ADMIN->add('lifecycle_category', new admin_externalpage('tool_lifecycle_workflow_drafts', get_string('workflow_drafts_header', 'tool_lifecycle'), new moodle_url(\tool_lifecycle\urls::WORKFLOW_DRAFTS))); diff --git a/step/createbackup/classes/privacy/provider.php b/step/createbackup/classes/privacy/provider.php index 306f0a82..9fba71a4 100644 --- a/step/createbackup/classes/privacy/provider.php +++ b/step/createbackup/classes/privacy/provider.php @@ -34,7 +34,7 @@ class provider implements null_provider { * * @return string the reason */ - public static function get_reason() : string { + public static function get_reason(): string { return 'privacy:metadata'; } } diff --git a/step/createbackup/db/upgrade.php b/step/createbackup/db/upgrade.php index d1583cd7..56a1a62b 100644 --- a/step/createbackup/db/upgrade.php +++ b/step/createbackup/db/upgrade.php @@ -45,7 +45,7 @@ function xmldb_lifecyclestep_createbackup_upgrade($oldversion) { foreach ($coursedeletesteps as $step) { if (empty(settings_manager::get_settings($step->id, 'step'))) { settings_manager::save_settings($step->id, 'step', 'createbackup', - array($settingsname => $settingsvalue)); + [$settingsname => $settingsvalue]); } } diff --git a/step/createbackup/lang/de/lifecyclestep_createbackup.php b/step/createbackup/lang/de/lifecyclestep_createbackup.php index 12cc46d4..285e96e2 100644 --- a/step/createbackup/lang/de/lifecyclestep_createbackup.php +++ b/step/createbackup/lang/de/lifecyclestep_createbackup.php @@ -22,7 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['maximumbackupspercron'] = 'Maximale Anzahl an Sicherungen per cron'; $string['pluginname'] = 'Kurssicherungs-Schritt'; $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; -$string['maximumbackupspercron'] = 'Maximale Anzahl an Sicherungen per cron'; diff --git a/step/createbackup/lang/en/lifecyclestep_createbackup.php b/step/createbackup/lang/en/lifecyclestep_createbackup.php index 693e7fa6..bbea16bc 100644 --- a/step/createbackup/lang/en/lifecyclestep_createbackup.php +++ b/step/createbackup/lang/en/lifecyclestep_createbackup.php @@ -22,7 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['maximumbackupspercron'] = 'Maximum number of backups per cron'; $string['pluginname'] = 'Create backup step'; $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; -$string['maximumbackupspercron'] = 'Maximum number of backups per cron'; diff --git a/step/createbackup/lib.php b/step/createbackup/lib.php index ae38c21c..18724439 100644 --- a/step/createbackup/lib.php +++ b/step/createbackup/lib.php @@ -100,9 +100,9 @@ public function get_subpluginname() { * @return instance_setting[] containing settings keys and PARAM_TYPES */ public function instance_settings() { - return array( + return [ new instance_setting('maximumbackupspercron', PARAM_INT, true), - ); + ]; } /** diff --git a/step/deletecourse/classes/privacy/provider.php b/step/deletecourse/classes/privacy/provider.php index 6ab29e62..affe4e59 100644 --- a/step/deletecourse/classes/privacy/provider.php +++ b/step/deletecourse/classes/privacy/provider.php @@ -34,7 +34,7 @@ class provider implements null_provider { * * @return string the reason */ - public static function get_reason() : string { + public static function get_reason(): string { return 'privacy:metadata'; } } diff --git a/step/deletecourse/db/upgrade.php b/step/deletecourse/db/upgrade.php index c8467c5e..43560660 100644 --- a/step/deletecourse/db/upgrade.php +++ b/step/deletecourse/db/upgrade.php @@ -49,7 +49,7 @@ function xmldb_lifecyclestep_deletecourse_upgrade($oldversion) { foreach ($coursedeletesteps as $step) { if (empty(settings_manager::get_settings($step->id, 'step'))) { settings_manager::save_settings($step->id, 'step', 'deletecourse', - array($settingsname => $settingsvalue)); + [$settingsname => $settingsvalue]); } } diff --git a/step/deletecourse/lang/de/lifecyclestep_deletecourse.php b/step/deletecourse/lang/de/lifecyclestep_deletecourse.php index 62c1f8fd..316d0281 100644 --- a/step/deletecourse/lang/de/lifecyclestep_deletecourse.php +++ b/step/deletecourse/lang/de/lifecyclestep_deletecourse.php @@ -22,7 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['deletecourse_maximumdeletionspercron'] = 'Maximale Anzahl an Kurslöschungen per cron'; $string['pluginname'] = 'Kurslöschen-Schritt'; $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; -$string['deletecourse_maximumdeletionspercron'] = 'Maximale Anzahl an Kurslöschungen per cron'; diff --git a/step/deletecourse/lang/en/lifecyclestep_deletecourse.php b/step/deletecourse/lang/en/lifecyclestep_deletecourse.php index 5e6f337f..90819692 100644 --- a/step/deletecourse/lang/en/lifecyclestep_deletecourse.php +++ b/step/deletecourse/lang/en/lifecyclestep_deletecourse.php @@ -22,7 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['deletecourse_maximumdeletionspercron'] = 'Maximum number of courses deleted per cron'; $string['pluginname'] = 'Delete course step'; $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; -$string['deletecourse_maximumdeletionspercron'] = 'Maximum number of courses deleted per cron'; diff --git a/step/deletecourse/lib.php b/step/deletecourse/lib.php index 3503f159..098f512a 100644 --- a/step/deletecourse/lib.php +++ b/step/deletecourse/lib.php @@ -94,9 +94,9 @@ public function get_subpluginname() { * @return instance_setting[] containing settings keys and PARAM_TYPES */ public function instance_settings() { - return array( + return [ new instance_setting('maximumdeletionspercron', PARAM_INT, true), - ); + ]; } /** diff --git a/step/duplicate/classes/privacy/provider.php b/step/duplicate/classes/privacy/provider.php index 136ee7ca..b17e946e 100644 --- a/step/duplicate/classes/privacy/provider.php +++ b/step/duplicate/classes/privacy/provider.php @@ -34,7 +34,7 @@ class provider implements null_provider { * * @return string the reason */ - public static function get_reason() : string { + public static function get_reason(): string { return 'privacy:metadata'; } } diff --git a/step/duplicate/db/access.php b/step/duplicate/db/access.php index 85169b97..78e62082 100644 --- a/step/duplicate/db/access.php +++ b/step/duplicate/db/access.php @@ -22,17 +22,17 @@ */ defined('MOODLE_INTERNAL') || die(); -$capabilities = array( +$capabilities = [ - 'lifecyclestep/duplicate:enterdata' => array( + 'lifecyclestep/duplicate:enterdata' => [ 'contextlevel' => CONTEXT_COURSE, 'captype' => 'write', - 'archetypes' => array( + 'archetypes' => [ 'editingteacher' => CAP_ALLOW, - ), - 'clonepermissionsfrom' => 'tool/lifecycle:managecourses' - ), -); + ], + 'clonepermissionsfrom' => 'tool/lifecycle:managecourses', + ], +]; diff --git a/step/duplicate/interactionlib.php b/step/duplicate/interactionlib.php index f8d389f8..6cece993 100644 --- a/step/duplicate/interactionlib.php +++ b/step/duplicate/interactionlib.php @@ -70,13 +70,13 @@ public function get_action_tools($process) { $shortname = process_data_manager::get_process_data($process->id, $step->id, duplicate::PROC_DATA_COURSESHORTNAME); $fullname = process_data_manager::get_process_data($process->id, $step->id, duplicate::PROC_DATA_COURSEFULLNAME); if (!empty($fullname) && !empty($shortname)) { - return array(); + return []; } - return array( - array('action' => self::ACTION_DUPLICATE_FORM, + return [ + ['action' => self::ACTION_DUPLICATE_FORM, 'alt' => get_string('duplicate_form', 'lifecyclestep_duplicate'), - ), - ); + ], + ]; } /** @@ -116,7 +116,7 @@ public function handle_interaction($process, $step, $action = 'default') { return step_interactive_response::rollback(); } if ($data = $form->get_submitted_data()) { - if ($foundcourses = $DB->get_records('course', array('shortname' => $data->shortname))) { + if ($foundcourses = $DB->get_records('course', ['shortname' => $data->shortname])) { foreach ($foundcourses as $foundcourse) { $foundcoursenames[] = $foundcourse->fullname; } diff --git a/step/duplicate/lang/de/lifecyclestep_duplicate.php b/step/duplicate/lang/de/lifecyclestep_duplicate.php index 39f01957..c2e3e806 100644 --- a/step/duplicate/lang/de/lifecyclestep_duplicate.php +++ b/step/duplicate/lang/de/lifecyclestep_duplicate.php @@ -22,14 +22,14 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['action_new_course_data'] = '{$a} hat neuen Kursnamen eingegeben'; +$string['duplicate:enterdata'] = 'Daten für Kursduplikation eingeben'; +$string['duplicate_course_header'] = 'Kurs duplizieren'; +$string['duplicate_form'] = 'Daten eingeben'; $string['pluginname'] = 'Kurs-Duplizieren-Schritt'; $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; -$string['duplicate_form'] = 'Daten eingeben'; -$string['duplicate_course_header'] = 'Kurs duplizieren'; $string['status_message_duplication'] = 'Duplizierter Kurs wird bald verfügbar sein.'; $string['status_message_form'] = 'Zusätzliche Informationen benötigt'; -$string['action_new_course_data'] = '{$a} hat neuen Kursnamen eingegeben'; -$string['duplicate:enterdata'] = 'Daten für Kursduplikation eingeben'; diff --git a/step/duplicate/lang/en/lifecyclestep_duplicate.php b/step/duplicate/lang/en/lifecyclestep_duplicate.php index b71b5a15..bf15ef60 100644 --- a/step/duplicate/lang/en/lifecyclestep_duplicate.php +++ b/step/duplicate/lang/en/lifecyclestep_duplicate.php @@ -22,14 +22,14 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['action_new_course_data'] = '{$a} supplied new course name'; +$string['duplicate:enterdata'] = 'Enter data for course duplication'; +$string['duplicate_course_header'] = 'Duplicate course'; +$string['duplicate_form'] = 'Enter data'; $string['pluginname'] = 'Duplicate step'; $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; -$string['duplicate_form'] = 'Enter data'; -$string['duplicate_course_header'] = 'Duplicate course'; $string['status_message_duplication'] = 'Duplicated course will be available shortly.'; $string['status_message_form'] = 'Additional information required'; -$string['action_new_course_data'] = '{$a} supplied new course name'; -$string['duplicate:enterdata'] = 'Enter data for course duplication'; diff --git a/step/duplicate/lib.php b/step/duplicate/lib.php index 201c997d..d730b8df 100644 --- a/step/duplicate/lib.php +++ b/step/duplicate/lib.php @@ -71,7 +71,7 @@ public function process_course($processid, $instanceid, $course) { $shortname, $course->category, $course->visible, - array()); + []); } catch (\moodle_exception $e) { if ($e->getCode() == 'shortnametaken') { process_data_manager::set_process_data($processid, $instanceid, self::PROC_DATA_COURSESHORTNAME, ''); @@ -130,18 +130,18 @@ public function duplicate_course($courseid, $fullname, $shortname, $categoryid, require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php'); // Parameter validation. - $params = array( + $params = [ 'courseid' => $courseid, 'fullname' => $fullname, 'shortname' => $shortname, 'categoryid' => $categoryid, 'visible' => $visible, - 'options' => $options - ); + 'options' => $options, + ]; // Context validation. - if (! ($course = $DB->get_record('course', array('id' => $params['courseid'])))) { + if (! ($course = $DB->get_record('course', ['id' => $params['courseid']]))) { throw new \moodle_exception('invalidcourseid', 'error'); } @@ -151,7 +151,7 @@ public function duplicate_course($courseid, $fullname, $shortname, $categoryid, // Course to be duplicated. $coursecontext = \context_course::instance($course->id); - $backupdefaults = array( + $backupdefaults = [ 'activities' => 1, 'blocks' => 1, 'filters' => 1, @@ -161,10 +161,10 @@ public function duplicate_course($courseid, $fullname, $shortname, $categoryid, 'comments' => 0, 'userscompletion' => 0, 'logs' => 0, - 'grade_histories' => 0 - ); + 'grade_histories' => 0, + ]; - $backupsettings = array(); + $backupsettings = []; // Check for backup and restore options. if (!empty($params['options'])) { foreach ($params['options'] as $option) { @@ -172,7 +172,7 @@ public function duplicate_course($courseid, $fullname, $shortname, $categoryid, // Strict check for a correct value (allways 1 or 0, true or false). $value = clean_param($option['value'], PARAM_INT); - if ($value !== 0 and $value !== 1) { + if ($value !== 0 && $value !== 1) { throw new \moodle_exception('invalidextparam', 'webservice', '', $option['name']); } @@ -197,7 +197,7 @@ public function duplicate_course($courseid, $fullname, $shortname, $categoryid, } // Check if the shortname is used. - if ($foundcourses = $DB->get_records('course', array('shortname' => $shortname))) { + if ($foundcourses = $DB->get_records('course', ['shortname' => $shortname])) { foreach ($foundcourses as $foundcourse) { $foundcoursenames[] = $foundcourse->fullname; } @@ -272,7 +272,7 @@ public function duplicate_course($courseid, $fullname, $shortname, $categoryid, $rc->execute_plan(); $rc->destroy(); - $course = $DB->get_record('course', array('id' => $newcourseid), '*', MUST_EXIST); + $course = $DB->get_record('course', ['id' => $newcourseid], '*', MUST_EXIST); $course->fullname = $params['fullname']; $course->shortname = $params['shortname']; $course->visible = $params['visible']; diff --git a/step/email/classes/privacy/provider.php b/step/email/classes/privacy/provider.php index afbcb511..a41ad4e4 100644 --- a/step/email/classes/privacy/provider.php +++ b/step/email/classes/privacy/provider.php @@ -52,7 +52,7 @@ public static function get_metadata(collection $collection): collection { [ 'touser' => 'privacy:metadata:lifecyclestep_email:touser', 'courseid' => 'privacy:metadata:lifecyclestep_email:courseid', - 'instanceid' => 'privacy:metadata:lifecyclestep_email:instanceid' + 'instanceid' => 'privacy:metadata:lifecyclestep_email:instanceid', ], 'privacy:metadata:lifecyclestep_email:summary' ); @@ -133,7 +133,7 @@ public static function delete_data_for_users(approved_userlist $userlist): void $DB->delete_records('lifecyclestep_email', ['touser' => $userid]); } else if ($userlist->get_context() instanceof context_course) { $DB->delete_records('lifecyclestep_email', ['touser' => $userid, - 'courseid' => $userlist->get_context()->instanceid]); + 'courseid' => $userlist->get_context()->instanceid, ]); } } } diff --git a/step/email/db/access.php b/step/email/db/access.php index 7c33a548..3ec76d81 100644 --- a/step/email/db/access.php +++ b/step/email/db/access.php @@ -22,20 +22,20 @@ */ defined('MOODLE_INTERNAL') || die(); -$capabilities = array( +$capabilities = [ - 'lifecyclestep/email:preventdeletion' => array( + 'lifecyclestep/email:preventdeletion' => [ 'contextlevel' => CONTEXT_COURSE, 'captype' => 'write', - 'archetypes' => array( + 'archetypes' => [ 'manager' => CAP_PREVENT, 'editingteacher' => CAP_ALLOW, 'teacher' => CAP_PREVENT, 'students' => CAP_PREVENT, - ), - 'clonepermissionsfrom' => 'tool/lifecycle:managecourses' - ), -); + ], + 'clonepermissionsfrom' => 'tool/lifecycle:managecourses', + ], +]; diff --git a/step/email/interactionlib.php b/step/email/interactionlib.php index 1085e128..8d71b69b 100644 --- a/step/email/interactionlib.php +++ b/step/email/interactionlib.php @@ -67,11 +67,11 @@ public function get_relevant_capability() { * @throws \coding_exception */ public function get_action_tools($process) { - return array( - array('action' => self::ACTION_KEEP, + return [ + ['action' => self::ACTION_KEEP, 'alt' => get_string('keep_course', 'lifecyclestep_email'), - ), - ); + ], + ]; } /** diff --git a/step/email/lang/de/lifecyclestep_email.php b/step/email/lang/de/lifecyclestep_email.php index 82e8115c..b0fab933 100644 --- a/step/email/lang/de/lifecyclestep_email.php +++ b/step/email/lang/de/lifecyclestep_email.php @@ -22,35 +22,34 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'Email-Schritt'; - -$string['email_responsetimeout'] = 'Zeit, die der Nutzer hat, um zu reagieren'; -$string['email_subject'] = 'Betreffvorlage'; -$emailplaceholdersnohtml = '

' . 'Sie können die folgenden Platzhalter benutzen:' - . '
' . 'Vorname des Empfängers: ##firstname##' - . '
' . 'Nachname des Empfängers: ##lastname##' - . '
' . 'Link zur Antwortseite: ##link##' - . '
' . 'Betroffene Kurse: ##courses##' - . '

'; -$string['email_subject_help'] = 'Stellen Sie die Vorlage für den Emailbetreff ein.' . $emailplaceholdersnohtml; +$string['action_prevented_deletion'] = '{$a} verhinderte Löschung'; +$string['email:preventdeletion'] = 'Löschen verhindern'; $string['email_content'] = 'Vorlage für Emails in Klartext'; -$string['email_content_help'] = 'Stellen Sie die Vorlage für Emails ein. (in Klartext, alternativ können Sie auch die HTML-Vorlage unten einstellen.)' . $emailplaceholdersnohtml; -$emailplaceholdershtml = '

' . 'Sie können die folgenden Platzhalter benutzen:' +$string['email_content_help'] = 'Stellen Sie die Vorlage für Emails ein. (in Klartext, alternativ können Sie auch die HTML-Vorlage unten einstellen.)' . '

' . 'Sie können die folgenden Platzhalter benutzen:' + . '
' . 'Vorname des Empfängers: ##firstname##' + . '
' . 'Nachname des Empfängers: ##lastname##' + . '
' . 'Link zur Antwortseite: ##link##' + . '
' . 'Betroffene Kurse: ##courses##' + . '

'; +$string['email_content_html'] = 'HTML-Vorlage für Emails'; +$string['email_content_html_help'] = 'Stellen sie die HTML-Vorlage für Emails ein. (in HTML-Format; falls gesetzt, wird es an Stelle der Klartext-Vorlage benutzt!)' . '

' . 'Sie können die folgenden Platzhalter benutzen:' . '
' . 'Vorname des Empfängers: ##firstname##' . '
' . 'Nachname des Empfängers: ##lastname##' . '
' . 'Link zur Antwortseite: ##link-html##' . '
' . 'Betroffene Kurse: ##courses-html##' . '

'; -$string['email_content_html'] = 'HTML-Vorlage für Emails'; -$string['email_content_html_help'] = 'Stellen sie die HTML-Vorlage für Emails ein. (in HTML-Format; falls gesetzt, wird es an Stelle der Klartext-Vorlage benutzt!)' . $emailplaceholdershtml; - -$string['email:preventdeletion'] = 'Löschen verhindern'; - +$string['email_responsetimeout'] = 'Zeit, die der Nutzer hat, um zu reagieren'; +$string['email_subject'] = 'Betreffvorlage'; +$string['email_subject_help'] = 'Stellen Sie die Vorlage für den Emailbetreff ein.' . '

' . 'Sie können die folgenden Platzhalter benutzen:' + . '
' . 'Vorname des Empfängers: ##firstname##' + . '
' . 'Nachname des Empfängers: ##lastname##' + . '
' . 'Link zur Antwortseite: ##link##' + . '
' . 'Betroffene Kurse: ##courses##' + . '

'; $string['keep_course'] = 'Kurs behalten'; -$string['status_message_requiresattention'] = 'Kurs ist zum Löschen vorgemerkt'; -$string['action_prevented_deletion'] = '{$a} verhinderte Löschung'; - +$string['pluginname'] = 'Email-Schritt'; $string['privacy:metadata:lifecyclestep_email:courseid'] = 'Die ID des Kurses, zu dem E-Mail-Benachrichtigungen versandt werden'; $string['privacy:metadata:lifecyclestep_email:instanceid'] = 'Die ID der Schritt-Instanz, der E-Mails verschickt'; $string['privacy:metadata:lifecyclestep_email:summary'] = 'Informationen, welche Benutzer per E-Mail benachrichtigt werden'; $string['privacy:metadata:lifecyclestep_email:touser'] = 'Die ID des Benutzers, an den eine E-Mail verschickt wird'; +$string['status_message_requiresattention'] = 'Kurs ist zum Löschen vorgemerkt'; diff --git a/step/email/lang/en/lifecyclestep_email.php b/step/email/lang/en/lifecyclestep_email.php index a4d06443..a0fd8ec4 100644 --- a/step/email/lang/en/lifecyclestep_email.php +++ b/step/email/lang/en/lifecyclestep_email.php @@ -22,35 +22,34 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'Email step'; - -$string['email_responsetimeout'] = 'Time the user has for the response'; -$string['email_subject'] = 'Subject template'; -$emailplaceholdersnohtml = '

' . 'You can use the following placeholders:' - . '
' . 'First name of recipient: ##firstname##' - . '
' . 'Last name of recipient: ##lastname##' - . '
' . 'Link to response page: ##link##' - . '
' . 'Impacted courses: ##courses##' - . '

'; -$string['email_subject_help'] = 'Set the template for the subject of the email.' . $emailplaceholdersnohtml; +$string['action_prevented_deletion'] = '{$a} prevented deletion'; +$string['email:preventdeletion'] = 'Prevent deletion'; $string['email_content'] = 'Content plain text template'; -$string['email_content_help'] = 'Set the template for the content of the email (plain text, alternatively you can use HTML template for HTML email below)' . $emailplaceholdersnohtml; -$emailplaceholdershtml = '

' . 'You can use the following placeholders:' - . '
' . 'First name of recipient: ##firstname##' - . '
' . 'Last name of recipient: ##lastname##' - . '
' . 'Link to response page: ##link-html##' - . '
' . 'Impacted courses: ##courses-html##' - . '

'; +$string['email_content_help'] = 'Set the template for the content of the email (plain text, alternatively you can use HTML template for HTML email below)' . '

' . 'You can use the following placeholders:' + . '
' . 'First name of recipient: ##firstname##' + . '
' . 'Last name of recipient: ##lastname##' + . '
' . 'Link to response page: ##link##' + . '
' . 'Impacted courses: ##courses##' + . '

'; $string['email_content_html'] = 'Content HTML Template'; -$string['email_content_html_help'] = 'Set the html template for the content of the email (HTML email, will be used instead of plaintext field if not empty!)' . $emailplaceholdershtml; - -$string['email:preventdeletion'] = 'Prevent deletion'; - +$string['email_content_html_help'] = 'Set the html template for the content of the email (HTML email, will be used instead of plaintext field if not empty!)' . '

' . 'You can use the following placeholders:' + . '
' . 'First name of recipient: ##firstname##' + . '
' . 'Last name of recipient: ##lastname##' + . '
' . 'Link to response page: ##link-html##' + . '
' . 'Impacted courses: ##courses-html##' + . '

'; +$string['email_responsetimeout'] = 'Time the user has for the response'; +$string['email_subject'] = 'Subject template'; +$string['email_subject_help'] = 'Set the template for the subject of the email.' . '

' . 'You can use the following placeholders:' + . '
' . 'First name of recipient: ##firstname##' + . '
' . 'Last name of recipient: ##lastname##' + . '
' . 'Link to response page: ##link##' + . '
' . 'Impacted courses: ##courses##' + . '

'; $string['keep_course'] = 'Keep course'; -$string['status_message_requiresattention'] = 'Course is marked for deletion'; -$string['action_prevented_deletion'] = '{$a} prevented deletion'; - +$string['pluginname'] = 'Email step'; $string['privacy:metadata:lifecyclestep_email:courseid'] = 'ID of the course, emails will be sent for'; $string['privacy:metadata:lifecyclestep_email:instanceid'] = 'ID of the step instance sending emails'; $string['privacy:metadata:lifecyclestep_email:summary'] = 'Information about whhich users will be informed by email'; $string['privacy:metadata:lifecyclestep_email:touser'] = 'ID of the user who is being notified via email'; +$string['status_message_requiresattention'] = 'Course is marked for deletion'; diff --git a/step/email/lib.php b/step/email/lib.php index cb1e4db1..4635aed8 100644 --- a/step/email/lib.php +++ b/step/email/lib.php @@ -88,7 +88,7 @@ public function process_course($processid, $instanceid, $course) { public function process_waiting_course($processid, $instanceid, $course) { // When time runs up and no one wants to keep the course, then proceed. $process = process_manager::get_process_by_id($processid); - if ($process->timestepchanged < time() - settings_manager::get_settings( + if (null !== $process && $process->timestepchanged < time() - settings_manager::get_settings( $instanceid, settings_type::STEP )['responsetimeout']) { @@ -111,25 +111,28 @@ public function post_processing_bulk_operation() { $settings['contenthtml'] = format_text($settings['contenthtml'], FORMAT_HTML); $userstobeinformed = $DB->get_records('lifecyclestep_email', - array('instanceid' => $step->id), '', 'distinct touser'); + ['instanceid' => $step->id], '', 'distinct touser'); foreach ($userstobeinformed as $userrecord) { $user = \core_user::get_user($userrecord->touser); $transaction = $DB->start_delegated_transaction(); $mailentries = $DB->get_records('lifecyclestep_email', - array('instanceid' => $step->id, - 'touser' => $user->id)); + ['instanceid' => $step->id, + 'touser' => $user->id, ]); $parsedsettings = $this->replace_placeholders($settings, $user, $step->id, $mailentries); - $subject = $parsedsettings['subject']; - $content = $parsedsettings['content']; - $contenthtml = $parsedsettings['contenthtml']; - // TODO: use course info to parse content template! - email_to_user($user, \core_user::get_noreply_user(), $subject, $content, $contenthtml); - $DB->delete_records('lifecyclestep_email', - array('instanceid' => $step->id, - 'touser' => $user->id)); - $transaction->allow_commit(); + $subject = $parsedsettings['subject']; + $content = $parsedsettings['content']; + $contenthtml = $parsedsettings['contenthtml']; + // TODO: use course info to parse content template! + $success = email_to_user($user, \core_user::get_noreply_user(), $subject, $content, $contenthtml); + if (!$success) { + mtrace("E-mail to user {$user->id} failed."); + } + $DB->delete_records('lifecyclestep_email', + ['instanceid' => $step->id, + 'touser' => $user->id, ]); + $transaction->allow_commit(); } } @@ -148,8 +151,8 @@ public function post_processing_bulk_operation() { private function replace_placeholders($strings, $user, $stepid, $mailentries) { global $CFG; - $patterns = array(); - $replacements = array(); + $patterns = []; + $replacements = []; // Replaces firstname of the user. $patterns[] = '##firstname##'; @@ -182,7 +185,7 @@ private function replace_placeholders($strings, $user, $stepid, $mailentries) { // Replace courses html. $patterns[] = '##courses-html##'; $courses = $mailentries; - $coursestabledata = array(); + $coursestabledata = []; foreach ($courses as $entry) { $coursestabledata[$entry->courseid] = $this->parse_course_row_data($entry->courseid); } @@ -213,7 +216,7 @@ private function parse_course($courseid) { */ private function parse_course_row_data($courseid) { $course = get_course($courseid); - return array($course->fullname); + return [$course->fullname]; } /** @@ -221,12 +224,12 @@ private function parse_course_row_data($courseid) { * @return instance_setting[] containing settings keys and PARAM_TYPES */ public function instance_settings() { - return array( + return [ new instance_setting('responsetimeout', PARAM_INT, false), new instance_setting('subject', PARAM_TEXT, true), new instance_setting('content', PARAM_RAW, true), new instance_setting('contenthtml', PARAM_RAW, true), - ); + ]; } /** @@ -271,6 +274,6 @@ public function extend_add_instance_form_definition($mform) { */ public function extend_add_instance_form_definition_after_data($mform, $settings) { $mform->setDefault('contenthtml', - array('text' => isset($settings['contenthtml']) ? $settings['contenthtml'] : '', 'format' => FORMAT_HTML)); + ['text' => isset($settings['contenthtml']) ? $settings['contenthtml'] : '', 'format' => FORMAT_HTML]); } } diff --git a/step/email/tests/privacy/provider_test.php b/step/email/tests/privacy/provider_test.php index 37e3afa7..fcb8311e 100644 --- a/step/email/tests/privacy/provider_test.php +++ b/step/email/tests/privacy/provider_test.php @@ -44,7 +44,7 @@ * @author Philipp Memmel * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class provider_test extends provider_testcase { +final class provider_test extends provider_testcase { /** * Basic setup for the provider tests. @@ -146,7 +146,7 @@ public function test_export_user_data(): void { $writer = writer::with_context($course1context); $this->assertTrue($writer->has_any_data()); $recordids = $DB->get_records('lifecyclestep_email', ['touser' => $this->user1->id, - 'courseid' => $this->course1->id], '', 'id'); + 'courseid' => $this->course1->id, ], '', 'id'); foreach ($recordids as $id) { $exportedrecord = $writer->get_data(['lifecyclestep_email-' . $id->id]); $this->assertEquals($this->user1->id, $exportedrecord->touser); @@ -156,7 +156,7 @@ public function test_export_user_data(): void { $writer = writer::with_context($course2context); $this->assertTrue($writer->has_any_data()); $recordids = $DB->get_records('lifecyclestep_email', ['touser' => $this->user1->id, - 'courseid' => $this->course2->id], '', 'id'); + 'courseid' => $this->course2->id, ], '', 'id'); foreach ($recordids as $id) { $exportedrecord = $writer->get_data(['lifecyclestep_email-' . $id->id]); $this->assertEquals($this->user1->id, $exportedrecord->touser); @@ -190,7 +190,7 @@ public function test_get_users_in_context(): void { * @return void * @throws dml_exception */ - public function test_delete_data_for_users() { + public function test_delete_data_for_users(): void { global $DB; $approveduserlist = new approved_userlist(context_system::instance(), 'lifecyclestep_email', [$this->user1->id, $this->user2->id]); @@ -212,7 +212,7 @@ public function test_delete_data_for_users() { * @return void * @throws dml_exception */ - public function test_delete_data_for_users_coursecontext() { + public function test_delete_data_for_users_coursecontext(): void { global $DB; $approveduserlist = new approved_userlist(context_course::instance($this->course1->id), 'lifecyclestep_email', [$this->user1->id, $this->user2->id]); diff --git a/step/lib.php b/step/lib.php index 7209d1d3..224399b6 100644 --- a/step/lib.php +++ b/step/lib.php @@ -104,7 +104,7 @@ abstract public function get_subpluginname(); * @return instance_setting[] containing settings keys and PARAM_TYPES */ public function instance_settings() { - return array(); + return []; } /** @@ -142,6 +142,16 @@ public function extend_add_instance_form_definition_after_data($mform, $settings public function abort_course($process) { } + + /** + * Ensure validity of settings upon backup restoration. + * @param array $settings + * @return array List of errors with settings. If empty, the given settings are valid. + */ + public function ensure_validity(array $settings): array { + return []; + } + } /** diff --git a/templates/workflowoverview.mustache b/templates/workflowoverview.mustache index 70a01042..e6907e91 100644 --- a/templates/workflowoverview.mustache +++ b/templates/workflowoverview.mustache @@ -66,7 +66,7 @@ } ], "listofcourses": [], - "nosteplink": {}, + "nosteplink": "", "table": null } }} @@ -84,12 +84,14 @@
{{{addinstance}}}
{{#str}} trigger, tool_lifecycle{{/str}} {{{triggerhelp}}}
- {{#automatic}} + {{#showcoursecounts}} + {{#automatic}}
{{#str}} courses_will_be_triggered_total, tool_lifecycle, {{coursestriggered}} {{/str}}
{{#str}} courses_will_be_excluded_total, tool_lifecycle, {{coursesexcluded}} {{/str}}
- {{/automatic}} + {{/automatic}} + {{/showcoursecounts}}
{{#trigger}}
@@ -103,10 +105,12 @@
+ {{#showcoursecounts}} {{#automatic}} - {{#str}} courses_will_be_triggered, tool_lifecycle, {{triggeredcourses}} {{/str}}
- {{#str}} courses_will_be_excluded, tool_lifecycle, {{excludedcourses}} {{/str}} + {{#str}} courses_will_be_triggered, tool_lifecycle, {{triggeredcourses}} {{/str}}
+ {{#str}} courses_will_be_excluded, tool_lifecycle, {{excludedcourses}} {{/str}} {{/automatic}} + {{/showcoursecounts}}
{{/trigger}} @@ -140,4 +144,4 @@ {{{ table }}} {{/table}} - \ No newline at end of file + diff --git a/tests/active_workflow_is_manual_test.php b/tests/active_workflow_is_manual_test.php index 2e004264..1c502be0 100644 --- a/tests/active_workflow_is_manual_test.php +++ b/tests/active_workflow_is_manual_test.php @@ -40,7 +40,7 @@ * @copyright 2018 WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class active_workflow_is_manual_test extends \advanced_testcase { +final class active_workflow_is_manual_test extends \advanced_testcase { /** Icon of the trigger. */ const MANUAL_TRIGGER1_ICON = 't/up'; @@ -58,7 +58,7 @@ class active_workflow_is_manual_test extends \advanced_testcase { * Setup the testcase. * @throws \coding_exception */ - public function setUp() : void { + public function setUp(): void { global $USER; $this->resetAfterTest(true); $generator = $this->getDataGenerator()->get_plugin_generator('tool_lifecycle'); @@ -85,7 +85,7 @@ public function setUp() : void { * @throws \dml_transaction_exception * @throws \moodle_exception */ - public function test_activate_manual() { + public function test_activate_manual(): void { workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->manualworkflow->id); $reloadworkflow = workflow_manager::get_workflow($this->manualworkflow->id); $this->assertTrue(workflow_manager::is_active($this->manualworkflow->id)); @@ -100,7 +100,7 @@ public function test_activate_manual() { * @throws \dml_transaction_exception * @throws \moodle_exception */ - public function test_activate_automatic() { + public function test_activate_automatic(): void { workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->automaticworkflow->id); $reloadworkflow = workflow_manager::get_workflow($this->automaticworkflow->id); $this->assertTrue(workflow_manager::is_active($this->automaticworkflow->id)); diff --git a/tests/active_workflow_sortindex_updown_test.php b/tests/active_workflow_sortindex_updown_test.php index e43eb80b..7aecda2f 100644 --- a/tests/active_workflow_sortindex_updown_test.php +++ b/tests/active_workflow_sortindex_updown_test.php @@ -41,13 +41,13 @@ * @copyright 2017 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class active_workflow_sortindex_updown_test extends workflow_actions_testcase { +final class active_workflow_sortindex_updown_test extends workflow_actions_testcase { /** * Test to put down the first workflow. * @covers \tool_lifecycle\local\manager\workflow_manager move actions down */ - public function test_down_first() { + public function test_down_first(): void { workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow1->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow2->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow3->id); @@ -67,7 +67,7 @@ public function test_down_first() { * Test to put down the second workflow. * @covers \tool_lifecycle\local\manager\workflow_manager move actions down */ - public function test_down_second() { + public function test_down_second(): void { workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow1->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow2->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow3->id); @@ -87,7 +87,7 @@ public function test_down_second() { * Test to put down the third workflow. * @covers \tool_lifecycle\local\manager\workflow_manager move actions down */ - public function test_down_third() { + public function test_down_third(): void { workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow1->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow2->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow3->id); @@ -107,7 +107,7 @@ public function test_down_third() { * Test to put up the third workflow. * @covers \tool_lifecycle\local\manager\workflow_manager move actions up */ - public function test_up_first() { + public function test_up_first(): void { workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow1->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow2->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow3->id); @@ -127,7 +127,7 @@ public function test_up_first() { * Test to put up the third workflow. * @covers \tool_lifecycle\local\manager\workflow_manager move actions up */ - public function test_up_second() { + public function test_up_second(): void { workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow1->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow2->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow3->id); @@ -147,7 +147,7 @@ public function test_up_second() { * Test to put up the third workflow. * @covers \tool_lifecycle\local\manager\workflow_manager move actions up */ - public function test_up_third() { + public function test_up_third(): void { workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow1->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow2->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow3->id); diff --git a/tests/backup_and_restore_workflow_test.php b/tests/backup_and_restore_workflow_test.php index 2472092b..79452610 100644 --- a/tests/backup_and_restore_workflow_test.php +++ b/tests/backup_and_restore_workflow_test.php @@ -28,6 +28,7 @@ require_once(__DIR__ . '/generator/lib.php'); require_once(__DIR__ . '/../lib.php'); +use mod_bigbluebuttonbn\settings; use tool_lifecycle\local\backup\backup_lifecycle_workflow; use tool_lifecycle\local\backup\restore_lifecycle_workflow; use tool_lifecycle\local\manager\workflow_manager; @@ -44,7 +45,7 @@ * @copyright 2018 WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class backup_and_restore_workflow_test extends \advanced_testcase { +final class backup_and_restore_workflow_test extends \advanced_testcase { /** @var $workflow workflow */ private $workflow; @@ -56,10 +57,18 @@ class backup_and_restore_workflow_test extends \advanced_testcase { * Setup the testcase. * @throws \coding_exception */ - public function setUp() : void { + public function setUp(): void { $this->resetAfterTest(true); $generator = $this->getDataGenerator()->get_plugin_generator('tool_lifecycle'); $this->workflow = $generator->create_workflow(['startdatedelay', 'categories'], ['email', 'createbackup', 'deletecourse']); + $category = $this->getDataGenerator()->create_category(); + foreach (trigger_manager::get_triggers_for_workflow($this->workflow->id) as $trigger) { + if ($trigger->subpluginname === 'categories') { + settings_manager::save_setting($trigger->id, settings_type::TRIGGER, 'categories', + 'categories', $category->id); + } + } + foreach (workflow_manager::get_workflows() as $existingworkflow) { $this->existingworkflows[] = $existingworkflow->id; } @@ -69,7 +78,7 @@ public function setUp() : void { * Test to activate the manual workflow. * @covers \tool_lifecycle\local\manager\workflow_manager check if backup is created */ - public function test_backup_workflow() { + public function test_backup_workflow(): void { $backuptask = new backup_lifecycle_workflow($this->workflow->id); $backuptask->execute(); $filename = $backuptask->get_temp_filename(); diff --git a/tests/backup_manager_test.php b/tests/backup_manager_test.php index 2ed76032..ce192f9b 100644 --- a/tests/backup_manager_test.php +++ b/tests/backup_manager_test.php @@ -34,7 +34,7 @@ * @copyright 2017 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class backup_manager_test extends \advanced_testcase { +final class backup_manager_test extends \advanced_testcase { /** @var array $course Instance of the course under test. */ private $course; @@ -42,7 +42,7 @@ class backup_manager_test extends \advanced_testcase { /** * Setup the testcase. */ - public function setUp() : void { + public function setUp(): void { $this->resetAfterTest(false); $this->course = $this->getDataGenerator()->create_course(); } @@ -51,7 +51,7 @@ public function setUp() : void { * Test creating a backup for a course. * @covers \tool_lifecycle\local\manager\backup_manager create backup */ - public function test_backup_create() { + public function test_backup_create(): void { global $DB; $result = backup_manager::create_course_backup($this->course->id); $this->assertTrue($result); @@ -63,7 +63,7 @@ public function test_backup_create() { * Test redirect without errors when starting to restore a backup. * @covers \tool_lifecycle\local\manager\backup_manager restore backup */ - public function test_backup_restore() { + public function test_backup_restore(): void { global $DB; $backups = $DB->get_records('tool_lifecycle_backups'); $this->assertEquals(1, count($backups)); diff --git a/tests/behat/manual_trigger.feature b/tests/behat/manual_trigger.feature index 164d4088..e667c0cb 100644 --- a/tests/behat/manual_trigger.feature +++ b/tests/behat/manual_trigger.feature @@ -1,4 +1,4 @@ -@tool @tool_lifecycle +@tool @tool_lifecycle @manual_trigger Feature: Add a manual trigger and test view and actions as a teacher Background: diff --git a/tests/behat/upload_workflow.feature b/tests/behat/upload_workflow.feature new file mode 100644 index 00000000..2ea1a1c3 --- /dev/null +++ b/tests/behat/upload_workflow.feature @@ -0,0 +1,11 @@ +@tool @tool_lifecycle @_file_upload @upload_workflow +Feature: Upload a workflow definition + + @javascript + Scenario: Upload a new workflow + Given I log in as "admin" + And I navigate to "Plugins > Admin tools > Life Cycle > Workflow drafts" in site administration + And I click on "Upload workflow" "link" + And I upload "admin/tool/lifecycle/tests/fixtures/simpleworkflow.xml" file to "File" filemanager + And I press "Upload" + Then I should see "A Workflow" diff --git a/tests/fixtures/simpleworkflow.xml b/tests/fixtures/simpleworkflow.xml new file mode 100644 index 00000000..3e570689 --- /dev/null +++ b/tests/fixtures/simpleworkflow.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/tests/generator/lib.php b/tests/generator/lib.php index ae963a13..cd0461b4 100644 --- a/tests/generator/lib.php +++ b/tests/generator/lib.php @@ -46,27 +46,27 @@ class tool_lifecycle_generator extends testing_module_generator { /** @var array $defaultsteps Default steps configuration. */ private static $defaultsteps = [ "deletecourse" => [ - "maximumdeletionspercron" => 10 + "maximumdeletionspercron" => 10, ], "email" => [ "responsetimeout" => 10, "subject" => "Test Email", "content" => "Content", - "contenthtml" => "Content HTML" + "contenthtml" => "Content HTML", ], "createbackup" => [ - "maximumbackupspercron" => 10 + "maximumbackupspercron" => 10, ], ]; /** @var array $defaulttrigger Default trigger configuration. */ private static $defaulttrigger = [ "startdatedelay" => [ - "delay" => 10000 + "delay" => 10000, ], "categories" => [ "categories" => "1,10", - "exclude" => true + "exclude" => true, ], ]; diff --git a/tests/manual_trigger_tools_test.php b/tests/manual_trigger_tools_test.php index db905e01..d20f037a 100644 --- a/tests/manual_trigger_tools_test.php +++ b/tests/manual_trigger_tools_test.php @@ -38,7 +38,7 @@ * @copyright 2018 Tobias Reischmann, Jan Dageforde WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class manual_trigger_tools_test extends \advanced_testcase { +final class manual_trigger_tools_test extends \advanced_testcase { /** Icon of the manual trigger 1. */ const MANUAL_TRIGGER1_ICON = 't/up'; /** Display name of the manual trigger 1. */ @@ -62,7 +62,7 @@ class manual_trigger_tools_test extends \advanced_testcase { * Setup the testcase. * @throws \coding_exception */ - public function setUp() : void { + public function setUp(): void { global $USER; $this->resetAfterTest(true); $generator = $this->getDataGenerator()->get_plugin_generator('tool_lifecycle'); @@ -87,7 +87,7 @@ public function setUp() : void { * Test getting manual trigger tools of active workflows. * @covers \tool_lifecycle\local\manager\workflow_manager get triggers for one wf */ - public function test_get_manual_trigger_tools_for_one_active_workflow() { + public function test_get_manual_trigger_tools_for_one_active_workflow(): void { workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow2->id); $tools = workflow_manager::get_manual_trigger_tools_for_active_workflows(); $this->assertCount(1, $tools); @@ -102,7 +102,7 @@ public function test_get_manual_trigger_tools_for_one_active_workflow() { * Test getting manual trigger tools of active workflows. * @covers \tool_lifecycle\local\manager\workflow_manager get triggers for multiple wf */ - public function test_get_manual_trigger_tools_for_active_workflows() { + public function test_get_manual_trigger_tools_for_active_workflows(): void { workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow2->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow1->id); $tools = workflow_manager::get_manual_trigger_tools_for_active_workflows(); diff --git a/tests/manually_triggered_process_test.php b/tests/manually_triggered_process_test.php index 52597adc..104014e0 100644 --- a/tests/manually_triggered_process_test.php +++ b/tests/manually_triggered_process_test.php @@ -47,7 +47,7 @@ * @copyright 2018 WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class manually_triggered_process_test extends \advanced_testcase { +final class manually_triggered_process_test extends \advanced_testcase { /** Icon of the manual trigger. */ const MANUAL_TRIGGER1_ICON = 't/up'; /** Display name of the manual trigger. */ @@ -66,7 +66,7 @@ class manually_triggered_process_test extends \advanced_testcase { * @throws \coding_exception * @throws \moodle_exception */ - public function setUp() : void { + public function setUp(): void { global $USER; // We do not need a sesskey check in theses tests. @@ -82,7 +82,7 @@ public function setUp() : void { $manualworkflow = $generator->create_manual_workflow($triggersettings); $step = $generator->create_step("instance1", "createbackup", $manualworkflow->id); settings_manager::save_settings($step->id, settings_type::STEP, "createbackup", - array("maximumbackupspercron" => 10) + ["maximumbackupspercron" => 10] ); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $manualworkflow->id); @@ -95,7 +95,7 @@ public function setUp() : void { * Test to proceed a manually triggered process to step index 1. * @covers \tool_lifecycle\local\manager\process_manager test if manual process started */ - public function test_proceeding_of_manually_triggered_processes() { + public function test_proceeding_of_manually_triggered_processes(): void { $process = process_manager::manually_trigger_process($this->course->id, $this->trigger->id); $this->assertEquals(0, $process->stepindex); diff --git a/tests/persistence/persist_process_data_test.php b/tests/persistence/persist_process_data_test.php index b76f67be..9c40aec6 100644 --- a/tests/persistence/persist_process_data_test.php +++ b/tests/persistence/persist_process_data_test.php @@ -40,7 +40,7 @@ * @copyright 2017 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class persist_process_data_test extends \advanced_testcase { +final class persist_process_data_test extends \advanced_testcase { /** @var process $process Instance of the process. */ private $process; @@ -55,7 +55,7 @@ class persist_process_data_test extends \advanced_testcase { * @throws coding_exception * @throws dml_exception */ - public function setUp() : void { + public function setUp(): void { $this->resetAfterTest(true); $generator = $this->getDataGenerator()->get_plugin_generator('tool_lifecycle'); @@ -70,7 +70,7 @@ public function setUp() : void { * Test the getting and setting of process data. * @covers \tool_lifecycle\local\manager\process_data_manager */ - public function test_get_set_process_data() { + public function test_get_set_process_data(): void { $step = step_manager::get_step_instance_by_workflow_index($this->process->workflowid, $this->process->stepindex); process_data_manager::set_process_data( $this->process->id, diff --git a/tests/persistence/persist_process_test.php b/tests/persistence/persist_process_test.php index 2915ab55..54180ce7 100644 --- a/tests/persistence/persist_process_test.php +++ b/tests/persistence/persist_process_test.php @@ -39,7 +39,7 @@ * @copyright 2017 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class persist_process_test extends \advanced_testcase { +final class persist_process_test extends \advanced_testcase { /** @var workflow $workflow Instance of the workflow. */ private $workflow; @@ -51,7 +51,7 @@ class persist_process_test extends \advanced_testcase { * Setup the testcase. * @throws coding_exception */ - public function setUp() : void { + public function setUp(): void { $this->resetAfterTest(true); $generator = $this->getDataGenerator()->get_plugin_generator('tool_lifecycle'); @@ -63,7 +63,7 @@ public function setUp() : void { * Test the creation of a process. * @covers \tool_lifecycle\local\manager\process_manager */ - public function test_create() { + public function test_create(): void { $process = process_manager::create_process($this->course->id, $this->workflow->id); $this->assertNotNull($process); $this->assertNotEmpty($process->id); @@ -77,7 +77,7 @@ public function test_create() { * Tests setting a process on waiting. * @covers \tool_lifecycle\local\manager\process_manager */ - public function test_process_waiting() { + public function test_process_waiting(): void { $process = process_manager::create_process($this->course->id, $this->workflow->id); $this->assertFalse($process->waiting); process_manager::set_process_waiting($process); @@ -89,7 +89,7 @@ public function test_process_waiting() { * Tests deletion of a process when rolledback. * @covers \tool_lifecycle\local\manager\process_manager */ - public function test_process_rollback() { + public function test_process_rollback(): void { $process = process_manager::create_process($this->course->id, $this->workflow->id); delayed_courses_manager::set_course_delayed($process->courseid, get_config('tool_lifecycle', 'duration')); process_manager::rollback_process($process); @@ -101,7 +101,7 @@ public function test_process_rollback() { * Tests proceeding a process to the next step. * @covers \tool_lifecycle\local\manager\process_manager */ - public function test_process_proceed() { + public function test_process_proceed(): void { $process = process_manager::create_process($this->course->id, $this->workflow->id); $this->assertEquals(0, $process->stepindex); process_manager::proceed_process($process); diff --git a/tests/persistence/persist_step_test.php b/tests/persistence/persist_step_test.php index bc830a0a..b5e5e8c9 100644 --- a/tests/persistence/persist_step_test.php +++ b/tests/persistence/persist_step_test.php @@ -39,7 +39,7 @@ * @copyright 2017 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class persist_step_test extends \advanced_testcase { +final class persist_step_test extends \advanced_testcase { /** @var workflow $workflow Instance of the workflow. */ private $workflow; @@ -52,7 +52,7 @@ class persist_step_test extends \advanced_testcase { * @throws coding_exception * @throws moodle_exception */ - public function setUp() : void { + public function setUp(): void { $this->resetAfterTest(true); $this->generator = $this->getDataGenerator()->get_plugin_generator('tool_lifecycle'); @@ -63,7 +63,7 @@ public function setUp() : void { * Test that after an insert the id from the database is set within the step object. * @covers \tool_lifecycle\local\manager\step_manager */ - public function test_add_step() { + public function test_add_step(): void { $step = $this->generator->create_step( 'instance1', 'subpluginname', @@ -77,7 +77,7 @@ public function test_add_step() { * Test that sortindizes are created correclty when creating multiple steps. * @covers \tool_lifecycle\local\manager\step_manager */ - public function test_add_multiple_steps() { + public function test_add_multiple_steps(): void { $step1 = $this->generator->create_step( 'instance1', 'subpluginname', @@ -99,7 +99,7 @@ public function test_add_multiple_steps() { * Test that the step can be removed correctly. * @covers \tool_lifecycle\local\manager\step_manager */ - public function test_remove_step() { + public function test_remove_step(): void { $step1 = $this->generator->create_step( 'instance1', 'subpluginname', @@ -132,7 +132,7 @@ public function test_remove_step() { * Test that sortindizes are still created correctly, when some steps were already removed. * @covers \tool_lifecycle\local\manager\step_manager */ - public function test_add_after_remove_step() { + public function test_add_after_remove_step(): void { $step1 = $this->generator->create_step( 'instance1', 'subpluginname', diff --git a/tests/persistence/persist_workflow_test.php b/tests/persistence/persist_workflow_test.php index f4109c55..ed2438bb 100644 --- a/tests/persistence/persist_workflow_test.php +++ b/tests/persistence/persist_workflow_test.php @@ -38,7 +38,7 @@ * @copyright 2017 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class persist_workflow_test extends \advanced_testcase { +final class persist_workflow_test extends \advanced_testcase { /** @var workflow $workflow Instance of the workflow. */ private $workflow; @@ -46,7 +46,7 @@ class persist_workflow_test extends \advanced_testcase { /** * Setup the testcase. */ - public function setUp() : void { + public function setUp(): void { $this->resetAfterTest(true); $record = new \stdClass(); $record->id = null; @@ -58,7 +58,7 @@ public function setUp() : void { * Test the creation of a process. * @covers \tool_lifecycle\local\manager\workflow_manager create a wf. */ - public function test_create() { + public function test_create(): void { $this->assertNull($this->workflow->id); workflow_manager::insert_or_update($this->workflow); $this->assertNotNull($this->workflow->id); diff --git a/tests/privacy_test.php b/tests/privacy_test.php index 461a5f37..b2eedf4f 100644 --- a/tests/privacy_test.php +++ b/tests/privacy_test.php @@ -49,7 +49,7 @@ * @copyright 2019 Justus Dieckmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class privacy_test extends provider_testcase { +final class privacy_test extends provider_testcase { /** Icon of the manual trigger. */ @@ -75,7 +75,7 @@ class privacy_test extends provider_testcase { * Setup the testcase. * @throws \coding_exception */ - public function setUp() : void { + public function setUp(): void { global $USER; // We do not need a sesskey check in theses tests. @@ -100,7 +100,7 @@ public function setUp() : void { * @throws \invalid_parameter_exception * @throws \moodle_exception */ - public function test_get_contexts_for_userid() { + public function test_get_contexts_for_userid(): void { $c1 = $this->getDataGenerator()->create_course(); $c2 = $this->getDataGenerator()->create_course(); $u1 = $this->getDataGenerator()->create_user(); @@ -130,7 +130,7 @@ public function test_get_contexts_for_userid() { * @throws \invalid_parameter_exception * @throws \moodle_exception */ - public function test_export_user_data() { + public function test_export_user_data(): void { $c1 = $this->getDataGenerator()->create_course(); $c2 = $this->getDataGenerator()->create_course(); $u1 = $this->getDataGenerator()->create_user(); @@ -150,12 +150,12 @@ public function test_export_user_data() { $writer = writer::with_context(\context_system::instance()); $step = step_manager::get_step_instance_by_workflow_index($this->workflow->id, 1); $subcontext = ['tool_lifecycle', 'action_log', "process_$p1->id", $step->instancename, - "action_" . self::ACTION_KEEP]; + "action_" . self::ACTION_KEEP, ]; $data1 = $writer->get_data($subcontext); $this->assertEquals($u1->id, $data1->userid); $this->assertEquals(self::ACTION_KEEP, $data1->action); $subcontext = ['tool_lifecycle', 'action_log', "process_$p2->id", $step->instancename, - "action_" . self::ACTION_KEEP]; + "action_" . self::ACTION_KEEP, ]; $data2 = $writer->get_data($subcontext); $this->assertEquals($u1->id, $data2->userid); $this->assertEquals(self::ACTION_KEEP, $data2->action); @@ -169,7 +169,7 @@ public function test_export_user_data() { * @throws \invalid_parameter_exception * @throws \moodle_exception */ - public function test_delete_data_for_all_users_in_context() { + public function test_delete_data_for_all_users_in_context(): void { global $DB; $c1 = $this->getDataGenerator()->create_course(); $u1 = $this->getDataGenerator()->create_user(); @@ -195,7 +195,7 @@ public function test_delete_data_for_all_users_in_context() { * @throws \invalid_parameter_exception * @throws \moodle_exception */ - public function test_delete_data_for_user() { + public function test_delete_data_for_user(): void { global $DB; $c1 = $this->getDataGenerator()->create_course(); $c2 = $this->getDataGenerator()->create_course(); @@ -229,7 +229,7 @@ public function test_delete_data_for_user() { * @throws \invalid_parameter_exception * @throws \moodle_exception */ - public function test_get_users_in_context() { + public function test_get_users_in_context(): void { $c1 = $this->getDataGenerator()->create_course(); $c2 = $this->getDataGenerator()->create_course(); $u1 = $this->getDataGenerator()->create_user(); @@ -258,7 +258,7 @@ public function test_get_users_in_context() { * @throws \invalid_parameter_exception * @throws \moodle_exception */ - public function test_delete_data_for_users() { + public function test_delete_data_for_users(): void { global $DB; $c1 = $this->getDataGenerator()->create_course(); $c2 = $this->getDataGenerator()->create_course(); diff --git a/tests/process_error_test.php b/tests/process_error_test.php index 2e601fe1..49259054 100644 --- a/tests/process_error_test.php +++ b/tests/process_error_test.php @@ -41,7 +41,7 @@ * @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 { +final class process_error_test extends \advanced_testcase { /** Icon of the manual trigger. */ const MANUAL_TRIGGER1_ICON = 't/up'; /** Display name of the manual trigger. */ @@ -60,7 +60,7 @@ class process_error_test extends \advanced_testcase { * @throws \coding_exception * @throws \moodle_exception */ - public function setUp() : void { + public function setUp(): void { global $USER, $DB; // We do not need a sesskey check in theses tests. @@ -75,7 +75,7 @@ public function setUp() : void { $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) + ["maximumdeletionspercron" => 10] ); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $manualworkflow->id); @@ -92,7 +92,7 @@ public function setUp() : void { * Test if the correct process error was put into the table. * @covers \tool_lifecycle\processor */ - public function test_process_error_in_table() { + public function test_process_error_in_table(): void { global $DB; $process = process_manager::manually_trigger_process($this->course->id, $this->trigger->id); diff --git a/tests/process_status_message_test.php b/tests/process_status_message_test.php index dad40e11..ecb0855a 100644 --- a/tests/process_status_message_test.php +++ b/tests/process_status_message_test.php @@ -35,7 +35,7 @@ * @copyright 2018 Tamara Gunkel, Jan Dageforde WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class process_status_message_test extends \advanced_testcase { +final class process_status_message_test extends \advanced_testcase { /** Icon of the manual trigger. */ const MANUAL_TRIGGER1_ICON = 't/up'; /** Display name of the manual trigger. */ @@ -53,7 +53,7 @@ class process_status_message_test extends \advanced_testcase { * Setup the testcase. * @throws \coding_exception */ - public function setUp() : void { + public function setUp(): void { global $USER; // We do not need a sesskey check in theses tests. @@ -76,7 +76,7 @@ public function setUp() : void { * Test getting status message for a process. * @covers \tool_lifecycle\local\manager\interaction_manager */ - public function test_get_status_message() { + public function test_get_status_message(): void { $process = $this->generator->create_process(2, $this->workflow->id); $message = \tool_lifecycle\local\manager\interaction_manager::get_process_status_message($process->id); $this->assertEquals(get_string("workflow_started", "tool_lifecycle"), $message); diff --git a/tests/settings_manager_test.php b/tests/settings_manager_test.php index e91623cb..8a3372db 100644 --- a/tests/settings_manager_test.php +++ b/tests/settings_manager_test.php @@ -39,7 +39,7 @@ * @copyright 2017 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class settings_manager_test extends \advanced_testcase { +final class settings_manager_test extends \advanced_testcase { /** @var step_subplugin $step Instance of the step plugin. */ private $step; @@ -57,7 +57,7 @@ class settings_manager_test extends \advanced_testcase { * Setup the testcase. * @throws \coding_exception */ - public function setUp() : void { + public function setUp(): void { $this->resetAfterTest(false); $generator = $this->getDataGenerator()->get_plugin_generator('tool_lifecycle'); @@ -71,7 +71,7 @@ public function setUp() : void { * Test setting and getting settings data for steps. * @covers \tool_lifecycle\local\manager\settings_manager */ - public function test_set_get_step_settings() { + public function test_set_get_step_settings(): void { $data = new \stdClass(); $data->subject = self::EMAIL_VALUE; settings_manager::save_settings($this->step->id, settings_type::STEP, $this->step->subpluginname, $data); @@ -84,7 +84,7 @@ public function test_set_get_step_settings() { * Test setting and getting settings data for triggers. * @covers \tool_lifecycle\local\manager\settings_manager */ - public function test_set_get_trigger_settings() { + public function test_set_get_trigger_settings(): void { $data = new \stdClass(); $data->delay = self::STARTDELAY_VALUE; settings_manager::save_settings($this->trigger->id, settings_type::TRIGGER, $this->trigger->subpluginname, $data); @@ -97,7 +97,7 @@ public function test_set_get_trigger_settings() { * Test correct removal of setting, if steps, triggers or workflows are deleted. * @covers \tool_lifecycle\local\manager\settings_manager */ - public function test_remove_workflow() { + public function test_remove_workflow(): void { global $DB; $data = new \stdClass(); $data->subject = self::EMAIL_VALUE; @@ -105,18 +105,18 @@ public function test_remove_workflow() { $data = new \stdClass(); $data->delay = 100; settings_manager::save_settings($this->trigger->id, settings_type::TRIGGER, $this->trigger->subpluginname, $data); - $settingsstep = $DB->get_records('tool_lifecycle_settings', array('instanceid' => $this->step->id, - 'type' => settings_type::STEP)); + $settingsstep = $DB->get_records('tool_lifecycle_settings', ['instanceid' => $this->step->id, + 'type' => settings_type::STEP, ]); $this->assertNotEmpty($settingsstep); - $settingstrigger = $DB->get_records('tool_lifecycle_settings', array('instanceid' => $this->trigger->id, - 'type' => settings_type::TRIGGER)); + $settingstrigger = $DB->get_records('tool_lifecycle_settings', ['instanceid' => $this->trigger->id, + 'type' => settings_type::TRIGGER, ]); $this->assertNotEmpty($settingstrigger); workflow_manager::remove($this->workflow->id); - $settingsstep = $DB->get_records('tool_lifecycle_settings', array('instanceid' => $this->step->id, - 'type' => settings_type::STEP)); + $settingsstep = $DB->get_records('tool_lifecycle_settings', ['instanceid' => $this->step->id, + 'type' => settings_type::STEP, ]); $this->assertEmpty($settingsstep); - $settingstrigger = $DB->get_records('tool_lifecycle_settings', array('instanceid' => $this->trigger->id, - 'type' => settings_type::TRIGGER)); + $settingstrigger = $DB->get_records('tool_lifecycle_settings', ['instanceid' => $this->trigger->id, + 'type' => settings_type::TRIGGER, ]); $this->assertEmpty($settingstrigger); } diff --git a/tests/workflow_actions_testcase.php b/tests/workflow_actions_testcase.php index 7403d130..e6f5b0ce 100644 --- a/tests/workflow_actions_testcase.php +++ b/tests/workflow_actions_testcase.php @@ -51,7 +51,7 @@ abstract class workflow_actions_testcase extends \advanced_testcase { * Setup the testcase. * @throws coding_exception */ - public function setUp() : void { + public function setUp(): void { global $USER; // We do not need a sesskey check in theses tests. $USER->ignoresesskey = true; diff --git a/tests/workflow_activate_disable_duplicate_test.php b/tests/workflow_activate_disable_duplicate_test.php index e48b37c0..a0acf658 100644 --- a/tests/workflow_activate_disable_duplicate_test.php +++ b/tests/workflow_activate_disable_duplicate_test.php @@ -42,13 +42,13 @@ * @copyright 2018 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class workflow_activate_disable_duplicate_test extends workflow_actions_testcase { +final class workflow_activate_disable_duplicate_test extends workflow_actions_testcase { /** * Test to activate the first workflow. * @covers \tool_lifecycle\local\manager\workflow_manager */ - public function test_activate_first() { + public function test_activate_first(): void { workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow1->id); $reloadworkflow = workflow_manager::get_workflow($this->workflow1->id); $this->assertTrue(workflow_manager::is_active($this->workflow1->id)); @@ -59,7 +59,7 @@ public function test_activate_first() { * Test to activate the first and the second workflow. * @covers \tool_lifecycle\local\manager\workflow_manager */ - public function test_activate_second() { + public function test_activate_second(): void { workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow1->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow2->id); @@ -72,7 +72,7 @@ public function test_activate_second() { * Test to activate all three workflow. * @covers \tool_lifecycle\local\manager\workflow_manager */ - public function test_activate_third() { + public function test_activate_third(): void { workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow1->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow2->id); workflow_manager::handle_action(action::WORKFLOW_ACTIVATE, $this->workflow3->id); @@ -86,7 +86,7 @@ public function test_activate_third() { * Test to deactivate the first workflow. * @covers \tool_lifecycle\local\manager\workflow_manager */ - public function test_deactivate_first() { + public function test_deactivate_first(): void { workflow_manager::handle_action(action::WORKFLOW_ABORTDISABLE, $this->workflow1->id); $this->assertFalse(workflow_manager::is_active($this->workflow1->id)); } @@ -95,7 +95,7 @@ public function test_deactivate_first() { * Test to duplicate the first workflow. * @covers \tool_lifecycle\local\manager\workflow_manager */ - public function test_duplicate_first() { + public function test_duplicate_first(): void { workflow_manager::handle_action(action::WORKFLOW_DUPLICATE, $this->workflow1->id); $workflows = workflow_manager::get_workflows(); $this->assertCount(4, $workflows); diff --git a/trigger/categories/classes/privacy/provider.php b/trigger/categories/classes/privacy/provider.php index 19da3d64..3eff6200 100644 --- a/trigger/categories/classes/privacy/provider.php +++ b/trigger/categories/classes/privacy/provider.php @@ -34,7 +34,7 @@ class provider implements null_provider { * * @return string the reason */ - public static function get_reason() : string { + public static function get_reason(): string { return 'privacy:metadata'; } } diff --git a/trigger/categories/lang/de/lifecycletrigger_categories.php b/trigger/categories/lang/de/lifecycletrigger_categories.php index fcec1378..f803d7b4 100644 --- a/trigger/categories/lang/de/lifecycletrigger_categories.php +++ b/trigger/categories/lang/de/lifecycletrigger_categories.php @@ -22,9 +22,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'Kategorie-Trigger'; -$string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; - $string['categories'] = 'Kategorien, für die der Workflow ausgelöst werden soll.'; +$string['categories_do_not_exist'] = 'Es gibt keine Kurskategorien mit den folgenden IDs: {$a}.'; $string['categories_noselection'] = 'Bitte wählen sie mindestens eine Kategorie aus.'; $string['exclude'] = 'Falls ausgewählt, werden gerade die Kurse der angegebenen Kategorien nicht ausgelöst.'; +$string['pluginname'] = 'Kategorie-Trigger'; +$string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; diff --git a/trigger/categories/lang/en/lifecycletrigger_categories.php b/trigger/categories/lang/en/lifecycletrigger_categories.php index 423bd48e..d630083c 100644 --- a/trigger/categories/lang/en/lifecycletrigger_categories.php +++ b/trigger/categories/lang/en/lifecycletrigger_categories.php @@ -22,9 +22,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'Categories trigger'; -$string['privacy:metadata'] = 'This subplugin does not store any personal data.'; - $string['categories'] = 'Categories, for which the workflow should be triggered'; +$string['categories_do_not_exist'] = 'There are no categories with the following ids: {$a}.'; $string['categories_noselection'] = 'Please choose at least one category.'; $string['exclude'] = 'If ticked, the named categories are excluded from triggering instead.'; +$string['pluginname'] = 'Categories trigger'; +$string['privacy:metadata'] = 'This subplugin does not store any personal data.'; diff --git a/trigger/categories/lib.php b/trigger/categories/lib.php index b44376f6..95a64610 100644 --- a/trigger/categories/lib.php +++ b/trigger/categories/lib.php @@ -63,7 +63,7 @@ public function check_course($course, $triggerid) { public function get_course_recordset_where($triggerid) { global $DB, $CFG; $categories = settings_manager::get_settings($triggerid, settings_type::TRIGGER)['categories']; - $exclude = settings_manager::get_settings($triggerid, settings_type::TRIGGER)['exclude'] && true; + $exclude = settings_manager::get_settings($triggerid, settings_type::TRIGGER)['exclude']; $categories = explode(',', $categories); // Use core_course_category for moodle 3.6 and higher. @@ -73,21 +73,21 @@ public function get_course_recordset_where($triggerid) { require_once($CFG->libdir . '/coursecatlib.php'); $categoryobjects = \coursecat::get_many($categories); } - $allcategories = array(); + $allcategories = []; foreach ($categories as $category) { - array_push($allcategories , $category); + array_push($allcategories, $category); + if (!isset($categoryobjects[$category]) || !$categoryobjects[$category]) { + continue; + } $children = $categoryobjects[$category]->get_all_children_ids(); - $allcategories = array_merge($allcategories , $children); + $allcategories = array_merge($allcategories, $children); } - list($insql, $inparams) = $DB->get_in_or_equal($allcategories, SQL_PARAMS_NAMED); + list($insql, $inparams) = $DB->get_in_or_equal($allcategories, SQL_PARAMS_NAMED, 'param', !$exclude); $where = "{course}.category {$insql}"; - if ($exclude) { - $where = "NOT " . $where; - } - return array($where, $inparams); + return [$where, $inparams]; } /** @@ -103,10 +103,10 @@ public function get_subpluginname() { * @return instance_setting[] containing settings keys and PARAM_TYPES */ public function instance_settings() { - return array( + return [ new instance_setting('categories', PARAM_SEQUENCE, true), new instance_setting('exclude', PARAM_BOOL, true), - ); + ]; } /** @@ -118,10 +118,10 @@ public function instance_settings() { */ public function extend_add_instance_form_definition($mform) { $displaylist = core_course_category::make_categories_list(); - $options = array( + $options = [ 'multiple' => true, 'noselectionstring' => get_string('categories_noselection', 'lifecycletrigger_categories'), - ); + ]; $mform->addElement('autocomplete', 'categories', get_string('categories', 'lifecycletrigger_categories'), $displaylist, $options); @@ -131,4 +131,25 @@ public function extend_add_instance_form_definition($mform) { $mform->setType('exclude', PARAM_BOOL); } + /** + * Ensure validity of settings upon backup restoration. + * @param array $settings + * @return array List of errors with settings. If empty, the given settings are valid. + */ + public function ensure_validity(array $settings): array { + $missingcategories = []; + $categories = explode(',', $settings['categories']); + $categoryobjects = \core_course_category::get_many($categories); + foreach ($categories as $category) { + if (!isset($categoryobjects[$category]) || !$categoryobjects[$category]) { + $missingcategories[] = $category; + } + } + if ($missingcategories) { + return [get_string('categories_do_not_exist', 'lifecycletrigger_categories', join(', ', $missingcategories))]; + } else { + return []; + } + } + } diff --git a/trigger/categories/tests/trigger_test.php b/trigger/categories/tests/trigger_test.php index c00bfda6..8187ec27 100644 --- a/trigger/categories/tests/trigger_test.php +++ b/trigger/categories/tests/trigger_test.php @@ -41,7 +41,7 @@ * @copyright 2017 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class trigger_test extends \advanced_testcase { +final class trigger_test extends \advanced_testcase { /** @var trigger_subplugin $excludetrigger Trigger instance that excludes a category. */ private $excludetrigger; @@ -60,7 +60,7 @@ class trigger_test extends \advanced_testcase { * Setup the testcase. * @throws \moodle_exception */ - public function setUp() : void { + public function setUp(): void { $this->resetAfterTest(true); $this->setAdminUser(); @@ -70,11 +70,11 @@ public function setUp() : void { $this->category = $generator->create_category(); $othercategory = $generator->create_category(); - $this->childcategory = $generator->create_category(array('parent' => $this->category->id)); - $data = array( + $this->childcategory = $generator->create_category(['parent' => $this->category->id]); + $data = [ 'categories' => $othercategory->id . ',' . $this->category->id, 'exclude' => true, - ); + ]; $this->excludetrigger = \tool_lifecycle_trigger_categories_generator::create_trigger_with_workflow($data); @@ -86,9 +86,9 @@ public function setUp() : void { * Tests if courses, which are in the category are correctly triggered. * @covers \tool_lifecycle\processor \tool_lifecycle\trigger\categories */ - public function test_course_has_cat() { + public function test_course_has_cat(): void { - $course = $this->getDataGenerator()->create_course(array('category' => $this->category->id)); + $course = $this->getDataGenerator()->create_course(['category' => $this->category->id]); $recordset = $this->processor->get_course_recordset([$this->excludetrigger], []); foreach ($recordset as $element) { @@ -111,9 +111,9 @@ public function test_course_has_cat() { * Tests if courses, which are in the category are correctly triggered. * @covers \tool_lifecycle\processor \tool_lifecycle\trigger\categories */ - public function test_course_within_cat() { + public function test_course_within_cat(): void { - $course = $this->getDataGenerator()->create_course(array('category' => $this->childcategory->id)); + $course = $this->getDataGenerator()->create_course(['category' => $this->childcategory->id]); $recordset = $this->processor->get_course_recordset([$this->excludetrigger], []); foreach ($recordset as $element) { @@ -136,7 +136,7 @@ public function test_course_within_cat() { * Tests if courses, which are not in the category are correctly triggered. * @covers \tool_lifecycle\processor \tool_lifecycle\trigger\categories */ - public function test_course_not_within_cat() { + public function test_course_not_within_cat(): void { $course = $this->getDataGenerator()->create_course(); $recordset = $this->processor->get_course_recordset([$this->includetrigger], []); diff --git a/trigger/delayedcourses/classes/privacy/provider.php b/trigger/delayedcourses/classes/privacy/provider.php index 2befaf30..ab47a280 100644 --- a/trigger/delayedcourses/classes/privacy/provider.php +++ b/trigger/delayedcourses/classes/privacy/provider.php @@ -34,7 +34,7 @@ class provider implements null_provider { * * @return string the reason */ - public static function get_reason() : string { + public static function get_reason(): string { return 'privacy:metadata'; } } diff --git a/trigger/delayedcourses/lang/de/lifecycletrigger_delayedcourses.php b/trigger/delayedcourses/lang/de/lifecycletrigger_delayedcourses.php index 317e6567..4c6015f7 100644 --- a/trigger/delayedcourses/lang/de/lifecycletrigger_delayedcourses.php +++ b/trigger/delayedcourses/lang/de/lifecycletrigger_delayedcourses.php @@ -22,7 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['delay'] = 'Dieser Trigger wird alle Kurse ausschließen, die durch Nutzerinteraktion verzögert wurden.'; $string['pluginname'] = 'Verzögerte Kurse ausschließen - Trigger'; $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; -$string['delay'] = 'Dieser Trigger wird alle Kurse ausschließen, die durch Nutzerinteraktion verzögert wurden.'; diff --git a/trigger/delayedcourses/lang/en/lifecycletrigger_delayedcourses.php b/trigger/delayedcourses/lang/en/lifecycletrigger_delayedcourses.php index 2d8525ee..4b694e55 100644 --- a/trigger/delayedcourses/lang/en/lifecycletrigger_delayedcourses.php +++ b/trigger/delayedcourses/lang/en/lifecycletrigger_delayedcourses.php @@ -22,7 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['delay'] = 'This module will exclude all courses, which were delayed by user interaction'; $string['pluginname'] = 'Exclude delayed courses trigger'; $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; -$string['delay'] = 'This module will exclude all courses, which were delayed by user interaction'; diff --git a/trigger/delayedcourses/tests/trigger_test.php b/trigger/delayedcourses/tests/trigger_test.php index ed8dedf0..162d1282 100644 --- a/trigger/delayedcourses/tests/trigger_test.php +++ b/trigger/delayedcourses/tests/trigger_test.php @@ -43,7 +43,7 @@ * @copyright 2017 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class trigger_test extends \advanced_testcase { +final class trigger_test extends \advanced_testcase { /** @var trigger_subplugin $triggerinstance Instance of the delayedcourses trigger. */ private $triggerinstance; @@ -57,7 +57,7 @@ class trigger_test extends \advanced_testcase { /** @var workflow Workflow delaying processes for all workflows */ private $workflowdealayingallworkflows; - public function setUp() : void { + public function setUp(): void { $this->resetAfterTest(true); $this->setAdminUser(); @@ -71,7 +71,7 @@ public function setUp() : void { * Tests that a course is not excluded by this plugin, when there exists no dalayed entry, yet. * @covers \tool_lifecycle\processor \tool_lifecycle\trigger\delayedcourses */ - public function test_course_not_delayed() { + public function test_course_not_delayed(): void { $course = $this->getDataGenerator()->create_course(); @@ -90,7 +90,7 @@ public function test_course_not_delayed() { * Tests that a course is excluded by this plugin, when there exists a dalayed entry. * @covers \tool_lifecycle\processor \tool_lifecycle\trigger\delayedcourses */ - public function test_course_delayed() { + public function test_course_delayed(): void { $course = $this->getDataGenerator()->create_course(); @@ -111,7 +111,7 @@ public function test_course_delayed() { * Tests that a course is not excluded by this plugin, when there exists a dalayed entry, but it is expired. * @covers \tool_lifecycle\processor \tool_lifecycle\trigger\delayedcourses */ - public function test_course_delay_expired() { + public function test_course_delay_expired(): void { $course = $this->getDataGenerator()->create_course(); delayed_courses_manager::set_course_delayed($course->id, -2000); $recordset = $this->processor->get_course_recordset([$this->triggerinstance], []); @@ -129,7 +129,7 @@ public function test_course_delay_expired() { * Tests that a course is not excluded by this plugin, when it was delayed for a single workflow. * @covers \tool_lifecycle\processor \tool_lifecycle\trigger\delayedcourses */ - public function test_course_delay_for_single_workflow() { + public function test_course_delay_for_single_workflow(): void { $course = $this->getDataGenerator()->create_course(); delayed_courses_manager::set_course_delayed_for_workflow($course->id, true, $this->workflow->id); $recordset = $this->processor->get_course_recordset([$this->triggerinstance], []); @@ -147,7 +147,7 @@ public function test_course_delay_for_single_workflow() { * Tests that a course is excluded by this plugin, when it was delayed for all workflows. * @covers \tool_lifecycle\processor \tool_lifecycle\trigger\delayedcourses */ - public function test_course_delay_for_all_workflows() { + public function test_course_delay_for_all_workflows(): void { $course = $this->getDataGenerator()->create_course(); delayed_courses_manager::set_course_delayed_for_workflow($course->id, true, $this->workflowdealayingallworkflows->id); diff --git a/trigger/lib.php b/trigger/lib.php index 3c01ffb7..720a4868 100644 --- a/trigger/lib.php +++ b/trigger/lib.php @@ -50,7 +50,7 @@ abstract public function get_subpluginname(); * @return instance_setting[] containing settings keys and PARAM_TYPES */ public function instance_settings() { - return array(); + return []; } /** @@ -115,6 +115,15 @@ public function get_status_message() { return get_string("workflow_started", "tool_lifecycle"); } + /** + * Ensure validity of settings upon backup restoration. + * @param array $settings + * @return array List of errors with settings. If empty, the given settings are valid. + */ + public function ensure_validity(array $settings): array { + return []; + } + } /** @@ -152,7 +161,7 @@ public function is_manual_trigger() { * @return array A list containing the constructed sql fragment and an array of parameters. */ public function get_course_recordset_where($triggerid) { - return array('', array()); + return ['', []]; } } diff --git a/trigger/manual/classes/privacy/provider.php b/trigger/manual/classes/privacy/provider.php index b595b593..bbc660f9 100644 --- a/trigger/manual/classes/privacy/provider.php +++ b/trigger/manual/classes/privacy/provider.php @@ -34,7 +34,7 @@ class provider implements null_provider { * * @return string the reason */ - public static function get_reason() : string { + public static function get_reason(): string { return 'privacy:metadata'; } } diff --git a/trigger/manual/lang/de/lifecycletrigger_manual.php b/trigger/manual/lang/de/lifecycletrigger_manual.php index 41bc7298..66ca61e9 100644 --- a/trigger/manual/lang/de/lifecycletrigger_manual.php +++ b/trigger/manual/lang/de/lifecycletrigger_manual.php @@ -26,7 +26,7 @@ $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; $string['setting_capability'] = 'Berechtigung'; $string['setting_capability_help'] = 'Die Moodle-Berechtigung, die ein Nutzer benötigt, um einen Workflow mit diesem Trigger zu sehen und auszulösen, z.B. "enrol/manual:enrol". Bitte schauen Sie sich die Moodle Access API für Details an.'; -$string['setting_icon'] = 'Icon'; -$string['setting_icon_help'] = 'Das Moodle-Icon das dem Nutzer für diesen Trigger angezeigt wird, z.B. "core/tick". Die ganze Liste möglicher Icons kann in der Moodle-Dokumentation gefunden werden.'; $string['setting_displayname'] = 'Aktionsname'; $string['setting_displayname_help'] = 'Der Name für die Triggeraktion, der dem Nutzer angezeigt wird.'; +$string['setting_icon'] = 'Icon'; +$string['setting_icon_help'] = 'Das Moodle-Icon das dem Nutzer für diesen Trigger angezeigt wird, z.B. "e/tick". Die ganze Liste möglicher Icons kann in der Moodle-Dokumentation gefunden werden.'; diff --git a/trigger/manual/lang/en/lifecycletrigger_manual.php b/trigger/manual/lang/en/lifecycletrigger_manual.php index dea6815d..0c043430 100644 --- a/trigger/manual/lang/en/lifecycletrigger_manual.php +++ b/trigger/manual/lang/en/lifecycletrigger_manual.php @@ -26,7 +26,7 @@ $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; $string['setting_capability'] = 'Capability'; $string['setting_capability_help'] = 'The Moodle capability needed to see and invoke a workflow using this trigger, e.g. "enrol/manual:enrol". Please see Moodle access API documentation for details.'; -$string['setting_icon'] = 'Icon'; -$string['setting_icon_help'] = 'The Moodle icon to be showed to the user for this trigger, e.g. "core/tick". A full list of possible icons can be found at Moodle documentation.'; $string['setting_displayname'] = 'Action name'; $string['setting_displayname_help'] = 'A name for the trigger action displayed to the user.'; +$string['setting_icon'] = 'Icon'; +$string['setting_icon_help'] = 'The Moodle icon to be showed to the user for this trigger, e.g. "e/tick". A full list of possible icons can be found at Moodle documentation.'; diff --git a/trigger/manual/lib.php b/trigger/manual/lib.php index b3bc945e..56a3ff2f 100644 --- a/trigger/manual/lib.php +++ b/trigger/manual/lib.php @@ -76,7 +76,7 @@ public function extend_add_instance_form_definition($mform) { $elementname = 'capability'; $capabilities = get_all_capabilities(); - $capabilitynames = array(); + $capabilitynames = []; foreach ($capabilities as $cap) { $capabilitynames[$cap['name']] = $cap['name']; } diff --git a/trigger/sitecourse/classes/privacy/provider.php b/trigger/sitecourse/classes/privacy/provider.php index 8ef22f4c..49601fc5 100644 --- a/trigger/sitecourse/classes/privacy/provider.php +++ b/trigger/sitecourse/classes/privacy/provider.php @@ -34,7 +34,7 @@ class provider implements null_provider { * * @return string the reason */ - public static function get_reason() : string { + public static function get_reason(): string { return 'privacy:metadata'; } } diff --git a/trigger/sitecourse/lang/de/lifecycletrigger_sitecourse.php b/trigger/sitecourse/lang/de/lifecycletrigger_sitecourse.php index 4ea16ed6..80601d68 100644 --- a/trigger/sitecourse/lang/de/lifecycletrigger_sitecourse.php +++ b/trigger/sitecourse/lang/de/lifecycletrigger_sitecourse.php @@ -22,7 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['delay'] = 'Dieser Trigger wird den Startseitenkurs ausschließen.'; $string['pluginname'] = 'Startseitenkurs ausschließen - Trigger'; $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; -$string['delay'] = 'Dieser Trigger wird den Startseitenkurs ausschließen.'; diff --git a/trigger/sitecourse/lang/en/lifecycletrigger_sitecourse.php b/trigger/sitecourse/lang/en/lifecycletrigger_sitecourse.php index 7a6c02e2..62f6fb03 100644 --- a/trigger/sitecourse/lang/en/lifecycletrigger_sitecourse.php +++ b/trigger/sitecourse/lang/en/lifecycletrigger_sitecourse.php @@ -22,7 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['delay'] = 'This module will exclude the site course from processing'; $string['pluginname'] = 'Exclude site course trigger'; $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; -$string['delay'] = 'This module will exclude the site course from processing'; diff --git a/trigger/sitecourse/lib.php b/trigger/sitecourse/lib.php index 14809c74..5553ade3 100644 --- a/trigger/sitecourse/lib.php +++ b/trigger/sitecourse/lib.php @@ -59,7 +59,7 @@ public function check_course($course, $triggerid) { public function get_course_recordset_where($triggerid) { global $DB; list($insql, $inparam) = $DB->get_in_or_equal(SITEID, SQL_PARAMS_NAMED); - return array("{course}.id {$insql}", $inparam); + return ["{course}.id {$insql}", $inparam]; } /** diff --git a/trigger/sitecourse/tests/trigger_test.php b/trigger/sitecourse/tests/trigger_test.php index 2f48f48b..ea613e47 100644 --- a/trigger/sitecourse/tests/trigger_test.php +++ b/trigger/sitecourse/tests/trigger_test.php @@ -41,7 +41,7 @@ * @copyright 2017 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class trigger_test extends \advanced_testcase { +final class trigger_test extends \advanced_testcase { /** @var trigger_subplugin $triggerinstance Instance of the trigger. */ private $triggerinstance; @@ -50,7 +50,7 @@ class trigger_test extends \advanced_testcase { * Setup the testcase. * @throws coding_exception */ - public function setUp() : void { + public function setUp(): void { $this->resetAfterTest(true); $this->setAdminUser(); @@ -61,7 +61,7 @@ public function setUp() : void { * Tests if the site course is excluded by this plugin. * @covers \tool_lifecycle\processor \tool_lifecycle\trigger\sitecourse */ - public function test_sitecourse_course() { + public function test_sitecourse_course(): void { $course = get_site(); @@ -75,7 +75,7 @@ public function test_sitecourse_course() { * Tests if courses, which are older than the default of 190 days are triggered by this plugin. * @covers \tool_lifecycle\processor \tool_lifecycle\trigger\sitecourse */ - public function test_normal_course() { + public function test_normal_course(): void { $course = $this->getDataGenerator()->create_course(); diff --git a/trigger/specificdate/classes/privacy/provider.php b/trigger/specificdate/classes/privacy/provider.php index 72e670ce..50e0b6f0 100644 --- a/trigger/specificdate/classes/privacy/provider.php +++ b/trigger/specificdate/classes/privacy/provider.php @@ -34,7 +34,7 @@ class provider implements null_provider { * * @return string the reason */ - public static function get_reason() : string { + public static function get_reason(): string { return 'privacy:metadata'; } } diff --git a/trigger/specificdate/lang/de/lifecycletrigger_specificdate.php b/trigger/specificdate/lang/de/lifecycletrigger_specificdate.php index 51e4efa8..5de91618 100644 --- a/trigger/specificdate/lang/de/lifecycletrigger_specificdate.php +++ b/trigger/specificdate/lang/de/lifecycletrigger_specificdate.php @@ -22,10 +22,10 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['dates'] = 'Daten, an denen der Workflow ausgeführt werden soll.'; +$string['dates_help'] = 'Ein Datum pro Zeile in dem Format Tag.Monat

Zum Beispiel 04.08 für den 4. August. Wenn Sie das heutige Datum wählen, wird es getriggert.'; +$string['dates_not_parseable'] = 'Daten müssen in dem Format Tag.Monat sein!'; $string['pluginname'] = 'Bestimmtes Datum - Trigger'; $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; -$string['dates'] = 'Daten, an denen der Workflow ausgeführt werden soll.'; -$string['dates_help'] = 'Ein Datum pro Zeile in dem Format Tag.Monat

Zum Beispiel 04.08 für den 4. August. Wenn Sie das heutige Datum wählen, wird es getriggert.'; $string['timelastrun'] = 'Datum, an dem der Trigger zuletzt ausgeführt wurde.'; -$string['dates_not_parseable'] = 'Daten müssen in dem Format Tag.Monat sein!'; diff --git a/trigger/specificdate/lang/en/lifecycletrigger_specificdate.php b/trigger/specificdate/lang/en/lifecycletrigger_specificdate.php index d0a2dbb1..0133bab3 100644 --- a/trigger/specificdate/lang/en/lifecycletrigger_specificdate.php +++ b/trigger/specificdate/lang/en/lifecycletrigger_specificdate.php @@ -22,10 +22,10 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['dates'] = 'Dates at which the workflow should run.'; +$string['dates_help'] = 'Write one date per line with the format Day.Month

For example 04.08 for 4th of august. If you put in today\'s date, it will be triggered.'; +$string['dates_not_parseable'] = 'Dates must be of the format Day.Month'; $string['pluginname'] = 'Specific date trigger'; $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; -$string['dates'] = 'Dates at which the workflow should run.'; -$string['dates_help'] = 'Write one date per line with the format Day.Month

For example 04.08 for 4th of august. If you put in today\'s date, it will be triggered.'; $string['timelastrun'] = 'Date when the trigger last run.'; -$string['dates_not_parseable'] = 'Dates must be of the format Day.Month'; diff --git a/trigger/specificdate/lib.php b/trigger/specificdate/lib.php index 9df0bcbd..67922207 100644 --- a/trigger/specificdate/lib.php +++ b/trigger/specificdate/lib.php @@ -80,11 +80,11 @@ public function get_course_recordset_where($triggerid) { $settings['timelastrun'] = $current; $trigger = trigger_manager::get_instance($triggerid); settings_manager::save_settings($triggerid, settings_type::TRIGGER, $trigger->subpluginname, $settings); - return array('true', array()); + return ['true', []]; } } } - return array('false', array()); + return ['false', []]; } /** @@ -95,16 +95,16 @@ public function get_course_recordset_where($triggerid) { */ private function parse_dates($datesraw) { $dates = preg_split('/\r\n|\r|\n/', $datesraw); - $result = array(); + $result = []; foreach ($dates as $date) { $dateparts = explode('.', $date); if (count($dateparts) !== 2) { throw new \moodle_exception("Each date has to consist of two parts devided by point. We got: " . $date); } - $result[] = array( + $result[] = [ 'mon' => $dateparts[1], - 'day' => $dateparts[0] - ); + 'day' => $dateparts[0], + ]; } return $result; } @@ -122,10 +122,10 @@ public function get_subpluginname() { * @return instance_setting[] containing settings keys and PARAM_TYPES */ public function instance_settings() { - return array( + return [ new instance_setting('dates', PARAM_TEXT), new instance_setting('timelastrun', PARAM_INT), - ); + ]; } /** diff --git a/trigger/startdatedelay/classes/privacy/provider.php b/trigger/startdatedelay/classes/privacy/provider.php index f994ae06..b5c52828 100644 --- a/trigger/startdatedelay/classes/privacy/provider.php +++ b/trigger/startdatedelay/classes/privacy/provider.php @@ -34,7 +34,7 @@ class provider implements null_provider { * * @return string the reason */ - public static function get_reason() : string { + public static function get_reason(): string { return 'privacy:metadata'; } } diff --git a/trigger/startdatedelay/lang/de/lifecycletrigger_startdatedelay.php b/trigger/startdatedelay/lang/de/lifecycletrigger_startdatedelay.php index 1be8ecc1..babe5911 100644 --- a/trigger/startdatedelay/lang/de/lifecycletrigger_startdatedelay.php +++ b/trigger/startdatedelay/lang/de/lifecycletrigger_startdatedelay.php @@ -22,8 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['delay'] = 'Zeit seit Kursstartdatum, bis ein Prozess gestartet wird'; +$string['delay_help'] = 'Der Trigger wird ausgeführt, falls die Zeit, die seit dem Start des Kurses vergangen ist, größer ist, als der angegebene Zeitraum.'; $string['pluginname'] = 'Startdatumsabstand - Trigger'; $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; -$string['delay'] = 'Zeit seit Kursstartdatum, bis ein Prozess gestartet wird'; -$string['delay_help'] = 'Der Trigger wird ausgeführt, falls die Zeit, die seit dem Start des Kurses vergangen ist, größer ist, als der angegebene Zeitraum.'; diff --git a/trigger/startdatedelay/lang/en/lifecycletrigger_startdatedelay.php b/trigger/startdatedelay/lang/en/lifecycletrigger_startdatedelay.php index ba6f77df..b03b47e7 100644 --- a/trigger/startdatedelay/lang/en/lifecycletrigger_startdatedelay.php +++ b/trigger/startdatedelay/lang/en/lifecycletrigger_startdatedelay.php @@ -22,8 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['delay'] = 'Delay from start of course until starting a process'; +$string['delay_help'] = 'The trigger will be invoked if the time passed since the course has started is longer than this delay.'; $string['pluginname'] = 'Start date delay trigger'; $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; -$string['delay'] = 'Delay from start of course until starting a process'; -$string['delay_help'] = 'The trigger will be invoked if the time passed since the course has started is longer than this delay.'; diff --git a/trigger/startdatedelay/lib.php b/trigger/startdatedelay/lib.php index 01e3d0ed..7f9f5940 100644 --- a/trigger/startdatedelay/lib.php +++ b/trigger/startdatedelay/lib.php @@ -60,10 +60,10 @@ public function check_course($course, $triggerid) { public function get_course_recordset_where($triggerid) { $delay = settings_manager::get_settings($triggerid, settings_type::TRIGGER)['delay']; $where = "{course}.startdate < :startdatedelay"; - $params = array( + $params = [ "startdatedelay" => time() - $delay, - ); - return array($where, $params); + ]; + return [$where, $params]; } /** @@ -79,9 +79,9 @@ public function get_subpluginname() { * @return instance_setting[] containing settings keys and PARAM_TYPES */ public function instance_settings() { - return array( - new instance_setting('delay', PARAM_INT, true) - ); + return [ + new instance_setting('delay', PARAM_INT, true), + ]; } /** diff --git a/trigger/startdatedelay/tests/trigger_test.php b/trigger/startdatedelay/tests/trigger_test.php index 0175bf4e..fe04e71c 100644 --- a/trigger/startdatedelay/tests/trigger_test.php +++ b/trigger/startdatedelay/tests/trigger_test.php @@ -40,7 +40,7 @@ * @copyright 2017 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class trigger_test extends \advanced_testcase { +final class trigger_test extends \advanced_testcase { /** @var $triggerinstance trigger_subplugin Instance of the trigger. */ private $triggerinstance; @@ -48,7 +48,7 @@ class trigger_test extends \advanced_testcase { /** @var $processor processor Instance of the lifecycle processor. */ private $processor; - public function setUp() : void { + public function setUp(): void { $this->resetAfterTest(true); $this->setAdminUser(); @@ -60,9 +60,9 @@ public function setUp() : void { * Tests if courses, which are newer than the default of 190 days are not triggered by this plugin. * @covers \tool_lifecycle\processor \tool_lifecycle\trigger\startdatedelay */ - public function test_young_course() { + public function test_young_course(): void { - $course = $this->getDataGenerator()->create_course(array('startdate' => time() - 50 * 24 * 60 * 60)); + $course = $this->getDataGenerator()->create_course(['startdate' => time() - 50 * 24 * 60 * 60]); $recordset = $this->processor->get_course_recordset([$this->triggerinstance], []); $found = false; @@ -79,9 +79,9 @@ public function test_young_course() { * Tests if courses, which are older than the default of 190 days are triggered by this plugin. * @covers \tool_lifecycle\processor \tool_lifecycle\trigger\startdatedelay */ - public function test_old_course() { + public function test_old_course(): void { - $course = $this->getDataGenerator()->create_course(array('startdate' => time() - 200 * 24 * 60 * 60)); + $course = $this->getDataGenerator()->create_course(['startdate' => time() - 200 * 24 * 60 * 60]); $recordset = $this->processor->get_course_recordset([$this->triggerinstance], []); $found = false; diff --git a/uploadworkflow.php b/uploadworkflow.php index 7fd08dfb..351adebb 100644 --- a/uploadworkflow.php +++ b/uploadworkflow.php @@ -22,13 +22,10 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -use tool_lifecycle\action; +use core\notification; use tool_lifecycle\local\backup\restore_lifecycle_workflow; -use tool_lifecycle\local\entity\workflow; use tool_lifecycle\local\form\form_upload_workflow; -use tool_lifecycle\local\form\form_workflow_instance; -use tool_lifecycle\local\manager\workflow_manager; -use tool_lifecycle\local\table\workflow_definition_table; +use tool_lifecycle\permission_and_navigation; use tool_lifecycle\urls; require_once(__DIR__ . '/../../../config.php'); @@ -36,7 +33,7 @@ require_login(); global $OUTPUT, $PAGE, $DB; -\tool_lifecycle\permission_and_navigation::setup_draft(); +permission_and_navigation::setup_draft(); $PAGE->set_url(new \moodle_url(urls::UPLOAD_WORKFLOW)); $title = get_string('upload_workflow', 'tool_lifecycle'); @@ -55,15 +52,22 @@ if ($data = $form->get_data()) { $xmldata = $form->get_file_content('backupfile'); $restore = new restore_lifecycle_workflow($xmldata); - $errors = $restore->execute(); + $force = $data->force ?? false; + $errors = $restore->execute($force); if (count($errors) != 0) { + notification::add(get_string('workflow_was_not_imported', 'tool_lifecycle'), notification::ERROR); + foreach (array_unique($errors) as $error) { + notification::add($error, notification::ERROR); + } + $form = new form_upload_workflow(null, ['showforce' => true]); + /** @var \tool_lifecycle_renderer $renderer */ $renderer = $PAGE->get_renderer('tool_lifecycle'); - $renderer->render_workflow_upload_form($form, $errors); + $renderer->render_workflow_upload_form($form); die(); } else { // Redirect to workflow page. - redirect(urls::WORKFLOW_DETAILS, ['wf' => $restore->get_workflow()->id]); + redirect(new moodle_url(urls::WORKFLOW_DETAILS, ['wf' => $restore->get_workflow()->id])); } } diff --git a/version.php b/version.php index 76fb3600..e8f6b54a 100644 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die; $plugin->maturity = MATURITY_BETA; -$plugin->version = 2022112400; +$plugin->version = 2024042300; $plugin->component = 'tool_lifecycle'; -$plugin->requires = 2020061500; // Requires Moodle 3.9+. -$plugin->release = 'v4.1-r1'; +$plugin->requires = 2022112800; // Requires Moodle 4.1+. +$plugin->release = 'v4.4-r1'; diff --git a/view.php b/view.php index 245c9a46..73036694 100644 --- a/view.php +++ b/view.php @@ -21,6 +21,7 @@ * @copyright 2017 Tobias Reischmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + require_once(__DIR__ . '/../../../config.php'); require_login(null, false); diff --git a/workflowoverview.php b/workflowoverview.php index c4229929..d0ff6a80 100644 --- a/workflowoverview.php +++ b/workflowoverview.php @@ -21,6 +21,7 @@ * @copyright 2021 Nina Herrmann and Justus Dieckmann, WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + require_once(__DIR__ . '/../../../config.php'); require_once($CFG->libdir . '/adminlib.php'); require_login(); @@ -84,21 +85,31 @@ 'edit' => get_string('edit'), 'delete' => get_string('delete'), 'move_up' => get_string('move_up', 'tool_lifecycle'), - 'move_down' => get_string('move_down', 'tool_lifecycle') + 'move_down' => get_string('move_down', 'tool_lifecycle'), ]; -$amounts = (new \tool_lifecycle\processor())->get_count_of_courses_to_trigger_for_workflow($workflow->id); -$displaytotaltriggered = !empty($triggers); +$showcoursecounts = get_config('tool_lifecycle', 'showcoursecounts'); +if ($showcoursecounts) { + // On moodle instances with many courses the following call can be fatal, because each trigger + // check function will be called for every single course of the instance to determine how many + // courses will be triggered by the workflow/the specific trigger. This count is only being + // used to show the admin how many courses will be triggered, it has no functional aspect. + $amounts = (new \tool_lifecycle\processor())->get_count_of_courses_to_trigger_for_workflow($workflow->id); + $displaytotaltriggered = !empty($triggers); +} + +$displaytriggers = []; +$displaysteps = []; foreach ($triggers as $trigger) { // The array from the DB Function uses ids as keys. // Mustache cannot handle arrays which have other keys therefore a new array is build. // FUTURE: Nice to have Icon for each subplugin. - + $trigger = (object)(array) $trigger; // Cast to normal object to be able to set dynamic properties. $actionmenu = new action_menu([ new action_menu_link_secondary( new moodle_url(urls::EDIT_ELEMENT, ['type' => settings_type::TRIGGER, 'elementid' => $trigger->id]), - new pix_icon('i/edit', $str['edit']), $str['edit']) + new pix_icon('i/edit', $str['edit']), $str['edit']), ]); if ($iseditable) { $actionmenu->add(new action_menu_link_secondary( @@ -108,17 +119,21 @@ ); } $trigger->actionmenu = $OUTPUT->render($actionmenu); - $trigger->automatic = $amounts[$trigger->sortindex]->automatic; - $displaytotaltriggered &= $trigger->automatic; - if ($trigger->automatic) { - $trigger->triggeredcourses = $amounts[$trigger->sortindex]->triggered; - $trigger->excludedcourses = $amounts[$trigger->sortindex]->excluded; + if ($showcoursecounts) { + $trigger->automatic = $amounts[$trigger->sortindex]->automatic; + $displaytotaltriggered &= $trigger->automatic; + if ($trigger->automatic) { + $trigger->triggeredcourses = $amounts[$trigger->sortindex]->triggered; + $trigger->excludedcourses = $amounts[$trigger->sortindex]->excluded; + } } + $displaytriggers[] = $trigger; } foreach ($steps as $step) { + $step = (object)(array) $step; // Cast to normal object to be able to set dynamic properties. $ncourses = $DB->count_records('tool_lifecycle_process', - array('stepindex' => $step->sortindex, 'workflowid' => $workflowid)); + ['stepindex' => $step->sortindex, 'workflowid' => $workflowid]); $step->numberofcourses = $ncourses; if ($step->id == $stepid) { $step->selected = true; @@ -126,7 +141,7 @@ $actionmenu = new action_menu([ new action_menu_link_secondary( new moodle_url(urls::EDIT_ELEMENT, ['type' => settings_type::STEP, 'elementid' => $step->id]), - new pix_icon('i/edit', $str['edit']), $str['edit']) + new pix_icon('i/edit', $str['edit']), $str['edit']), ]); if ($iseditable) { $actionmenu->add(new action_menu_link_secondary( @@ -150,11 +165,12 @@ } } $step->actionmenu = $OUTPUT->render($actionmenu); + $displaysteps[] = $step; } -$arrayofcourses = array(); +$arrayofcourses = []; -$url = new moodle_url(urls::WORKFLOW_DETAILS, array('wf' => $workflowid)); +$url = new moodle_url(urls::WORKFLOW_DETAILS, ['wf' => $workflowid]); $out = null; if ($stepid) { @@ -175,16 +191,19 @@ 'rollbackdelay' => format_time($workflow->rollbackdelay), 'finishdelay' => format_time($workflow->finishdelay), 'delayglobally' => $workflow->delayforallworkflows, - 'trigger' => array_values($triggers), - 'automatic' => $displaytotaltriggered, - 'coursestriggered' => $amounts['all']->triggered, - 'coursesexcluded' => $amounts['all']->excluded, - 'coursesetsize' => $amounts['all']->coursesetsize, - 'steps' => array_values($steps), + 'trigger' => $displaytriggers, + 'showcoursecounts' => $showcoursecounts, + 'steps' => $displaysteps, 'listofcourses' => $arrayofcourses, 'nosteplink' => $nosteplink, - 'table' => $out + 'table' => $out, ]; +if ($showcoursecounts) { + $data['automatic'] = $displaytotaltriggered; + $data['coursestriggered'] = $amounts['all']->triggered; + $data['coursesexcluded'] = $amounts['all']->excluded; + $data['coursesetsize'] = $amounts['all']->coursesetsize; +} echo $renderer->header(); @@ -205,15 +224,15 @@ $addinstance .= $OUTPUT->render_from_template('tool_lifecycle/warn_icon', $icondata); $addinstance .= $OUTPUT->single_select(new \moodle_url(urls::EDIT_ELEMENT, - array('type' => settings_type::TRIGGER, 'wf' => $workflow->id)), - 'subplugin', $selectabletriggers, '', array('' => get_string('add_new_trigger_instance', 'tool_lifecycle')), + ['type' => settings_type::TRIGGER, 'wf' => $workflow->id]), + 'subplugin', $selectabletriggers, '', ['' => get_string('add_new_trigger_instance', 'tool_lifecycle')], null, ['id' => 'tool_lifecycle-choose-trigger']); $steps = step_manager::get_step_types(); $addinstance .= ''; $addinstance .= $OUTPUT->single_select(new \moodle_url(urls::EDIT_ELEMENT, - array('type' => settings_type::STEP, 'wf' => $workflow->id)), - 'subplugin', $steps, '', array('' => get_string('add_new_step_instance', 'tool_lifecycle')), + ['type' => settings_type::STEP, 'wf' => $workflow->id]), + 'subplugin', $steps, '', ['' => get_string('add_new_step_instance', 'tool_lifecycle')], null, ['id' => 'tool_lifecycle-choose-step']); $data['addinstance'] = $addinstance; }