├── .github └── workflows │ ├── config.json │ ├── moodle-ci.yml │ └── moodle-release.yml ├── .gitignore ├── CHANGES.md ├── LICENSE ├── README.md ├── activeprocesses.php ├── activeworkflows.php ├── amd ├── build │ ├── tablebulkactions.min.js │ └── tablebulkactions.min.js.map └── src │ └── tablebulkactions.js ├── classes ├── action.php ├── event │ ├── process_proceeded.php │ ├── process_rollback.php │ └── process_triggered.php ├── local │ ├── backup │ │ ├── backup_lifecycle_workflow.php │ │ └── restore_lifecycle_workflow.php │ ├── data │ │ └── manual_trigger_tool.php │ ├── entity │ │ ├── process.php │ │ ├── step_subplugin.php │ │ ├── subplugin.php │ │ ├── trigger_subplugin.php │ │ └── workflow.php │ ├── form │ │ ├── form_courses_filter.php │ │ ├── form_delays_filter.php │ │ ├── form_delete_delays.php │ │ ├── form_step_instance.php │ │ ├── form_trigger_instance.php │ │ ├── form_upload_workflow.php │ │ └── form_workflow_instance.php │ ├── manager │ │ ├── backup_manager.php │ │ ├── delayed_courses_manager.php │ │ ├── interaction_manager.php │ │ ├── lib_manager.php │ │ ├── process_data_manager.php │ │ ├── process_manager.php │ │ ├── settings_manager.php │ │ ├── step_manager.php │ │ ├── subplugin_manager.php │ │ ├── trigger_manager.php │ │ └── workflow_manager.php │ ├── response │ │ ├── step_interactive_response.php │ │ ├── step_response.php │ │ └── trigger_response.php │ └── table │ │ ├── active_automatic_workflows_table.php │ │ ├── active_manual_workflows_table.php │ │ ├── active_processes_table.php │ │ ├── active_workflows_table.php │ │ ├── course_backups_table.php │ │ ├── courses_in_step_table.php │ │ ├── deactivated_workflows_table.php │ │ ├── delayed_courses_table.php │ │ ├── interaction_attention_table.php │ │ ├── interaction_remaining_table.php │ │ ├── interaction_table.php │ │ ├── process_errors_table.php │ │ ├── select_workflow_table.php │ │ ├── triggered_courses_table.php │ │ ├── workflow_definition_table.php │ │ └── workflow_table.php ├── permission_and_navigation.php ├── plugininfo │ ├── lifecyclestep.php │ └── lifecycletrigger.php ├── privacy │ └── provider.php ├── processor.php ├── settings_type.php ├── tabs.php ├── task │ ├── lifecycle_cleanup_task.php │ ├── lifecycle_error_notify_task.php │ └── lifecycle_task.php ├── urls.php └── view_controller.php ├── confirmation.php ├── coursebackups.php ├── createworkflowfromexisting.php ├── db ├── access.php ├── caches.php ├── events.php ├── install.xml ├── subplugins.json ├── subplugins.php ├── tasks.php └── upgrade.php ├── deactivatedworkflows.php ├── delayedcourses.php ├── downloadbackup.php ├── editelement.php ├── editworkflow.php ├── errors.php ├── lang ├── de │ └── tool_lifecycle.php └── en │ └── tool_lifecycle.php ├── lib.php ├── pix ├── icon.svg └── t │ └── disable.svg ├── renderer.php ├── restore.php ├── settings.php ├── step ├── adminapprove │ ├── README.md │ ├── amd │ │ ├── build │ │ │ ├── init.min.js │ │ │ ├── init.min.js.map │ │ │ ├── link-steps.min.js │ │ │ └── link-steps.min.js.map │ │ └── src │ │ │ ├── init.js │ │ │ └── link-steps.js │ ├── approvestep.php │ ├── classes │ │ ├── course_filter_form.php │ │ ├── decision_table.php │ │ ├── privacy │ │ │ └── provider.php │ │ └── step_table.php │ ├── db │ │ ├── caches.php │ │ ├── install.xml │ │ └── upgrade.php │ ├── index.php │ ├── interactionlib.php │ ├── lang │ │ ├── de │ │ │ └── lifecyclestep_adminapprove.php │ │ └── en │ │ │ └── lifecyclestep_adminapprove.php │ ├── lib.php │ ├── tests │ │ ├── admin_approve_test.php │ │ └── behat │ │ │ ├── behat_lifecyclestep_adminapprove.php │ │ │ ├── proceedtest.feature │ │ │ └── teacherview.feature │ └── version.php ├── createbackup │ ├── classes │ │ └── privacy │ │ │ └── provider.php │ ├── db │ │ └── upgrade.php │ ├── lang │ │ ├── de │ │ │ └── lifecyclestep_createbackup.php │ │ └── en │ │ │ └── lifecyclestep_createbackup.php │ ├── lib.php │ └── version.php ├── deletecourse │ ├── classes │ │ └── privacy │ │ │ └── provider.php │ ├── db │ │ └── upgrade.php │ ├── lang │ │ ├── de │ │ │ └── lifecyclestep_deletecourse.php │ │ └── en │ │ │ └── lifecyclestep_deletecourse.php │ ├── lib.php │ └── version.php ├── duplicate │ ├── classes │ │ ├── form_duplicate.php │ │ └── privacy │ │ │ └── provider.php │ ├── db │ │ └── access.php │ ├── interactionlib.php │ ├── lang │ │ ├── de │ │ │ └── lifecyclestep_duplicate.php │ │ └── en │ │ │ └── lifecyclestep_duplicate.php │ ├── lib.php │ └── version.php ├── email │ ├── classes │ │ └── privacy │ │ │ └── provider.php │ ├── db │ │ ├── access.php │ │ ├── install.xml │ │ └── upgrade.php │ ├── interactionlib.php │ ├── lang │ │ ├── de │ │ │ └── lifecyclestep_email.php │ │ └── en │ │ │ └── lifecyclestep_email.php │ ├── lib.php │ ├── tests │ │ ├── lib_test.php │ │ └── privacy │ │ │ └── provider_test.php │ └── version.php ├── interactionlib.php ├── lib.php └── makeinvisible │ ├── README.md │ ├── classes │ └── privacy │ │ └── provider.php │ ├── lang │ ├── de │ │ └── lifecyclestep_makeinvisible.php │ └── en │ │ └── lifecyclestep_makeinvisible.php │ ├── lib.php │ ├── tests │ └── make_invisible_test.php │ └── version.php ├── styles.css ├── templates ├── overview_addinstance.mustache ├── overview_step.mustache ├── overview_timetrigger.mustache ├── overview_trigger.mustache ├── search_input.mustache └── workflowoverview.mustache ├── tests ├── active_workflow_is_manual_test.php ├── active_workflow_sortindex_updown_test.php ├── backup_and_restore_workflow_test.php ├── backup_manager_test.php ├── behat │ ├── activate_workflow.feature │ ├── add_workflow.feature │ ├── behat_tool_lifecycle.php │ ├── disable_workflow.feature │ ├── interaction.feature │ ├── interaction_forms.feature │ ├── manual_trigger.feature │ └── upload_workflow.feature ├── fixtures │ └── simpleworkflow.xml ├── generator │ └── lib.php ├── manual_trigger_tools_test.php ├── manually_triggered_process_test.php ├── persistence │ ├── persist_process_data_test.php │ ├── persist_process_test.php │ ├── persist_step_test.php │ └── persist_workflow_test.php ├── phpunit.xml ├── privacy_test.php ├── process_error_test.php ├── process_status_message_test.php ├── settings_manager_test.php ├── workflow_actions_testcase.php └── workflow_activate_disable_duplicate_test.php ├── trigger ├── byrole │ ├── LICENSE │ ├── README.md │ ├── classes │ │ └── privacy │ │ │ └── provider.php │ ├── db │ │ └── install.xml │ ├── lang │ │ ├── de │ │ │ └── lifecycletrigger_byrole.php │ │ └── en │ │ │ └── lifecycletrigger_byrole.php │ ├── lib.php │ ├── tests │ │ ├── generator │ │ │ └── lib.php │ │ └── lifecycletrigger_byrole_test.php │ └── version.php ├── categories │ ├── classes │ │ └── privacy │ │ │ └── provider.php │ ├── lang │ │ ├── de │ │ │ └── lifecycletrigger_categories.php │ │ └── en │ │ │ └── lifecycletrigger_categories.php │ ├── lib.php │ ├── tests │ │ ├── generator │ │ │ └── lib.php │ │ └── trigger_test.php │ └── version.php ├── customfielddelay │ ├── README.md │ ├── classes │ │ └── privacy │ │ │ └── provider.php │ ├── lang │ │ ├── de │ │ │ └── lifecycletrigger_customfielddelay.php │ │ └── en │ │ │ └── lifecycletrigger_customfielddelay.php │ ├── lib.php │ ├── tests │ │ ├── generator │ │ │ └── lib.php │ │ └── trigger_test.php │ └── version.php ├── delayedcourses │ ├── classes │ │ └── privacy │ │ │ └── provider.php │ ├── lang │ │ ├── de │ │ │ └── lifecycletrigger_delayedcourses.php │ │ └── en │ │ │ └── lifecycletrigger_delayedcourses.php │ ├── lib.php │ └── version.php ├── lib.php ├── manual │ ├── classes │ │ └── privacy │ │ │ └── provider.php │ ├── lang │ │ ├── de │ │ │ └── lifecycletrigger_manual.php │ │ └── en │ │ │ └── lifecycletrigger_manual.php │ ├── lib.php │ └── version.php ├── semindependent │ ├── .travis.yml │ ├── README.md │ ├── db │ │ └── upgrade.php │ ├── lang │ │ ├── de │ │ │ └── lifecycletrigger_semindependent.php │ │ └── en │ │ │ └── lifecycletrigger_semindependent.php │ ├── lib.php │ ├── tests │ │ ├── generator │ │ │ └── lib.php │ │ └── trigger_test.php │ └── version.php ├── sitecourse │ ├── classes │ │ └── privacy │ │ │ └── provider.php │ ├── lang │ │ ├── de │ │ │ └── lifecycletrigger_sitecourse.php │ │ └── en │ │ │ └── lifecycletrigger_sitecourse.php │ ├── lib.php │ └── version.php ├── specificdate │ ├── classes │ │ └── privacy │ │ │ └── provider.php │ ├── lang │ │ ├── de │ │ │ └── lifecycletrigger_specificdate.php │ │ └── en │ │ │ └── lifecycletrigger_specificdate.php │ ├── lib.php │ └── version.php └── startdatedelay │ ├── classes │ └── privacy │ │ └── provider.php │ ├── lang │ ├── de │ │ └── lifecycletrigger_startdatedelay.php │ └── en │ │ └── lifecycletrigger_startdatedelay.php │ ├── lib.php │ ├── tests │ ├── generator │ │ └── lib.php │ └── trigger_test.php │ └── version.php ├── uploadworkflow.php ├── version.php ├── view.php ├── workflowdrafts.php └── workflowoverview.php /.github/workflows/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "main-moodle": "MOODLE_405_STABLE", 3 | "main-php": "8.3", 4 | "moodle-php": { 5 | "MOODLE_401_STABLE": ["8.0","8.1"], 6 | "MOODLE_405_STABLE": ["8.1","8.2","8.3"] 7 | }, 8 | "moodle-plugin-ci": "4.4.5" 9 | } 10 | -------------------------------------------------------------------------------- /.github/workflows/moodle-ci.yml: -------------------------------------------------------------------------------- 1 | name: Moodle Plugin CI 2 | on: [ push, pull_request ] 3 | 4 | jobs: 5 | call: 6 | name: "" 7 | uses: learnweb/moodle-workflows-learnweb/.github/workflows/moodle-ci.yml@main 8 | -------------------------------------------------------------------------------- /.github/workflows/moodle-release.yml: -------------------------------------------------------------------------------- 1 | name: Moodle Plugin Release 2 | 3 | on: 4 | release: 5 | types: [ published ] 6 | 7 | jobs: 8 | call-moodle-release-workflow: 9 | uses: learnweb/moodle-workflows-learnweb/.github/workflows/moodle-release.yml@main 10 | with: 11 | plugin-name: 'tool_lifecycle' 12 | secrets: inherit 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Used for simulating cron during development 2 | development.php 3 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | CHANGELOG 2 | ========= 3 | 4 | 4.5.0 (2025-05-04) 5 | ------------------ 6 | * [FEATURE] Workflowoverview: Added possibility to select single courses for process 7 | * [FEATURE] Add customfielddelay trigger 8 | * [FEATURE] At least one trigger and one step necessary for activating a workflow 9 | * [FEATURE] After workflow creation you have to add course selection trigger at first 10 | * [FEATURE] Exclude processed courses from trigger counting 11 | * [FEATURE] Prepare for not included trigger customfieldsemester 12 | * [FEATURE] Workflowoverview: separate course selection and course selection run triggers 13 | * [FEATURE] Improve performance of processor 14 | * [FEATURE] Improve performance of get_count_of_courses_to_trigger_for_workflow 15 | * [FEATURE] Shorter tab texts and introduce tab titles 16 | * [FEATURE] Replace triggers sitecourse and delayedcourses by workflow instance options 17 | * [FEATURE] Add triggers byrole and semindependent and step makeinvisible 18 | * [FEATURE] The step adminapprove is now a fixed part of the lifecycle plugin 19 | * [FEATURE] Workflowoverview: search field for course lists only in case of paging 20 | * [FEATURE] Workflowoverview: Display number and list of courses which are part of a process already 21 | * [FEATURE] Delayed courses page: confirmation needed when deleting all delays 22 | * [FEATURE] Workflowoverview: display delayed courses; courses lists also for triggers; search function in course lists 23 | * [FEATURE] Workflowoverview draft workflow: Introduce "Activate"-button 24 | * [FEATURE] Administration subpages organized by tabs (#237) 25 | * [FEATURE] Email: Clear separation in courses-list (#231) 26 | * [FEATURE] Fix error when otherindex does not exist (#192) 27 | * [FEATURE] Use field courseid for logging events (#203) 28 | * [FEATURE] Show category of specified level in interaction tables (#216) 29 | * [FEATURE] Email: add ##shortcourses## placeholder (#215) 30 | * [FEATURE] Store log data of sending emails in database (#218) 31 | * [FEATURE] In case the action column is empty display a string (#217) 32 | * [FEATURE] Add checkbox "only once a day" to admin setting for trigger specificdate (#221) 33 | * [FEATURE] Allow steps to run when course no longer exists (#222) (#223) 34 | * [FEATURE] Add validation for step form (#226) 35 | * [FIXED] Add character length input field validation for step and trigger names (#232) 36 | * [FIXED] Capability "viewhiddencourses" is not applied to Lifecycle's "Manage courses" (#234) 37 | * [FIXED] Backups not working if backup_auto_destination for automated backups is set (#233) 38 | * Moodle 4.5 compatible version 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Course Life Cycle (moodle-tool_lifecycle) 2 | 3 | [![Build Status](https://travis-ci.org/learnweb/moodle-tool_lifecycle.svg?branch=master)](https://travis-ci.org/learnweb/moodle-tool_lifecycle) 4 | [![codecov](https://codecov.io/gh/learnweb/moodle-tool_lifecycle/branch/master/graph/badge.svg)](https://codecov.io/gh/learnweb/moodle-tool_lifecycle) 5 | 6 | [Presentation Video Moodle Moot 2022](https://www.youtube.com/watch?v=7IduhrBMve4) | 7 | [Slides](https://moodle.academy/pluginfile.php/42164/mod_data/content/2470/04-9-Finally_%20Deleting%20Courses%20Automatically.pdf) 8 | 9 | This plugin provides a modular framework, similar to a workflow engine, which allows the to execute recurring tasks within moodle associated with courses. 10 | Possible use cases are (not limited to): 11 | - Deleting courses at end of life (including asking teachers for permission). 12 | - Doing a rollover at the end of a semester. 13 | - Automatically setting an end date for courses. 14 | 15 | To be adaptable to the needs of different institutions the plugin provides two subplugin types: 16 | 17 | **Trigger**: These subplugins control the conditions a course must meet so that a specific process is started. 18 | 19 | **Step**: These subplugins represent atomic, reusable tasks that should be executed for a specific course. 20 | 21 | ## Subplugins 22 | Requirements that are specific to your institution can be added through additional subplugins. 23 | 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)). 24 | It provides instructions for administrators as well as for developers to implement their own requirements into subplugins. 25 | 26 | Installation 27 | ============ 28 | This is an admin plugin and should go into ``admin/tool/lifecycle``. 29 | Obtain this plugin from https://moodle.org/plugins/view/tool_lifecycle. 30 | 31 | Moodle version 32 | ============== 33 | The plugin is continously tested with all moodle versions, which are security supported by the moodle headquarter. 34 | Therefore, Travis uses the most current release to build a test instance and run the behat and unit tests on them. 35 | In addition to all stable branches the version is tested against the master branch to support early adopters. 36 | 37 | Changelog 38 | ========= 39 | The changes for every release are listed here: https://github.com/learnweb/moodle-tool_lifecycle/wiki/Change-log. 40 | -------------------------------------------------------------------------------- /activeprocesses.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Display the list of active processes 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2025 Thomas Niedermaier University Münster 22 | * @copyright 2017 Tobias Reischmann WWU 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | use tool_lifecycle\local\form\form_courses_filter; 27 | use tool_lifecycle\local\table\active_processes_table; 28 | use tool_lifecycle\tabs; 29 | use tool_lifecycle\urls; 30 | 31 | require_once(__DIR__ . '/../../../config.php'); 32 | require_once($CFG->libdir . '/adminlib.php'); 33 | 34 | require_login(); 35 | 36 | $syscontext = context_system::instance(); 37 | $PAGE->set_url(new \moodle_url(urls::ACTIVE_PROCESSES)); 38 | $PAGE->set_context($syscontext); 39 | 40 | $PAGE->set_pagetype('admin-setting-' . 'tool_lifecycle'); 41 | $PAGE->set_pagelayout('admin'); 42 | 43 | $mform = new form_courses_filter(); 44 | 45 | // Cache handling. 46 | $cachekey = 'activeprocesses_filter'; 47 | $cache = cache::make('tool_lifecycle', 'mformdata'); 48 | if ($search = optional_param('search', null, PARAM_RAW)) { 49 | $obj = new stdClass(); 50 | $obj->fullname = $search; 51 | $obj->courseid = null; 52 | $obj->shortname = null; 53 | $cache->set($cachekey, $obj); 54 | redirect($PAGE->url); 55 | } 56 | 57 | if ($mform->is_cancelled()) { 58 | $cache->delete($cachekey); 59 | redirect($PAGE->url); 60 | } else if ($data = $mform->get_data()) { 61 | $cache->set($cachekey, $data); 62 | } else { 63 | $data = $cache->get($cachekey); 64 | if ($data) { 65 | $mform->set_data($data); 66 | } 67 | } 68 | 69 | $renderer = $PAGE->get_renderer('tool_lifecycle'); 70 | 71 | $heading = get_string('pluginname', 'tool_lifecycle')." / ".get_string('find_course_list_header', 'tool_lifecycle'); 72 | echo $renderer->header($heading); 73 | $tabrow = tabs::get_tabrow(true); 74 | $id = 'activeworkflows'; 75 | $renderer->tabs($tabrow, $id); 76 | 77 | $table = new active_processes_table('tool_lifecycle_active_processes', $data); 78 | 79 | $mform->display(); 80 | 81 | $table->out(50, false); 82 | 83 | echo $renderer->footer(); 84 | 85 | 86 | -------------------------------------------------------------------------------- /amd/build/tablebulkactions.min.js: -------------------------------------------------------------------------------- 1 | define("tool_lifecycle/tablebulkactions",["exports"],(function(_exports){ 2 | /** 3 | * Javascript controller for checkboxed table. 4 | * @module tool_lifecycle/tablebulkactions 5 | * @copyright 2021 Justus Dieckmann WWU 6 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 7 | */ 8 | function redirectPost(url,data){const form=document.createElement("form");document.body.appendChild(form),form.method="post",form.action=url;for(const pair of data){const input=document.createElement("input");input.type="hidden",input.name=pair.k,input.value=pair.v,form.appendChild(input)}form.submit()}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){const checkboxes=document.querySelectorAll('input[name="procerror-select"]');document.querySelectorAll("*[data-lifecycle-action]").forEach((a=>{a.onclick=e=>{e.preventDefault();let data=[{k:"action",v:a.getAttribute("data-lifecycle-action")},{k:"sesskey",v:M.cfg.sesskey}];"1"===a.getAttribute("data-lifecycle-forall")?(data.push({k:"all",v:"1"}),redirectPost(window.location,data)):(checkboxes.forEach((c=>{c.checked&&data.push({k:"id[]",v:c.value})})),redirectPost(window.location,data))}}))}})); 9 | 10 | //# sourceMappingURL=tablebulkactions.min.js.map -------------------------------------------------------------------------------- /amd/src/tablebulkactions.js: -------------------------------------------------------------------------------- 1 | // This file is part of Moodle - http://moodle.org/ 2 | // 3 | // Moodle is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // Moodle is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with Moodle. If not, see . 15 | 16 | /** 17 | * Javascript controller for checkboxed table. 18 | * @module tool_lifecycle/tablebulkactions 19 | * @copyright 2021 Justus Dieckmann WWU 20 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 21 | */ 22 | 23 | /** 24 | * Helper function to redirect via POST 25 | * @param {String} url redirect to 26 | * @param {Array} data redirect with data 27 | */ 28 | function redirectPost(url, data) { 29 | const form = document.createElement('form'); 30 | document.body.appendChild(form); 31 | form.method = 'post'; 32 | form.action = url; 33 | for (const pair of data) { 34 | const input = document.createElement('input'); 35 | input.type = 'hidden'; 36 | input.name = pair.k; 37 | input.value = pair.v; 38 | form.appendChild(input); 39 | } 40 | form.submit(); 41 | } 42 | 43 | /** 44 | * Init function 45 | */ 46 | export function init() { 47 | const checkboxes = document.querySelectorAll('input[name="procerror-select"]'); 48 | 49 | const action = document.querySelectorAll('*[data-lifecycle-action]'); 50 | action.forEach((a) => { 51 | a.onclick = (e) => { 52 | e.preventDefault(); 53 | let data = [ 54 | {k: 'action', v: a.getAttribute('data-lifecycle-action')}, 55 | {k: 'sesskey', v: M.cfg.sesskey} 56 | ]; 57 | if (a.getAttribute('data-lifecycle-forall') === '1') { 58 | data.push({k: 'all', v: '1'}); 59 | redirectPost(window.location, data); 60 | } else { 61 | checkboxes.forEach((c) => { 62 | if (c.checked) { 63 | data.push({k: 'id[]', v: c.value}); 64 | } 65 | }); 66 | redirectPost(window.location, data); 67 | } 68 | }; 69 | }); 70 | } -------------------------------------------------------------------------------- /classes/local/data/manual_trigger_tool.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Class representing a manual trigger tool 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2018 WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | namespace tool_lifecycle\local\data; 25 | 26 | use renderable; 27 | 28 | /** 29 | * Class representing a manual trigger tool 30 | * 31 | * @package tool_lifecycle 32 | * @copyright 2018 WWU 33 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 34 | */ 35 | class manual_trigger_tool implements renderable { 36 | 37 | /** @var int $triggerid Id of the trigger the tool belongs to. */ 38 | public $triggerid; 39 | 40 | /** @var string $icon Icon, which is displayed to the user in the trigger tools menu. */ 41 | public $icon; 42 | 43 | /** @var string $displayname Name, which is displayed to the user in the trigger tools menu. */ 44 | public $displayname; 45 | 46 | /** @var string $capability Capability, which is required to use and display this tool. */ 47 | public $capability; 48 | 49 | /** 50 | * manual_trigger_tool constructor. 51 | * @param int $triggerid Id of the trigger the tool belongs to. 52 | * @param string $icon Icon, which is displayed to the user in the trigger tools menu. 53 | * @param string $displayname Name, which is displayed to the user in the trigger tools menu. 54 | * @param string $capability Capability, which is required to use and display this tool. 55 | */ 56 | public function __construct($triggerid, $icon, $displayname, $capability) { 57 | $this->triggerid = $triggerid; 58 | $this->icon = $icon; 59 | $this->displayname = $displayname; 60 | $this->capability = $capability; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /classes/local/entity/step_subplugin.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Subplugin class 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | namespace tool_lifecycle\local\entity; 25 | 26 | /** 27 | * Subplugin class 28 | * 29 | * @package tool_lifecycle 30 | * @copyright 2017 Tobias Reischmann WWU 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | class step_subplugin extends subplugin { 34 | 35 | /** 36 | * Creates a subplugin from a db record. 37 | * @param object $record Data object. 38 | * @return step_subplugin 39 | */ 40 | public static function from_record($record) { 41 | if (!object_property_exists($record, 'subpluginname')) { 42 | return null; 43 | } 44 | if (!object_property_exists($record, 'instancename')) { 45 | return null; 46 | } 47 | if (!object_property_exists($record, 'workflowid')) { 48 | return null; 49 | } 50 | $id = null; 51 | if (object_property_exists($record, 'id') && !empty($record->id)) { 52 | $id = $record->id; 53 | } 54 | $instance = new self($record->instancename, $record->subpluginname, $record->workflowid, $id); 55 | if (object_property_exists($record, 'sortindex') ) { 56 | $instance->sortindex = $record->sortindex; 57 | } 58 | 59 | return $instance; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /classes/local/entity/subplugin.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Subplugin class 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | namespace tool_lifecycle\local\entity; 25 | 26 | /** 27 | * Subplugin class 28 | * 29 | * @package tool_lifecycle 30 | * @copyright 2017 Tobias Reischmann WWU 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | abstract class subplugin { 34 | 35 | /** @var int $id Id of subplugin */ 36 | public $id; 37 | 38 | /** @var string $instancename Instancename of the step*/ 39 | public $instancename; 40 | 41 | /** @var int $workflowid Id of the workflow this step belongs to*/ 42 | public $workflowid; 43 | 44 | /** @var string $subpluginname Name of subplugin */ 45 | public $subpluginname; 46 | 47 | /** @var int $sortindex Sort index, which defines the order, 48 | * in which the steps wihtin a workflow are executed*/ 49 | public $sortindex; 50 | 51 | /** 52 | * Creates a subplugin with subpluginname and optional id. 53 | * @param string $instancename name of the subplugin instance 54 | * @param string $subpluginname name of the subplugin 55 | * @param int $workflowid id of the workflow the subplugin belongs to 56 | * @param int $id id of the subplugin 57 | */ 58 | public function __construct($instancename, $subpluginname, $workflowid, $id = null) { 59 | $this->subpluginname = $subpluginname; 60 | $this->instancename = $instancename; 61 | $this->workflowid = $workflowid; 62 | $this->id = $id; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /classes/local/entity/trigger_subplugin.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Trigger subplugin class 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | namespace tool_lifecycle\local\entity; 25 | 26 | /** 27 | * Trigger subplugin class 28 | * 29 | * @package tool_lifecycle 30 | * @copyright 2017 Tobias Reischmann WWU 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | class trigger_subplugin extends subplugin { 34 | 35 | /** 36 | * Creates a subplugin from a db record. 37 | * @param object $record Data object. 38 | * @return trigger_subplugin 39 | */ 40 | public static function from_record($record) { 41 | if (!object_property_exists($record, 'subpluginname')) { 42 | return null; 43 | } 44 | if (!object_property_exists($record, 'instancename')) { 45 | return null; 46 | } 47 | if (!object_property_exists($record, 'workflowid')) { 48 | return null; 49 | } 50 | $id = null; 51 | if (object_property_exists($record, 'id') && !empty($record->id)) { 52 | $id = $record->id; 53 | } 54 | $instance = new self($record->instancename, $record->subpluginname, $record->workflowid, $id); 55 | if (object_property_exists($record, 'sortindex') ) { 56 | $instance->sortindex = $record->sortindex; 57 | } 58 | 59 | return $instance; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /classes/local/form/form_courses_filter.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * A moodle form for filtering the course backups table 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2021 Justus Dieckmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | namespace tool_lifecycle\local\form; 25 | 26 | defined('MOODLE_INTERNAL') || die(); 27 | 28 | require_once($CFG->libdir . '/formslib.php'); 29 | 30 | /** 31 | * A moodle form for filtering the course backups table 32 | * 33 | * @package tool_lifecycle 34 | * @copyright 2021 Justus Dieckmann WWU 35 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 | */ 37 | class form_courses_filter extends \moodleform { 38 | 39 | /** 40 | * Defines forms elements 41 | */ 42 | public function definition() { 43 | $mform = $this->_form; 44 | 45 | $mform->addElement('text', 'courseid', get_string('courseid', 'tool_lifecycle')); 46 | $mform->setType('courseid', PARAM_ALPHANUM); 47 | $mform->addRule('courseid', null, 'numeric', null, 'client'); 48 | 49 | $mform->addElement('text', 'shortname', get_string('shortname')); 50 | $mform->setType('shortname', PARAM_TEXT); 51 | 52 | $mform->addElement('text', 'fullname', get_string('fullname')); 53 | $mform->setType('fullname', PARAM_TEXT); 54 | 55 | // Edited from $this->add_action_buttons to allow custom cancel text. 56 | $buttonarray = []; 57 | $buttonarray[] = &$mform->createElement('submit', 'submitbutton', 58 | get_string('apply', 'tool_lifecycle')); 59 | $buttonarray[] = &$mform->createElement('cancel', 'cancel', get_string('reset')); 60 | $mform->addGroup($buttonarray, 'buttonar', '', [' '], false); 61 | $mform->closeHeaderBefore('buttonar'); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /classes/local/form/form_delete_delays.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Confirmation form for deleting all delays (workflow and global). 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2025 Thomas Niedermaier University Münster 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | namespace tool_lifecycle\local\form; 25 | 26 | use tool_lifecycle\action; 27 | 28 | defined('MOODLE_INTERNAL') || die(); 29 | 30 | require_once($CFG->libdir . '/formslib.php'); 31 | 32 | /** 33 | * Provides a form to confirm the deletion of all delays (workflow and global). 34 | * @package tool_lifecycle 35 | * @copyright 2025 Thomas Niedermaier University Münster 36 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 | */ 38 | class form_delete_delays extends \moodleform { 39 | 40 | /** 41 | * Defines forms elements 42 | */ 43 | public function definition() { 44 | $mform = $this->_form; 45 | 46 | $mform->addElement('header', 'delete_delays_form_header', get_string('delete_all_delays', 'tool_lifecycle')); 47 | 48 | $mform->addElement('static', 'message', get_string('delete_all_delays_confirmation', 'tool_lifecycle')); 49 | 50 | $mform->addElement('hidden', 'action'); // Save the current action. 51 | $mform->setType('action', PARAM_TEXT); 52 | $mform->setDefault('action', action::BULK_DELETE); 53 | 54 | $this->add_action_buttons('true', get_string('proceed', 'tool_lifecycle')); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /classes/local/form/form_upload_workflow.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Offers the possibility to upload a workflow in an xml format. 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | namespace tool_lifecycle\local\form; 25 | 26 | defined('MOODLE_INTERNAL') || die(); 27 | 28 | require_once($CFG->libdir . '/formslib.php'); 29 | 30 | /** 31 | * Provides a form to modify a workflow instance 32 | * @package tool_lifecycle 33 | * @copyright 2017 Tobias Reischmann WWU 34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 | */ 36 | class form_upload_workflow extends \moodleform { 37 | 38 | /** 39 | * Defines forms elements 40 | */ 41 | public function definition() { 42 | $mform = $this->_form; 43 | 44 | $mform->addElement('filepicker', 'backupfile', get_string('upload_workflow', 'tool_lifecycle'), null, 45 | ['accepted_types' => 'xml']); 46 | 47 | $showforce = isset($this->_customdata['showforce']) && $this->_customdata['showforce']; 48 | $mform->addElement($showforce ? 'checkbox' : 'hidden', 'force', get_string('force_import', 'tool_lifecycle')); 49 | $mform->setDefault('force', 0); 50 | $mform->setType('force', PARAM_BOOL); 51 | 52 | $this->add_action_buttons('true', get_string('upload')); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /classes/local/manager/subplugin_manager.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Manager for Subplugins 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | namespace tool_lifecycle\local\manager; 25 | 26 | /** 27 | * Manager for Subplugins 28 | * 29 | * @package tool_lifecycle 30 | * @copyright 2017 Tobias Reischmann WWU 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | abstract class subplugin_manager { 34 | 35 | /** 36 | * Determines if there exists a subplugin for the given name and type 37 | * @param string $subpluginname Name of the subplugin. 38 | * @param string $subplugintype Type of the subplugin. 39 | * @return bool 40 | */ 41 | protected static function is_subplugin($subpluginname, $subplugintype) { 42 | $subplugintypes = \core_component::get_subplugins('tool_lifecycle'); 43 | if (array_key_exists($subplugintype, $subplugintypes)) { 44 | $subplugins = $subplugintypes[$subplugintype]; 45 | if (in_array($subpluginname, $subplugins)) { 46 | return true; 47 | } 48 | } 49 | return false; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /classes/local/response/step_response.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Possible Responses of a Subplugin 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | namespace tool_lifecycle\local\response; 25 | 26 | /** 27 | * Possible Responses of a Subplugin 28 | * 29 | * @package tool_lifecycle 30 | * @copyright 2017 Tobias Reischmann WWU 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | class step_response { 34 | 35 | /** @var string Proceed the workflow to the next step. */ 36 | const PROCEED = 'proceed'; 37 | /** @var string The step is still processing the course and probably waiting for some interaction. */ 38 | const WAITING = 'waiting'; 39 | /** @var string The process should be rolled back. */ 40 | const ROLLBACK = 'rollback'; 41 | 42 | /** @var string Value of the response. */ 43 | private $value; 44 | 45 | /** 46 | * Creates an instance of a SubpluginResponse 47 | * @param string $responsetype code of the response 48 | */ 49 | private function __construct($responsetype) { 50 | $this->value = $responsetype; 51 | } 52 | 53 | /** 54 | * Creates a step_response telling that the subplugin finished processing the course. 55 | */ 56 | public static function proceed() { 57 | return new step_response(self::PROCEED); 58 | } 59 | 60 | /** 61 | * Creates a step_response telling that the subplugin is still processing the course. 62 | */ 63 | public static function waiting() { 64 | return new step_response(self::WAITING); 65 | } 66 | 67 | /** 68 | * Creates a step_response telling that a rollback for the process of this course is necessary. 69 | */ 70 | public static function rollback() { 71 | return new step_response(self::ROLLBACK); 72 | } 73 | 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /classes/plugininfo/lifecyclestep.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Pluginfo for life cycle step 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | namespace tool_lifecycle\plugininfo; 25 | 26 | use core\plugininfo\base; 27 | use tool_lifecycle\local\manager\step_manager; 28 | use tool_lifecycle\local\manager\workflow_manager; 29 | 30 | /** 31 | * Pluginfo for life cycle step 32 | * 33 | * @package tool_lifecycle 34 | * @copyright 2017 Tobias Reischmann WWU 35 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 | */ 37 | class lifecyclestep extends base { 38 | 39 | /** 40 | * Should there be a way to uninstall the plugin via the administration UI. 41 | * 42 | * By default uninstallation is not allowed, plugin developers must enable it explicitly! 43 | * 44 | * @return bool 45 | */ 46 | public function is_uninstall_allowed() { 47 | if ($this->is_standard()) { 48 | return false; 49 | } 50 | // Only allow uninstall, if no active workflow with step instances of this type is present. 51 | $steps = step_manager::get_step_instances_by_subpluginname($this->name); 52 | foreach ($steps as $step) { 53 | if (workflow_manager::is_active($step->workflowid)) { 54 | return false; 55 | } 56 | } 57 | return true; 58 | } 59 | 60 | /** 61 | * Remove the plugin. 62 | * @param \progress_trace $progress 63 | * @return bool 64 | */ 65 | public function uninstall(\progress_trace $progress) { 66 | step_manager::remove_all_instances($this->name); 67 | return true; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /classes/settings_type.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Defines available settings_types. 19 | * @package tool_lifecycle 20 | * @copyright 2017 Tobias Reischmann WWU 21 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 | */ 23 | namespace tool_lifecycle; 24 | 25 | /** 26 | * Defines available settings_types. 27 | * @package tool_lifecycle 28 | * @copyright 2017 Tobias Reischmann WWU 29 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 30 | */ 31 | class settings_type { 32 | 33 | /** @var string Represents the type for a step subplugin. */ 34 | const STEP = 'step'; 35 | /** @var string Represents the type for a trigger subplugin. */ 36 | const TRIGGER = 'trigger'; 37 | } 38 | -------------------------------------------------------------------------------- /classes/task/lifecycle_cleanup_task.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Scheduled task for cleanup past delays 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2019 Justus Dieckmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | namespace tool_lifecycle\task; 25 | 26 | /** 27 | * Scheduled task for cleanup past delays 28 | * 29 | * @package tool_lifecycle 30 | * @copyright 2019 Justus Dieckmann WWU 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | class lifecycle_cleanup_task extends \core\task\scheduled_task { 34 | 35 | /** 36 | * Get a descriptive name for this task (shown to admins). 37 | * 38 | * @return string 39 | * @throws \coding_exception 40 | */ 41 | public function get_name() { 42 | return get_string('lifecycle_cleanup_task', 'tool_lifecycle'); 43 | } 44 | 45 | /** 46 | * Do the job. 47 | */ 48 | public function execute() { 49 | global $DB; 50 | $twomonthago = time() - 60 * 24 * 60 * 60; 51 | $oneyearago = time() - 365 * 24 * 60 * 60; 52 | $DB->delete_records_select('tool_lifecycle_delayed', 'delayeduntil <= :time', ['time' => $twomonthago]); 53 | $DB->delete_records_select('tool_lifecycle_delayed_workf', 'delayeduntil <= :time', ['time' => $twomonthago]); 54 | $DB->delete_records_select('lifecyclestep_email_notified', 'timemailsent <= :time', ['time' => $oneyearago]); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /classes/task/lifecycle_error_notify_task.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Scheduled task for notify admin upon process errors 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2022 Justus Dieckmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | namespace tool_lifecycle\task; 25 | 26 | /** 27 | * Scheduled task for notify admin upon process errors 28 | * 29 | * @package tool_lifecycle 30 | * @copyright 2022 Justus Dieckmann WWU 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | class lifecycle_error_notify_task extends \core\task\scheduled_task { 34 | 35 | /** 36 | * Get a descriptive name for this task (shown to admins). 37 | * 38 | * @return string 39 | * @throws \coding_exception 40 | */ 41 | public function get_name() { 42 | return get_string('lifecycle_error_notify_task', 'tool_lifecycle'); 43 | } 44 | 45 | /** 46 | * Do the job. 47 | */ 48 | public function execute() { 49 | global $DB, $CFG; 50 | 51 | $lastrun = get_config('tool_lifecycle', 'adminerrornotifylastrun'); 52 | if (!$lastrun) { 53 | $lastrun = 0; 54 | } 55 | 56 | $currenttime = time(); 57 | 58 | $errorcount = $DB->count_records_select('tool_lifecycle_proc_error', 'errortimecreated > :lastrun', 59 | ['lastrun' => $lastrun]); 60 | 61 | set_config('adminerrornotifylastrun', $currenttime, 'tool_lifecycle'); 62 | 63 | if (!$errorcount) { 64 | return; 65 | } 66 | 67 | $obj = new \stdClass(); 68 | $obj->amount = $errorcount; 69 | $obj->url = $CFG->wwwroot . '/admin/tool/lifecycle/errors.php'; 70 | 71 | email_to_user(get_admin(), \core_user::get_noreply_user(), 72 | get_string('notifyerrorsemailsubject', 'tool_lifecycle', $obj), 73 | get_string('notifyerrorsemailcontent', 'tool_lifecycle', $obj), 74 | get_string('notifyerrorsemailcontenthtml', 'tool_lifecycle', $obj) 75 | ); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /classes/task/lifecycle_task.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Scheduled task for working on lifecycle processes 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | namespace tool_lifecycle\task; 25 | 26 | use tool_lifecycle\local\manager\lib_manager; 27 | use tool_lifecycle\local\manager\step_manager; 28 | use tool_lifecycle\processor; 29 | 30 | /** 31 | * Scheduled task for working on lifecycle processes 32 | * 33 | * @package tool_lifecycle 34 | * @copyright 2017 Tobias Reischmann WWU 35 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 | */ 37 | class lifecycle_task extends \core\task\scheduled_task { 38 | 39 | /** 40 | * Get a descriptive name for this task (shown to admins). 41 | * 42 | * @return string 43 | * @throws \coding_exception 44 | */ 45 | public function get_name() { 46 | return get_string('lifecycle_task', 'tool_lifecycle'); 47 | } 48 | 49 | /** 50 | * Do the job. 51 | */ 52 | public function execute() { 53 | $processor = new processor(); 54 | $processor->call_trigger(); 55 | 56 | $steps = step_manager::get_step_types(); 57 | /* @var \tool_lifecycle\step\libbase[] $steplibs stores the lib classes of all step subplugins.*/ 58 | $steplibs = []; 59 | foreach ($steps as $id => $step) { 60 | $steplibs[$id] = lib_manager::get_step_lib($id); 61 | $steplibs[$id]->pre_processing_bulk_operation(); 62 | } 63 | $processor->process_courses(); 64 | foreach ($steps as $id => $step) { 65 | $steplibs[$id]->post_processing_bulk_operation(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /confirmation.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Provides a confirmation form. 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2025 Thomas Niedermaier University Münster 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | use tool_lifecycle\local\form\form_delete_delays; 26 | use tool_lifecycle\tabs; 27 | use tool_lifecycle\urls; 28 | 29 | require_once(__DIR__ . '/../../../config.php'); 30 | 31 | require_login(); 32 | 33 | $syscontext = context_system::instance(); 34 | $PAGE->set_url(new \moodle_url(urls::CONFIRMATION)); 35 | $PAGE->set_context($syscontext); 36 | 37 | $PAGE->set_pagetype('admin-setting-' . 'tool_lifecycle'); 38 | $PAGE->set_pagelayout('admin'); 39 | 40 | $renderer = $PAGE->get_renderer('tool_lifecycle'); 41 | 42 | $heading = get_string('pluginname', 'tool_lifecycle')." / ".get_string('delayed_courses_header', 'tool_lifecycle'); 43 | 44 | $formurl = new \moodle_url(urls::CONFIRMATION, ['sesskey' => sesskey()]); 45 | $mform = new form_delete_delays($formurl); 46 | 47 | if ($mform->is_cancelled()) { 48 | redirect(new \moodle_url(urls::DELAYED_COURSES)); 49 | } else if ($data = $mform->get_data()) { 50 | $url = new moodle_url(urls::DELAYED_COURSES, ['action' => $data->action, 'sesskey' => sesskey()]); 51 | redirect($url); 52 | } else { 53 | echo $renderer->header($heading); 54 | $tabrow = tabs::get_tabrow(); 55 | $renderer->tabs($tabrow, 'delayedcourses'); 56 | 57 | $mform->display(); 58 | 59 | echo $renderer->footer(); 60 | } 61 | 62 | -------------------------------------------------------------------------------- /coursebackups.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Display the list of all course backups 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2025 Thomas Niedermaier University Münster 22 | * @copyright 2017 Tobias Reischmann WWU 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | use tool_lifecycle\local\form\form_courses_filter; 27 | use tool_lifecycle\tabs; 28 | use tool_lifecycle\urls; 29 | 30 | require_once(__DIR__ . '/../../../config.php'); 31 | require_once($CFG->libdir . '/adminlib.php'); 32 | 33 | require_login(); 34 | 35 | $syscontext = context_system::instance(); 36 | $PAGE->set_url(new \moodle_url(urls::COURSE_BACKUPS)); 37 | $PAGE->set_context($syscontext); 38 | 39 | $mform = new form_courses_filter(); 40 | 41 | // Cache handling. 42 | $cache = cache::make('tool_lifecycle', 'mformdata'); 43 | if ($mform->is_cancelled()) { 44 | $cache->delete('coursebackups_filter'); 45 | redirect($PAGE->url); 46 | } else if ($data = $mform->get_data()) { 47 | $cache->set('coursebackups_filter', $data); 48 | } else { 49 | $data = $cache->get('coursebackups_filter'); 50 | if ($data) { 51 | $mform->set_data($data); 52 | } 53 | } 54 | 55 | $table = new tool_lifecycle\local\table\course_backups_table('tool_lifecycle_course_backups', $data); 56 | 57 | $PAGE->set_pagetype('admin-setting-' . 'tool_lifecycle'); 58 | $PAGE->set_pagelayout('admin'); 59 | 60 | $renderer = $PAGE->get_renderer('tool_lifecycle'); 61 | 62 | $heading = get_string('pluginname', 'tool_lifecycle')." / ".get_string('course_backups_list_header', 'tool_lifecycle'); 63 | echo $renderer->header($heading); 64 | $tabrow = tabs::get_tabrow(); 65 | $id = optional_param('id', 'settings', PARAM_TEXT); 66 | $renderer->tabs($tabrow, $id); 67 | 68 | echo '
'; 69 | 70 | $mform->display(); 71 | 72 | echo '
'; 73 | 74 | $table->out(50, false); 75 | echo $renderer->footer(); 76 | 77 | 78 | -------------------------------------------------------------------------------- /db/access.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Capability definitions for the tool_lifecycle plugin 19 | * @package tool_lifecycle 20 | * @copyright 2018 Tamara Gunkel, Jan Dageförde (WWU) 21 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 | */ 23 | defined('MOODLE_INTERNAL') || die(); 24 | 25 | $capabilities = [ 26 | 27 | 'tool/lifecycle:managecourses' => [ 28 | 'contextlevel' => CONTEXT_COURSE, 29 | 'captype' => 'write', 30 | 'archetypes' => [ 31 | 'manager' => CAP_PREVENT, 32 | 'editingteacher' => CAP_ALLOW, 33 | 'teacher' => CAP_PREVENT, 34 | 'students' => CAP_PREVENT, 35 | ], 36 | 'clonepermissionsfrom' => 'moodle/course:update', 37 | ], 38 | ]; 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /db/caches.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Cache Definition for tool_lifecycle 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2019 Justus Dieckmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | $definitions = [ 28 | 'mformdata' => [ 29 | 'mode' => cache_store::MODE_SESSION, 30 | ], 31 | 'application' => [ 32 | 'mode' => cache_store::MODE_APPLICATION, 33 | 'simplekeys' => true, 34 | 'simpledata' => true, 35 | ], 36 | ]; 37 | -------------------------------------------------------------------------------- /db/events.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Event observer. 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2020 Justus Dieckmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | $observers = [ 28 | [ 29 | 'eventname' => 'core\event\course_deleted', 30 | 'callback' => 'tool_lifecycle\local\manager\process_manager::course_deletion_observed', 31 | ], 32 | ]; 33 | -------------------------------------------------------------------------------- /db/subplugins.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugintypes" : { 3 | "lifecycletrigger" : "admin\/tool\/lifecycle\/trigger", 4 | "lifecyclestep" : "admin\/tool\/lifecycle\/step" 5 | } 6 | } -------------------------------------------------------------------------------- /db/subplugins.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Definition of subplugins 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | defined('MOODLE_INTERNAL') || die(); 25 | 26 | $subplugins = json_decode(file_get_contents(__DIR__ . '/subplugins.json'), true)["plugintypes"]; 27 | -------------------------------------------------------------------------------- /db/tasks.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Definition of life cycle scheduled tasks. 19 | * 20 | * @package tool_lifecycle 21 | * @category task 22 | * @copyright 2017 Tobias Reischmann WWU 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | defined('MOODLE_INTERNAL') || die(); 27 | 28 | $tasks = [ 29 | [ 30 | 'classname' => 'tool_lifecycle\task\lifecycle_task', 31 | 'blocking' => 0, 32 | 'minute' => '*', 33 | 'hour' => '*', 34 | 'day' => '*', 35 | 'month' => '*', 36 | 'dayofweek' => '*', 37 | 'faildelay' => 1, 38 | ], 39 | [ 40 | 'classname' => 'tool_lifecycle\task\lifecycle_cleanup_task', 41 | 'blocking' => 0, 42 | 'minute' => '0', 43 | 'hour' => '4', 44 | 'day' => '*', 45 | 'month' => '*', 46 | 'dayofweek' => '0', 47 | ], 48 | [ 49 | 'classname' => 'tool_lifecycle\task\lifecycle_error_notify_task', 50 | 'blocking' => 0, 51 | 'minute' => 'R', 52 | 'hour' => '5', 53 | 'day' => '*', 54 | 'month' => '*', 55 | 'dayofweek' => '0', 56 | ], 57 | ]; 58 | -------------------------------------------------------------------------------- /deactivatedworkflows.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Displays all deactivated workflows 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2025 Thomas Niedermaier University Münster 22 | * @copyright 2018 Yorick Reum, JMU 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | require_once(__DIR__ . '/../../../config.php'); 27 | require_once($CFG->libdir . '/adminlib.php'); 28 | 29 | use tool_lifecycle\local\manager\workflow_manager; 30 | use tool_lifecycle\local\table\deactivated_workflows_table; 31 | use tool_lifecycle\tabs; 32 | use tool_lifecycle\urls; 33 | 34 | require_login(); 35 | 36 | $syscontext = context_system::instance(); 37 | $PAGE->set_url(new \moodle_url(urls::DEACTIVATED_WORKFLOWS)); 38 | $PAGE->set_context($syscontext); 39 | 40 | $workflowid = optional_param('workflowid', null, PARAM_INT); 41 | $action = optional_param('action', null, PARAM_TEXT); 42 | if ($workflowid && $action) { 43 | workflow_manager::handle_action($action, $workflowid); 44 | } 45 | 46 | $table = new deactivated_workflows_table('tool_lifecycle_deactivated_workflows'); 47 | 48 | $PAGE->set_pagetype('admin-setting-' . 'tool_lifecycle'); 49 | $PAGE->set_pagelayout('admin'); 50 | 51 | $renderer = $PAGE->get_renderer('tool_lifecycle'); 52 | 53 | $heading = get_string('pluginname', 'tool_lifecycle')." / ".get_string('deactivated_workflows_header', 'tool_lifecycle'); 54 | echo $renderer->header($heading); 55 | $tabrow = tabs::get_tabrow(); 56 | $id = optional_param('id', 'settings', PARAM_TEXT); 57 | $renderer->tabs($tabrow, $id); 58 | 59 | echo $OUTPUT->box_start("lifecycle-enable-overflow lifecycle-table"); 60 | 61 | $table->out(50, false); 62 | 63 | echo $OUTPUT->box_end(); 64 | 65 | echo $renderer->footer(); 66 | -------------------------------------------------------------------------------- /downloadbackup.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Provides download for backup 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2025 Thomas Niedermaier University Münster 22 | * @copyright 2019 Justus Dieckmann WWU 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | require_once(__DIR__ . '/../../../config.php'); 27 | 28 | require_login(); 29 | require_capability('moodle/site:config', context_system::instance()); 30 | 31 | $backupid = required_param('backupid', PARAM_INT); 32 | 33 | $backuprecord = $DB->get_record('tool_lifecycle_backups', ['id' => $backupid], 'backupfile', MUST_EXIST); 34 | $source = get_config('tool_lifecycle', 'backup_path') . DIRECTORY_SEPARATOR . $backuprecord->backupfile; 35 | 36 | if (!file_exists($source)) { 37 | throw new \moodle_exception('errorbackupfiledoesnotexist', 'tool_lifecycle', $source); 38 | } 39 | 40 | header("Content-Type: application/zip"); 41 | header("Content-Disposition: attachment; filename=\"backup-$backuprecord->backupfile\""); 42 | readfile($source); 43 | -------------------------------------------------------------------------------- /errors.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Displays the process errors 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2025 Thomas Niedermaier University Münster 22 | * @copyright 2021 Justus Dieckmann WWU 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | use tool_lifecycle\local\manager\process_manager; 27 | use tool_lifecycle\local\table\process_errors_table; 28 | use tool_lifecycle\tabs; 29 | use tool_lifecycle\urls; 30 | 31 | require_once(__DIR__ . '/../../../config.php'); 32 | require_once($CFG->libdir . '/adminlib.php'); 33 | 34 | require_login(); 35 | 36 | $syscontext = context_system::instance(); 37 | $PAGE->set_url(new \moodle_url(urls::PROCESS_ERRORS)); 38 | $PAGE->set_context($syscontext); 39 | 40 | // Action handling (delete, bulk-delete). 41 | $action = optional_param('action', null, PARAM_ALPHANUMEXT); 42 | if ($action) { 43 | global $DB; 44 | require_sesskey(); 45 | $ids = required_param_array('id', PARAM_INT); 46 | if ($action == 'proceed') { 47 | foreach ($ids as $id) { 48 | process_manager::proceed_process_after_error($id); 49 | } 50 | } else if ($action == 'rollback') { 51 | foreach ($ids as $id) { 52 | process_manager::rollback_process_after_error($id); 53 | } 54 | } else { 55 | throw new coding_exception("action must be either 'proceed' or 'rollback'"); 56 | } 57 | redirect($PAGE->url); 58 | } 59 | 60 | $PAGE->set_pagetype('admin-setting-' . 'tool_lifecycle'); 61 | $PAGE->set_pagelayout('admin'); 62 | 63 | $renderer = $PAGE->get_renderer('tool_lifecycle'); 64 | 65 | $heading = get_string('pluginname', 'tool_lifecycle')." / ".get_string('process_errors_header', 'tool_lifecycle'); 66 | echo $renderer->header($heading); 67 | $tabrow = tabs::get_tabrow(); 68 | $id = optional_param('id', 'settings', PARAM_TEXT); 69 | $renderer->tabs($tabrow, $id); 70 | 71 | $table = new process_errors_table(); 72 | $table->define_baseurl($PAGE->url); 73 | 74 | $PAGE->requires->js_call_amd('tool_lifecycle/tablebulkactions', 'init'); 75 | 76 | $table->out(100, false); 77 | 78 | echo $OUTPUT->footer(); 79 | -------------------------------------------------------------------------------- /pix/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /pix/t/disable.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /renderer.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Renderer for life cycle 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2025 Thomas Niedermaier University Münster 22 | * @copyright 2017 Tobias Reischmann WWU 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | /** 27 | * Renderer for life cycle 28 | * 29 | * @package tool_lifecycle 30 | * @copyright 2025 Thomas Niedermaier University Münster 31 | * @copyright 2017 Tobias Reischmann WWU 32 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 | */ 34 | class tool_lifecycle_renderer extends plugin_renderer_base { 35 | 36 | /** 37 | * Write the page footer 38 | */ 39 | public function footer() { 40 | echo $this->output->footer(); 41 | } 42 | 43 | /** 44 | * Write the page header 45 | * 46 | * @param string $title optional page title. 47 | * @throws \core\exception\coding_exception 48 | */ 49 | public function header($title = null) { 50 | echo $this->output->header(); 51 | if ($title) { 52 | echo $this->output->heading($title); 53 | } 54 | } 55 | 56 | /** 57 | * Write the tab row in page 58 | * 59 | * @param array $tabs the tabs 60 | * @param string $id ID of current page (can be empty) 61 | */ 62 | public function tabs($tabs, $id) { 63 | echo $this->output->tabtree($tabs, $id); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /restore.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Display the list of courses relevant for a specific user in a specific step instance. 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2025 Thomas Niedermaier University Münster 22 | * @copyright 2017 Tobias Reischmann WWU 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | require_once(__DIR__ . '/../../../config.php'); 27 | 28 | use tool_lifecycle\local\manager\backup_manager; 29 | 30 | $PAGE->set_context(context_system::instance()); 31 | require_login(null, false); 32 | require_capability('moodle/site:config', context_system::instance()); 33 | 34 | $backupid = required_param('backupid', PARAM_INT); 35 | 36 | backup_manager::restore_course_backup($backupid); 37 | -------------------------------------------------------------------------------- /step/adminapprove/README.md: -------------------------------------------------------------------------------- 1 | # Adminapprove (moodle-lifecyclestep_adminapprove) 2 | 3 | This is a step for [Life Cycle](https://github.com/learnweb/moodle-tool_lifecycle), in which admins can manually decide for every course, whether the course should proceed or roll back. 4 | 5 | This is meant as a safeguard, so that admins can check whether their workflows are working correctly. 6 | 7 | ![Adminapprove table](https://raw.githubusercontent.com/justusdieckmann/images/master/lifecyclestep_adminapprove.png); 8 | 9 | ## Behaviour 10 | Each cron-job, all courses that are processed in a adminapprove step get added to the corresponding step table and the admin is notified. 11 | 12 | If the admin marks courses to be proceeded / rolled back, they are removed from the step table and they are proceeded / rolled back during the next cron job. -------------------------------------------------------------------------------- /step/adminapprove/amd/build/init.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Life Cycle Admin Approve Step AMD Module 3 | * 4 | * @module lifecyclestep_adminapprove/init 5 | * @copyright 2019 Justus Dieckmann WWU 6 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 7 | */ 8 | define("lifecyclestep_adminapprove/init",["jquery"],(function($){return{init:function(sesskey,url){$('input[name="checkall"]').click((function(){$('input[name="c[]"]').prop("checked",$('input[name="checkall"]').prop("checked"))})),$(".adminapprove-action").each((function(){$(this).click((function(){var post={act:$(this).attr("data-action"),"c[]":$(this).attr("data-content"),sesskey:sesskey},form=document.createElement("form");for(var k in form.hidden=!0,form.method="post",form.action=url,post){var input=document.createElement("input");input.type="hidden",input.name=k,input.value=post[k],form.append(input)}document.body.append(form),form.submit()}))}))}}})); 9 | 10 | //# sourceMappingURL=init.min.js.map -------------------------------------------------------------------------------- /step/adminapprove/amd/build/link-steps.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Life Cycle Admin Approve Step AMD Module 3 | * 4 | * @module lifecyclestep_adminapprove/link-steps 5 | * @copyright 2019 Justus Dieckmann WWU 6 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 7 | */ 8 | define("lifecyclestep_adminapprove/link-steps",["jquery"],(function($){return{init:function(){$("#adminapprove-steptable tbody tr").each((function(){""==$(this).prop("class")&&($(this).css("cursor","pointer"),$(this).click((function(){var id=$(this).find("[data-stepid]").attr("data-stepid");location.href="approvestep.php?stepid="+id})))}))}}})); 9 | 10 | //# sourceMappingURL=link-steps.min.js.map -------------------------------------------------------------------------------- /step/adminapprove/amd/build/link-steps.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"link-steps.min.js","sources":["../src/link-steps.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Life Cycle Admin Approve Step AMD Module\n *\n * @module lifecyclestep_adminapprove/link-steps\n * @copyright 2019 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery'], function($) {\n return {\n init: function() {\n $('#adminapprove-steptable tbody tr').each(function() {\n if ($(this).prop('class') == '') {\n $(this).css('cursor', 'pointer');\n $(this).click(function () {\n var id = $(this).find(\"[data-stepid]\").attr('data-stepid');\n location.href = 'approvestep.php?stepid=' + id;\n });\n }\n });\n }\n };\n});"],"names":["define","$","init","each","this","prop","css","click","id","find","attr","location","href"],"mappings":";;;;;;;AAsBAA,+CAAO,CAAC,WAAW,SAASC,SACjB,CACHC,KAAM,WACFD,EAAE,oCAAoCE,MAAK,WACV,IAAzBF,EAAEG,MAAMC,KAAK,WACbJ,EAAEG,MAAME,IAAI,SAAU,WACtBL,EAAEG,MAAMG,OAAM,eACNC,GAAKP,EAAEG,MAAMK,KAAK,iBAAiBC,KAAK,eAC5CC,SAASC,KAAO,0BAA4BJ"} -------------------------------------------------------------------------------- /step/adminapprove/amd/src/init.js: -------------------------------------------------------------------------------- 1 | // This file is part of Moodle - http://moodle.org/ 2 | // 3 | // Moodle is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // Moodle is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with Moodle. If not, see . 15 | 16 | /** 17 | * Life Cycle Admin Approve Step AMD Module 18 | * 19 | * @module lifecyclestep_adminapprove/init 20 | * @copyright 2019 Justus Dieckmann WWU 21 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 | */ 23 | define(['jquery'], function($) { 24 | return { 25 | init: function(sesskey, url) { 26 | $('input[name="checkall"]').click(function() { 27 | $('input[name="c[]"]').prop('checked', $('input[name="checkall"]').prop('checked')); 28 | }); 29 | 30 | $('.adminapprove-action').each(function() { 31 | $(this).click(function() { 32 | var post = { 33 | 'act': $(this).attr('data-action'), 34 | 'c[]': $(this).attr('data-content'), 35 | 'sesskey': sesskey 36 | }; 37 | var form = document.createElement('form'); 38 | form.hidden = true; 39 | form.method = 'post'; 40 | form.action = url; 41 | for (var k in post) { 42 | var input = document.createElement('input'); 43 | input.type = 'hidden'; 44 | input.name = k; 45 | input.value = post[k]; 46 | form.append(input); 47 | } 48 | document.body.append(form); 49 | form.submit(); 50 | }); 51 | }); 52 | } 53 | }; 54 | }); -------------------------------------------------------------------------------- /step/adminapprove/amd/src/link-steps.js: -------------------------------------------------------------------------------- 1 | // This file is part of Moodle - http://moodle.org/ 2 | // 3 | // Moodle is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // Moodle is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with Moodle. If not, see . 15 | 16 | /** 17 | * Life Cycle Admin Approve Step AMD Module 18 | * 19 | * @module lifecyclestep_adminapprove/link-steps 20 | * @copyright 2019 Justus Dieckmann WWU 21 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 | */ 23 | define(['jquery'], function($) { 24 | return { 25 | init: function() { 26 | $('#adminapprove-steptable tbody tr').each(function() { 27 | if ($(this).prop('class') == '') { 28 | $(this).css('cursor', 'pointer'); 29 | $(this).click(function () { 30 | var id = $(this).find("[data-stepid]").attr('data-stepid'); 31 | location.href = 'approvestep.php?stepid=' + id; 32 | }); 33 | } 34 | }); 35 | } 36 | }; 37 | }); -------------------------------------------------------------------------------- /step/adminapprove/classes/course_filter_form.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Admin Approve Step 19 | * 20 | * @package lifecyclestep_adminapprove 21 | * @copyright 2019 Justus Dieckmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace lifecyclestep_adminapprove; 26 | 27 | defined('MOODLE_INTERNAL') || die(); 28 | 29 | global $CFG; 30 | require_once($CFG->libdir . '/formslib.php'); 31 | 32 | /** 33 | * A Form to filter courses. 34 | */ 35 | class course_filter_form extends \moodleform { 36 | 37 | /** 38 | * All Elements of the form. 39 | * @return void 40 | * @throws \coding_exception 41 | */ 42 | protected function definition() { 43 | global $CFG; 44 | $mform = $this->_form; 45 | $mform->addElement('text', 'courseid', get_string('courseid', 'lifecyclestep_adminapprove')); 46 | $mform->setType('courseid', PARAM_ALPHANUM); 47 | $mform->addRule('courseid', get_string('only_number', 'lifecyclestep_adminapprove'), 'numeric', null, 'client'); 48 | 49 | $mform->addElement('text', 'coursename', get_string('course')); 50 | $mform->setType('coursename', PARAM_NOTAGS); 51 | 52 | $categories = \core_course_category::get_all(); 53 | 54 | $categoryoptions = ['' => '-']; 55 | foreach ($categories as $category) { 56 | $categoryoptions[$category->id] = $category->name; 57 | } 58 | $mform->addElement('select', 'category', get_string('category'), $categoryoptions); 59 | 60 | $buttonarray = [ 61 | $mform->createElement('submit', 'submitbutton', get_string('filter')), 62 | $mform->createElement('cancel'), 63 | ]; 64 | $mform->addGroup($buttonarray, 'buttonar', '', [' '], false); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /step/adminapprove/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace lifecyclestep_adminapprove\privacy; 18 | 19 | use core_privacy\local\metadata\null_provider; 20 | 21 | /** 22 | * Privacy subsystem implementation for lifecyclestep_adminapprove. 23 | * 24 | * @package lifecyclestep_adminapprove 25 | * @copyright 2022 ISB Bayern 26 | * @author Philipp Memmel 27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 | */ 29 | class provider implements null_provider { 30 | 31 | /** 32 | * Get the language string identifier with the component's language 33 | * file to explain why this plugin stores no data. 34 | * 35 | * @return string the reason 36 | */ 37 | public static function get_reason(): string { 38 | return 'privacy:metadata'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /step/adminapprove/db/caches.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Cache Definition for Admin Approve Step 19 | * 20 | * @package lifecyclestep_adminapprove 21 | * @copyright 2019 Justus Dieckmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | $definitions = [ 28 | 'mformdata' => [ 29 | 'mode' => cache_store::MODE_SESSION, 30 | ], 31 | ]; 32 | -------------------------------------------------------------------------------- /step/adminapprove/db/install.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
-------------------------------------------------------------------------------- /step/adminapprove/db/upgrade.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Update script for lifecyclestep_adminapprove plugin 19 | * 20 | * @package lifecyclestep_adminapprove 21 | * @copyright 2025 Thomas Niedermaier University of Münster 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | /** 26 | * Update script for lifecyclestep_adminapprove. 27 | * @param int $oldversion Version id of the previously installed version. 28 | * @return bool 29 | * @throws ddl_exception 30 | * @throws ddl_field_missing_exception 31 | * @throws ddl_table_missing_exception 32 | * @throws dml_exception 33 | * @throws downgrade_exception 34 | * @throws upgrade_exception 35 | */ 36 | function xmldb_lifecyclestep_adminapprove_upgrade($oldversion) { 37 | 38 | global $DB; 39 | $dbman = $DB->get_manager(); 40 | if ($oldversion < 2025050400) { 41 | 42 | // Define table lifecyclestep_adminapprove to be created. 43 | $table = new xmldb_table('lifecyclestep_adminapprove'); 44 | 45 | // Adding fields to table lifecyclestep_adminapprove. 46 | $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 47 | $table->add_field('processid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 48 | $table->add_field('status', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0'); 49 | 50 | // Adding keys to table lifecyclestep_adminapprove. 51 | $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 52 | $table->add_key('processid_fk-u', XMLDB_KEY_FOREIGN_UNIQUE, ['processid'], 'tool_lifecycle_process', ['id']); 53 | 54 | // Conditionally launch create table for lifecyclestep_adminapprove. 55 | if (!$dbman->table_exists($table)) { 56 | $dbman->create_table($table); 57 | } 58 | 59 | // Adminapprove savepoint reached. 60 | upgrade_plugin_savepoint(true, 2025050400, 'lifecyclestep', 'adminapprove'); 61 | } 62 | return true; 63 | } 64 | -------------------------------------------------------------------------------- /step/adminapprove/index.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Admin Approve Step 19 | * 20 | * @package lifecyclestep_adminapprove 21 | * @copyright 2019 Justus Dieckmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | use tool_lifecycle\tabs; 26 | 27 | require_once(__DIR__ . '/../../../../../config.php'); 28 | require_once($CFG->libdir . '/adminlib.php'); 29 | 30 | require_login(); 31 | 32 | $PAGE->set_context(context_system::instance()); 33 | $PAGE->set_url(new \moodle_url("/admin/tool/lifecycle/step/adminapprove/index.php")); 34 | 35 | $PAGE->set_pagetype('admin-setting-' . 'tool_lifecycle'); 36 | $PAGE->set_pagelayout('admin'); 37 | 38 | $renderer = $PAGE->get_renderer('tool_lifecycle'); 39 | 40 | $heading = get_string('pluginname', 'tool_lifecycle')." / ".get_string('pluginname', 41 | 'lifecyclestep_adminapprove'); 42 | echo $renderer->header($heading); 43 | $tabrow = tabs::get_tabrow(); 44 | $renderer->tabs($tabrow, optional_param('id', '', PARAM_TEXT)); 45 | 46 | $table = new lifecyclestep_adminapprove\step_table(); 47 | $table->out(100, false); 48 | 49 | $PAGE->requires->js_call_amd('lifecyclestep_adminapprove/link-steps', 'init'); 50 | 51 | echo $OUTPUT->footer(); 52 | 53 | -------------------------------------------------------------------------------- /step/adminapprove/tests/behat/behat_lifecyclestep_adminapprove.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Step definition for life cycle step adminapprove. 19 | * 20 | * @package lifecyclestep_adminapprove 21 | * @category test 22 | * @copyright 2025 Thomas Niedermaier University Münster 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | require_once(__DIR__ . '/../../../../../../../lib/behat/behat_base.php'); 27 | 28 | /** 29 | * Step definition for life cycle. 30 | * 31 | * @package lifecyclestep_adminapprove 32 | * @category test 33 | * @copyright 2025 Thomas Niedermaier University Münster 34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 | */ 36 | class behat_lifecyclestep_adminapprove extends behat_base { 37 | /** 38 | * Opens Admin Approvals page. 39 | * 40 | * @Given /^I am on adminapprove page$/ 41 | */ 42 | public function i_am_on_adminapprove_page() { 43 | $this->getSession()->visit($this->locate_path('/admin/tool/lifecycle/step/adminapprove/index.php')); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /step/adminapprove/tests/behat/proceedtest.feature: -------------------------------------------------------------------------------- 1 | @tool @tool_lifecycle @lifecyclestep @lifecyclestep_adminapprove @javascript 2 | Feature: Add a workflow with an adminapprove step and test it 3 | 4 | Background: 5 | Given the following "courses" exist: 6 | | fullname | shortname | 7 | | Course 1 | C1 | 8 | | Course 2 | C2 | 9 | | Course 3 | C3 | 10 | | Course 4 | C4 | 11 | And I log in as "admin" 12 | And I navigate to "Plugins > Admin tools > Life Cycle" in site administration 13 | And I am on workflowdrafts page 14 | And I click on "Create new workflow" "link" 15 | And I set the following fields to these values: 16 | | Title | Admin Approve Step WF #1 | 17 | | Displayed workflow title | Admin Approve Step WF #1 | 18 | And I press "Save changes" 19 | And I select "Start date delay trigger" from the "tool_lifecycle-choose-trigger" singleselect 20 | And I set the following fields to these values: 21 | | Instance name | My Trigger | 22 | | delay[number] | 0 | 23 | | delay[timeunit] | seconds | 24 | And I press "Save changes" 25 | And I select "Admin approve step" from the "tool_lifecycle-choose-step" singleselect 26 | And I set the following fields to these values: 27 | | Instance name | Admin Approve Step #1 | 28 | | Status message | My status | 29 | And I press "Save changes" 30 | And I select "Delete course step" from the "tool_lifecycle-choose-step" singleselect 31 | And I set the field "Instance name" to "Delete Course #1" 32 | And I press "Save changes" 33 | And I am on workflowdrafts page 34 | And I press "Activate" 35 | 36 | Scenario: Test interaction of admin approve step 37 | When I am on adminapprove page 38 | Then I should see "There are currently no courses waiting for interaction in any Admin Approve step." 39 | When I run the scheduled task "tool_lifecycle\task\lifecycle_task" 40 | And I reload the page 41 | And I click on "Admin Approve Step #1" "link" 42 | Then I should see "Course 1" 43 | And I should see "Course 2" 44 | And I should see "Course 3" 45 | And I should see "Course 4" 46 | When I click on the tool "Proceed" in the "Course 1" row of the "lifecyclestep_adminapprove-decisiontable" table 47 | And I wait to be redirected 48 | Then I should not see "Course 1" 49 | When I click on the tool "Rollback" in the "Course 2" row of the "lifecyclestep_adminapprove-decisiontable" table 50 | And I wait to be redirected 51 | Then I should not see "Course 2" 52 | -------------------------------------------------------------------------------- /step/adminapprove/tests/behat/teacherview.feature: -------------------------------------------------------------------------------- 1 | @tool @tool_lifecycle @lifecyclestep @lifecyclestep_adminapprove @javascript 2 | Feature: Add a workflow with an adminapprove step and test the status in the teachers view. 3 | 4 | Background: 5 | Given the following "courses" exist: 6 | | fullname | shortname | 7 | | Course 1 | C1 | 8 | And the following "users" exist: 9 | | username | firstname | lastname | email | 10 | | teacher | Terry1 | Teacher1 | teacher1@example.com | 11 | And the following "course enrolments" exist: 12 | | user | course | role | 13 | | teacher | C1 | editingteacher | 14 | And I log in as "admin" 15 | And I navigate to "Plugins > Admin tools > Life Cycle" in site administration 16 | And I am on workflowdrafts page 17 | And I click on "Create new workflow" "link" 18 | And I set the following fields to these values: 19 | | Title | Admin Approve Step WF #1 | 20 | | Displayed workflow title | Admin Approve Step WF #1 | 21 | And I press "Save changes" 22 | And I select "Start date delay trigger" from the "tool_lifecycle-choose-trigger" singleselect 23 | And I set the following fields to these values: 24 | | Instance name | My Trigger | 25 | | delay[number] | 0 | 26 | | delay[timeunit] | seconds | 27 | And I press "Save changes" 28 | And I select "Admin approve step" from the "tool_lifecycle-choose-step" singleselect 29 | And I set the following fields to these values: 30 | | Instance name | Admin Approve Step #1 | 31 | | Status message | My status | 32 | And I press "Save changes" 33 | And I am on workflowdrafts page 34 | And I press "Activate" 35 | And I run the scheduled task "tool_lifecycle\task\lifecycle_task" 36 | And I log out 37 | 38 | Scenario: Test interaction of admin approve step 39 | When I log in as "teacher" 40 | And I am on lifecycle view 41 | Then I should see "Course 1" in the "tool_lifecycle_remaining" "table" 42 | And I should see "My status" in the "tool_lifecycle_remaining" "table" 43 | -------------------------------------------------------------------------------- /step/adminapprove/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Admin Approve Step 19 | * 20 | * @package lifecyclestep_adminapprove 21 | * @copyright 2025 Thomas Niedermaier Universität Münster 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die; 26 | 27 | $plugin->version = 2025050400; 28 | $plugin->component = 'lifecyclestep_adminapprove'; 29 | $plugin->dependencies = [ 30 | 'tool_lifecycle' => 2025050400, 31 | ]; 32 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 33 | $plugin->supported = [401, 405]; 34 | $plugin->release = 'v4.5-r1'; 35 | $plugin->maturity = MATURITY_STABLE; 36 | -------------------------------------------------------------------------------- /step/createbackup/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace lifecyclestep_createbackup\privacy; 18 | 19 | use core_privacy\local\metadata\null_provider; 20 | 21 | /** 22 | * Privacy subsystem implementation for lifecyclestep_createbackup. 23 | * 24 | * @package lifecyclestep_createbackup 25 | * @copyright 2022 ISB Bayern 26 | * @author Philipp Memmel 27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 | */ 29 | class provider implements null_provider { 30 | 31 | /** 32 | * Get the language string identifier with the component's language 33 | * file to explain why this plugin stores no data. 34 | * 35 | * @return string the reason 36 | */ 37 | public static function get_reason(): string { 38 | return 'privacy:metadata'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /step/createbackup/db/upgrade.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Update script for lifecycles subplugin createbackup 19 | * 20 | * @package lifecyclestep_createbackup 21 | * @copyright 2019 WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | use tool_lifecycle\local\manager\settings_manager; 26 | use tool_lifecycle\local\manager\step_manager; 27 | 28 | /** 29 | * Update script for lifecycles subplugin createbackup. 30 | * @param int $oldversion Version id of the previously installed version. 31 | * @throws coding_exception 32 | * @throws dml_exception 33 | * @throws downgrade_exception 34 | * @throws moodle_exception 35 | * @throws upgrade_exception 36 | */ 37 | function xmldb_lifecyclestep_createbackup_upgrade($oldversion) { 38 | 39 | if ($oldversion < 2019052900) { 40 | 41 | $coursedeletesteps = step_manager::get_step_instances_by_subpluginname('createbackup'); 42 | 43 | $settingsname = 'maximumbackupspercron'; 44 | $settingsvalue = 10; 45 | foreach ($coursedeletesteps as $step) { 46 | if (empty(settings_manager::get_settings($step->id, 'step'))) { 47 | settings_manager::save_settings($step->id, 'step', 'createbackup', 48 | [$settingsname => $settingsvalue]); 49 | } 50 | } 51 | 52 | // Deletecourse savepoint reached. 53 | upgrade_plugin_savepoint(true, 2019052900, 'lifecyclestep', 'createbackup'); 54 | } 55 | 56 | return true; 57 | } 58 | -------------------------------------------------------------------------------- /step/createbackup/lang/de/lifecyclestep_createbackup.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for create backup step 19 | * 20 | * @package lifecyclestep_createbackup 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['maximumbackupspercron'] = 'Maximale Anzahl an Sicherungen per cron'; 26 | $string['plugindescription'] = 'Stößt ein Backup der getriggerten Kursen an.'; 27 | $string['pluginname'] = 'Kurssicherungs-Schritt'; 28 | $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; 29 | 30 | -------------------------------------------------------------------------------- /step/createbackup/lang/en/lifecyclestep_createbackup.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for create backup step 19 | * 20 | * @package lifecyclestep_createbackup 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['maximumbackupspercron'] = 'Maximum number of backups per cron'; 26 | $string['plugindescription'] = 'Initiates a backup of the triggered courses.'; 27 | $string['pluginname'] = 'Create backup step'; 28 | $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; 29 | 30 | -------------------------------------------------------------------------------- /step/createbackup/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Create Backup Step 19 | * 20 | * @package lifecyclestep_createbackup 21 | * @copyright 2025 Thomas Niedermaier Universität Münster 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die; 26 | 27 | $plugin->version = 2025050400; 28 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 29 | $plugin->supported = [401, 405]; 30 | $plugin->component = 'lifecyclestep_createbackup'; 31 | $plugin->release = 'v4.5-r1'; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /step/deletecourse/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace lifecyclestep_deletecourse\privacy; 18 | 19 | use core_privacy\local\metadata\null_provider; 20 | 21 | /** 22 | * Privacy subsystem implementation for lifecyclestep_deletecourse. 23 | * 24 | * @package lifecyclestep_deletecourse 25 | * @copyright 2022 ISB Bayern 26 | * @author Philipp Memmel 27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 | */ 29 | class provider implements null_provider { 30 | 31 | /** 32 | * Get the language string identifier with the component's language 33 | * file to explain why this plugin stores no data. 34 | * 35 | * @return string the reason 36 | */ 37 | public static function get_reason(): string { 38 | return 'privacy:metadata'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /step/deletecourse/db/upgrade.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Update script for lifecycles subplugin deletecourse 19 | * 20 | * @package lifecyclestep_deletecourse 21 | * @copyright 2018 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | use tool_lifecycle\local\manager\settings_manager; 26 | use tool_lifecycle\local\manager\step_manager; 27 | 28 | /** 29 | * Update script for lifecycles subplugin deletecourse 30 | * 31 | * @package lifecyclestep_deletecourse 32 | * @copyright 2018 Tobias Reischmann WWU 33 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 34 | * @param int $oldversion Version id of the previously installed version. 35 | * @throws coding_exception 36 | * @throws dml_exception 37 | * @throws downgrade_exception 38 | * @throws moodle_exception 39 | * @throws upgrade_exception 40 | */ 41 | function xmldb_lifecyclestep_deletecourse_upgrade($oldversion) { 42 | 43 | if ($oldversion < 2018122300) { 44 | 45 | $coursedeletesteps = step_manager::get_step_instances_by_subpluginname('deletecourse'); 46 | 47 | $settingsname = 'maximumdeletionspercron'; 48 | $settingsvalue = 10; 49 | foreach ($coursedeletesteps as $step) { 50 | if (empty(settings_manager::get_settings($step->id, 'step'))) { 51 | settings_manager::save_settings($step->id, 'step', 'deletecourse', 52 | [$settingsname => $settingsvalue]); 53 | } 54 | } 55 | 56 | // Deletecourse savepoint reached. 57 | upgrade_plugin_savepoint(true, 2018122300, 'lifecyclestep', 'deletecourse'); 58 | } 59 | 60 | return true; 61 | } 62 | -------------------------------------------------------------------------------- /step/deletecourse/lang/de/lifecyclestep_deletecourse.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for delete course step 19 | * 20 | * @package lifecyclestep_deletecourse 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['deletecourse_maximumdeletionspercron'] = 'Maximale Anzahl an Kurslöschungen per cron'; 26 | $string['plugindescription'] = 'Initiiert das Löschen der getriggerten Kurse.'; 27 | $string['pluginname'] = 'Kurslöschen-Schritt'; 28 | $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; 29 | 30 | -------------------------------------------------------------------------------- /step/deletecourse/lang/en/lifecyclestep_deletecourse.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for delete course step 19 | * 20 | * @package lifecyclestep_deletecourse 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['deletecourse_maximumdeletionspercron'] = 'Maximum number of courses deleted per cron'; 26 | $string['plugindescription'] = 'Initiates the deletion of the triggered courses.'; 27 | $string['pluginname'] = 'Delete course step'; 28 | $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; 29 | 30 | -------------------------------------------------------------------------------- /step/deletecourse/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Delete Course Step 19 | * 20 | * @package lifecyclestep_deletecourse 21 | * @copyright 2025 Thomas Niedermaier Universität Münster 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die; 26 | 27 | $plugin->version = 2025050400; 28 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 29 | $plugin->supported = [401, 405]; 30 | $plugin->component = 'lifecyclestep_deletecourse'; 31 | $plugin->release = 'v4.5-r1'; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /step/duplicate/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace lifecyclestep_duplicate\privacy; 18 | 19 | use core_privacy\local\metadata\null_provider; 20 | 21 | /** 22 | * Privacy subsystem implementation for lifecyclestep_duplicate. 23 | * 24 | * @package lifecyclestep_duplicate 25 | * @copyright 2022 ISB Bayern 26 | * @author Philipp Memmel 27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 | */ 29 | class provider implements null_provider { 30 | 31 | /** 32 | * Get the language string identifier with the component's language 33 | * file to explain why this plugin stores no data. 34 | * 35 | * @return string the reason 36 | */ 37 | public static function get_reason(): string { 38 | return 'privacy:metadata'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /step/duplicate/db/access.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Capability definitions for the duplication step subplugin 19 | * @package lifecyclestep_duplicate 20 | * @copyright 2017 Tobias Reischmann WWU 21 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 | */ 23 | defined('MOODLE_INTERNAL') || die(); 24 | 25 | $capabilities = [ 26 | 27 | 'lifecyclestep/duplicate:enterdata' => [ 28 | 'contextlevel' => CONTEXT_COURSE, 29 | 'captype' => 'write', 30 | 'archetypes' => [ 31 | 'editingteacher' => CAP_ALLOW, 32 | ], 33 | 'clonepermissionsfrom' => 'tool/lifecycle:managecourses', 34 | ], 35 | ]; 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /step/duplicate/lang/de/lifecyclestep_duplicate.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for duplicate step 19 | * 20 | * @package lifecyclestep_duplicate 21 | * @copyright 2018 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['action_new_course_data'] = '{$a} hat neuen Kursnamen eingegeben'; 26 | $string['duplicate:enterdata'] = 'Daten für Kursduplikation eingeben'; 27 | $string['duplicate_course_header'] = 'Kurs duplizieren'; 28 | $string['duplicate_form'] = 'Daten eingeben'; 29 | $string['plugindescription'] = 'In diesem Schritt wird jeder getriggerte Kurs dupliziert.'; 30 | $string['pluginname'] = 'Kurs-Duplizieren-Schritt'; 31 | $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; 32 | $string['status_message_duplication'] = 'Duplizierter Kurs wird bald verfügbar sein.'; 33 | $string['status_message_form'] = 'Zusätzliche Informationen benötigt'; 34 | 35 | -------------------------------------------------------------------------------- /step/duplicate/lang/en/lifecyclestep_duplicate.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for duplicate step 19 | * 20 | * @package lifecyclestep_duplicate 21 | * @copyright 2018 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['action_new_course_data'] = '{$a} supplied new course name'; 26 | $string['duplicate:enterdata'] = 'Enter data for course duplication'; 27 | $string['duplicate_course_header'] = 'Duplicate course'; 28 | $string['duplicate_form'] = 'Enter data'; 29 | $string['plugindescription'] = 'Duplicates each triggered course.'; 30 | $string['pluginname'] = 'Duplicate step'; 31 | $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; 32 | $string['status_message_duplication'] = 'Duplicated course will be available shortly.'; 33 | $string['status_message_form'] = 'Additional information required'; 34 | 35 | -------------------------------------------------------------------------------- /step/duplicate/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Duplicate Step 19 | * 20 | * @package lifecyclestep_duplicate 21 | * @copyright 2025 Thomas Niedermaier Universität Münster 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die; 26 | 27 | $plugin->version = 2025050400; 28 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 29 | $plugin->supported = [401, 405]; 30 | $plugin->component = 'lifecyclestep_duplicate'; 31 | $plugin->release = 'v4.5-r1'; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /step/email/db/access.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Capability definitions for the email step subplugin 19 | * @package lifecyclestep_email 20 | * @copyright 2017 Tobias Reischmann WWU 21 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 | */ 23 | defined('MOODLE_INTERNAL') || die(); 24 | 25 | $capabilities = [ 26 | 27 | 'lifecyclestep/email:preventdeletion' => [ 28 | 'contextlevel' => CONTEXT_COURSE, 29 | 'captype' => 'write', 30 | 'archetypes' => [ 31 | 'manager' => CAP_PREVENT, 32 | 'editingteacher' => CAP_ALLOW, 33 | 'teacher' => CAP_PREVENT, 34 | 'students' => CAP_PREVENT, 35 | ], 36 | 'clonepermissionsfrom' => 'tool/lifecycle:managecourses', 37 | ], 38 | ]; 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /step/email/db/install.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 |
31 |
-------------------------------------------------------------------------------- /step/email/db/upgrade.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Update script for lifecyclestep_email plugin 19 | * 20 | * @package lifecyclestep_email 21 | * @copyright 2024 Nina Herrmann University of Münster 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | /** 26 | * Update script for lifecyclestep_email. 27 | * @param int $oldversion Version id of the previously installed version. 28 | * @return bool 29 | * @throws ddl_exception 30 | * @throws ddl_field_missing_exception 31 | * @throws ddl_table_missing_exception 32 | * @throws dml_exception 33 | * @throws downgrade_exception 34 | * @throws upgrade_exception 35 | */ 36 | function xmldb_lifecyclestep_email_upgrade($oldversion) { 37 | 38 | global $DB; 39 | $dbman = $DB->get_manager(); 40 | if ($oldversion < 2025050400) { 41 | $table = new xmldb_table('lifecyclestep_email_notified'); 42 | 43 | // Adding fields to table lifecyclestep_email_notified. 44 | $table->add_field('id', XMLDB_TYPE_INTEGER, '20', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 45 | $table->add_field('courseid', XMLDB_TYPE_INTEGER, '20', null, XMLDB_NOTNULL, null, null); 46 | $table->add_field('userid', XMLDB_TYPE_INTEGER, '20', null, XMLDB_NOTNULL, null, null); 47 | $table->add_field('timemailsent', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 48 | 49 | // Adding keys to table lifecyclestep_email_notified. 50 | $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 51 | $table->add_key('courseid_fk', XMLDB_KEY_FOREIGN, ['courseid'], 'course', ['id']); 52 | $table->add_key('userid_fk', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']); 53 | 54 | // Conditionally launch create table for lifecyclestep_email_notified. 55 | if (!$dbman->table_exists($table)) { 56 | $dbman->create_table($table); 57 | } 58 | 59 | // Lifecycle savepoint reached. 60 | upgrade_plugin_savepoint(true, 2025050400, 'lifecyclestep', 'email'); 61 | } 62 | return true; 63 | } 64 | -------------------------------------------------------------------------------- /step/email/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Email Step 19 | * 20 | * @package lifecyclestep_email 21 | * @copyright 2025 Thomas Niedermaier Universität Münster 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die; 26 | 27 | 28 | $plugin->version = 2025050400; 29 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 30 | $plugin->supported = [401, 405]; 31 | $plugin->component = 'lifecyclestep_email'; 32 | $plugin->release = 'v4.5-r1'; 33 | $plugin->maturity = MATURITY_STABLE; 34 | -------------------------------------------------------------------------------- /step/makeinvisible/README.md: -------------------------------------------------------------------------------- 1 | # Course Life Cycle (moodle-lifecyclestep_makeinvisible) 2 | 3 | This is a step for [Life Cycle](https://github.com/learnweb/moodle-tool_lifecycle), that hides courses. 4 | 5 | ## Behaviour 6 | 7 | For each course, moodle saves the visibility for course (```visibleold```) and category seperately. 8 | The final course visibility (```visible```) will be true, if both ```visibleold``` is true and the category is visible. 9 | This is done, so that if you hide a course, then hide the category and then show the category again, the course remains hidden. 10 | 11 | You can choose to display a course despite it's category being hidden, however, this is disregarded in case of a rollback. 12 | 13 | When this step is executed, the original visibility (```visibleold```) of the course is saved. 14 | Then the course will be set to hidden. 15 | 16 | In case of a rollback, if the course is still hidden, the courses visibility (```visibleold```) will be restored to it's saved state 17 | and the final visibility (```visible```) will be recalculated. 18 | 19 | If a course is visible, this step is executed, you unhide the course, hide it again and then a rollback is performed, 20 | the visibility of the course will be restored to being shown. -------------------------------------------------------------------------------- /step/makeinvisible/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace lifecyclestep_makeinvisible\privacy; 18 | 19 | use core_privacy\local\metadata\null_provider; 20 | 21 | /** 22 | * Privacy subsystem implementation for lifecyclestep_makeinvisible. 23 | * 24 | * @package lifecyclestep_makeinvisible 25 | * @copyright WWU Münster 26 | * @author Nina Herrmann 27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 | */ 29 | class provider implements null_provider { 30 | 31 | /** 32 | * Get the language string identifier with the component's language 33 | * file to explain why this plugin stores no data. 34 | * 35 | * @return string the reason 36 | */ 37 | public static function get_reason(): string { 38 | return 'privacy:metadata'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /step/makeinvisible/lang/de/lifecyclestep_makeinvisible.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang Strings for Make Invisible Step 19 | * 20 | * @package lifecyclestep_makeinvisible 21 | * @copyright 2019 Justus Dieckmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['plugindescription'] = 'Ein getriggerter Kurs wird vor den Teilnehmer:innen verborgen.'; 26 | $string['pluginname'] = 'Kurs verbergen - Schritt'; 27 | $string['privacy:metadata'] = 'Speichert keine personenbezogenen Daten'; 28 | -------------------------------------------------------------------------------- /step/makeinvisible/lang/en/lifecyclestep_makeinvisible.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang Strings for Make Invisible Step 19 | * 20 | * @package lifecyclestep_makeinvisible 21 | * @copyright 2019 Justus Dieckmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['plugindescription'] = 'Hides a course for participants.'; 26 | $string['pluginname'] = 'Make Course Invisible Step'; 27 | $string['privacy:metadata'] = 'Does not store any data'; 28 | -------------------------------------------------------------------------------- /step/makeinvisible/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Make Invisible Step 19 | * 20 | * @package lifecyclestep_makeinvisible 21 | * @copyright 2019 Justus Dieckmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die; 26 | 27 | $plugin->version = 2025050400; 28 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 29 | $plugin->supported = [401, 405]; 30 | $plugin->component = 'lifecyclestep_makeinvisible'; 31 | $plugin->dependencies = [ 32 | 'tool_lifecycle' => 2025050400, 33 | ]; 34 | $plugin->release = 'v4.5-r1'; 35 | $plugin->maturity = MATURITY_STABLE; 36 | -------------------------------------------------------------------------------- /templates/overview_addinstance.mustache: -------------------------------------------------------------------------------- 1 | {{! 2 | This file is part of Moodle - http://moodle.org/ 3 | 4 | Moodle is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Moodle is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Moodle. If not, see . 16 | }} 17 | {{! 18 | @template tool_lifecycle/overview_addinstance 19 | 20 | Add trigger and add step select fields 21 | 22 | Example context (json): 23 | { 24 | "addtriggerselect": "Add trigger select", 25 | "addstepselect": "Add step select", 26 | "activate": "Activate Button", 27 | "newworkflow": true 28 | } 29 | }} 30 | {{#newworkflow}} 31 |
{{#str}} addtriggernewworkflow, tool_lifecycle{{/str}}:
32 | {{/newworkflow}} 33 |
34 | {{{addtriggerselect}}} {{^newworkflow}}{{{addstepselect}}}{{/newworkflow}} {{{activate}}} 35 |
36 | -------------------------------------------------------------------------------- /templates/overview_step.mustache: -------------------------------------------------------------------------------- 1 | {{! 2 | This file is part of Moodle - http://moodle.org/ 3 | 4 | Moodle is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Moodle is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Moodle. If not, see . 16 | }} 17 | {{! 18 | @template tool_lifecycle/overview_step 19 | 20 | Presentation of lifecycle step in overview. 21 | 22 | Example context (json): 23 | { 24 | "instancename": "Triggername", 25 | "subpluginname": "adminapprove", 26 | "selected": true, 27 | "showdetails": true, 28 | "automatic": true, 29 | "additionalinfo": "---", 30 | "showdetails": 1, 31 | "id": 1, 32 | "numberofcourses": 5, 33 | "actionmenu": "actionmenu", 34 | "popuplink": "admin/tool/lifecycle/workflowoverview.php?wf=1" 35 | } 36 | }} 37 | {{#steps}} 38 |
39 |
40 |
41 |
42 | {{#shortentext}} 25, {{instancename}} {{/shortentext}}
43 | {{subpluginname}} 44 |
45 |
46 | {{{ actionmenu }}} 47 |
48 |
49 |
50 | {{#numberofcourses}} 51 | 52 | {{#str}} courses {{/str}}: {{numberofcourses}} 53 | 54 | {{/numberofcourses}} 55 | {{^numberofcourses}} 56 | {{#str}} courses {{/str}}: {{numberofcourses}} 57 | {{/numberofcourses}} 58 |
59 |
60 | {{/steps}} 61 | -------------------------------------------------------------------------------- /templates/overview_timetrigger.mustache: -------------------------------------------------------------------------------- 1 | {{! 2 | This file is part of Moodle - http://moodle.org/ 3 | 4 | Moodle is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Moodle is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Moodle. If not, see . 16 | }} 17 | {{! 18 | @template tool_lifecycle/overview_timetrigger 19 | 20 | Trigger course selection run presentation 21 | 22 | Example context (json): 23 | { 24 | "instancename": "Triggername", 25 | "subpluginname": "adminapprove", 26 | "classfires": "my-2", 27 | "showcoursecounts": true, 28 | "automatic": true, 29 | "additionalinfo": "Last run: 1.1.2000", 30 | "actionmenu": "actionmenu" 31 | } 32 | }} 33 | {{#timetrigger}} 34 |
35 |
36 |
37 | {{#shortentext}} 25, {{instancename}} {{/shortentext}}
38 | {{subpluginname}} 39 |
40 |
41 | {{{ actionmenu }}} 42 |
43 |
44 | {{#showcoursecounts}} 45 |
46 | {{{additionalinfo}}} 47 |
48 | {{/showcoursecounts}} 49 |
50 | {{/timetrigger}} 51 | -------------------------------------------------------------------------------- /templates/search_input.mustache: -------------------------------------------------------------------------------- 1 | {{! 2 | This file is part of Moodle - http://moodle.org/ 3 | 4 | Moodle is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Moodle is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Moodle. If not, see . 16 | }} 17 | {{! 18 | @template tool_lifecycle/search_input 19 | 20 | Simple search input. 21 | 22 | Directly copied from core/search_input, because we have to provide it for Moodle 3.9. 23 | 24 | Example context (json): 25 | { 26 | "action": "https://moodle.local/admin/search.php", 27 | "extraclasses": "my-2", 28 | "inputname": "search", 29 | "inform": false, 30 | "searchstring": "Search settings", 31 | "value": "policy", 32 | "btnclass": "primary", 33 | "query": "themedesigner", 34 | "hiddenfields": [ 35 | { 36 | "name": "context", 37 | "value": "11" 38 | } 39 | ] 40 | } 41 | }} 42 |
43 | {{^inform}} 44 |
45 | {{/inform}} 46 | {{#hiddenfields}} 47 | 48 | {{/hiddenfields}} 49 |
50 | 53 | 64 |
65 | 69 |
70 | 71 |
72 | {{#otherfields}} 73 |
{{{ otherfields }}}
74 | {{/otherfields}} 75 | {{^inform}} 76 |
77 | {{/inform}} 78 |
-------------------------------------------------------------------------------- /tests/behat/upload_workflow.feature: -------------------------------------------------------------------------------- 1 | @tool @tool_lifecycle @_file_upload @upload_workflow 2 | Feature: Upload a workflow definition 3 | 4 | @javascript 5 | Scenario: Upload a new workflow 6 | Given I log in as "admin" 7 | And I am on workflowdrafts page 8 | And I click on "Upload workflow" "link" 9 | And I upload "admin/tool/lifecycle/tests/fixtures/simpleworkflow.xml" file to "Upload workflow" filemanager 10 | And I press "Upload" 11 | Then I should see "A Workflow" 12 | -------------------------------------------------------------------------------- /tests/fixtures/simpleworkflow.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /tests/persistence/persist_workflow_test.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Tests creating storing and retrieving a workflow object. 19 | * @package tool_lifecycle 20 | * @category test 21 | * @group tool_lifecycle 22 | * @copyright 2017 Tobias Reischmann WWU 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | namespace tool_lifecycle; 26 | defined('MOODLE_INTERNAL') || die(); 27 | 28 | require_once(__DIR__ . '/../../lib.php'); 29 | 30 | use tool_lifecycle\local\entity\workflow; 31 | use tool_lifecycle\local\manager\workflow_manager; 32 | 33 | /** 34 | * Tests creating storing and retrieving a workflow object. 35 | * @package tool_lifecycle 36 | * @category test 37 | * @group tool_lifecycle 38 | * @copyright 2017 Tobias Reischmann WWU 39 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 40 | */ 41 | final class persist_workflow_test extends \advanced_testcase { 42 | 43 | /** @var workflow $workflow Instance of the workflow. */ 44 | private $workflow; 45 | 46 | /** 47 | * Setup the testcase. 48 | */ 49 | public function setUp(): void { 50 | parent::setUp(); 51 | $this->resetAfterTest(true); 52 | $record = new \stdClass(); 53 | $record->id = null; 54 | $record->title = 'Title'; 55 | $this->workflow = workflow::from_record($record); 56 | } 57 | 58 | /** 59 | * Test the creation of a process. 60 | * @covers \tool_lifecycle\local\manager\workflow_manager create a wf. 61 | */ 62 | public function test_create(): void { 63 | $this->assertNull($this->workflow->id); 64 | workflow_manager::insert_or_update($this->workflow); 65 | $this->assertNotNull($this->workflow->id); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /tests/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | . 34 | 35 | 36 | 37 | 38 | . 39 | 40 | . 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /trigger/byrole/README.md: -------------------------------------------------------------------------------- 1 | # moodle-lifecycletrigger_byrole 2 | This is a trigger-Subplugin for the admin tool [moodle-tool_lifecycle](https://github.com/learnweb/moodle-tool_lifecycle). 3 | Course without a reponsible person are marked for the cleanupprocess of the lifecycle admin tool. 4 | ## Settings 5 | Site administrators choose between all available roles for responsible roles. When multiple roles are selected it 6 | is sufficient if at least one role is represented in the course or in a parent context. This means that courses that belong 7 | to courses where the specific role is assigned are not deleted. 8 | 9 | Additionally, administrators determine a time period which 10 | serves as a queue time until a course is marked for the cleanup process. 11 | This functionality assures that courses are not altered when roles are merely changed temporary. 12 | 13 | ## Proceeding 14 | A trigger plugin always receives one course. To determine whether the course should be deleted the plugin 15 | checks which roles are present in the course. When at least one responsible role is present the course will not be triggered. 16 | Courses that have no responsible person are saved in the database with a timestamp. 17 | When a course has no responsible person and a entry in the table and the timestamp 18 | is sufficiently old, the course is triggered for the cleanup process of the admin tool. 19 | 20 | For detailed information on trigger plugins visit the 21 | [Wiki](https://github.com/learnweb/moodle-tool_lifecycle/wiki) of the lifecycle admin tool. -------------------------------------------------------------------------------- /trigger/byrole/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace lifecycletrigger_byrole\privacy; 18 | 19 | use core_privacy\local\metadata\null_provider; 20 | 21 | /** 22 | * Privacy subsystem implementation for lifecycletrigger_byrole. 23 | * 24 | * @package lifecycletrigger_byrole 25 | * @copyright WWU Münster 26 | * @author Nina Herrmann 27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 | */ 29 | class provider implements null_provider { 30 | 31 | /** 32 | * Get the language string identifier with the component's language 33 | * file to explain why this plugin stores no data. 34 | * 35 | * @return string the reason 36 | */ 37 | public static function get_reason(): string { 38 | return 'privacy:metadata'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /trigger/byrole/db/install.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
-------------------------------------------------------------------------------- /trigger/byrole/lang/de/lifecycletrigger_byrole.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for site course trigger 19 | * 20 | * @package lifecycletrigger_byrole 21 | * @copyright 2017 Tobias Reischmann WWU Nina Herrmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['delay'] = 'Wieviele Tage ohne Rolle'; 26 | $string['delay_help'] = 'Wieviele Tage ein Kurs ohne diese Rolle sein muß, damit der Trigger ausgelöst wird.'; 27 | $string['plugindescription'] = 'Löst aus wenn in einem Kurs für eine bestimmte Anzahl an Tagen eine bestimmte Rolle nicht vergeben wurde.'; 28 | $string['pluginname'] = 'Kurse mit fehlender Rolle'; 29 | $string['privacy:metadata'] = 'Speichert keine Userdaten'; 30 | $string['responsibleroles'] = 'Geforderte Rollen im Kurs'; 31 | $string['responsibleroles_help'] = 'Wählen Sie hier die geforderten Rollen aus. Wenn mindestens eine dieser Rollen vergeben wurde wird nicht ausgelöst..'; 32 | -------------------------------------------------------------------------------- /trigger/byrole/lang/en/lifecycletrigger_byrole.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for site course trigger 19 | * 20 | * @package lifecycletrigger_byrole 21 | * @copyright 2017 Tobias Reischmann WWU Nina Herrmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['delay'] = 'Days of delay for triggering'; 26 | $string['delay_help'] = 'Days a course has to remain without the mandatory role until the course is finally triggered'; 27 | $string['plugindescription'] = 'Triggers if a specified role is misssing in a course for a certain timespan.'; 28 | $string['pluginname'] = 'Trigger courses by roles missing'; 29 | $string['privacy:metadata'] = 'Does not store user specific data'; 30 | $string['responsibleroles'] = 'Responsible Roles in courses'; 31 | $string['responsibleroles_help'] = 'Select the roles that have to be present in the course. If one of these roles is present the course is not triggered.'; 32 | -------------------------------------------------------------------------------- /trigger/byrole/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lifecycle By Role Trigger 19 | * 20 | * @package lifecycletrigger_byrole 21 | * @copyright 2017 Tobias Reischmann WWU Nina Herrmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die; 26 | 27 | $plugin->version = 2025050400; 28 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 29 | $plugin->supported = [401, 405]; 30 | $plugin->component = 'lifecycletrigger_byrole'; 31 | $plugin->dependencies = [ 32 | 'tool_lifecycle' => 2025050400, 33 | ]; 34 | $plugin->release = 'v4.5-r1'; 35 | $plugin->maturity = MATURITY_STABLE; 36 | -------------------------------------------------------------------------------- /trigger/categories/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace lifecycletrigger_categories\privacy; 18 | 19 | use core_privacy\local\metadata\null_provider; 20 | 21 | /** 22 | * Privacy subsystem implementation for lifecycletrigger_categories. 23 | * 24 | * @package lifecycletrigger_categories 25 | * @copyright 2022 ISB Bayern 26 | * @author Philipp Memmel 27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 | */ 29 | class provider implements null_provider { 30 | 31 | /** 32 | * Get the language string identifier with the component's language 33 | * file to explain why this plugin stores no data. 34 | * 35 | * @return string the reason 36 | */ 37 | public static function get_reason(): string { 38 | return 'privacy:metadata'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /trigger/categories/lang/de/lifecycletrigger_categories.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for categories trigger 19 | * 20 | * @package lifecycletrigger_categories 21 | * @copyright 2018 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['categories'] = 'Kategorien, für die der Workflow ausgelöst werden soll.'; 26 | $string['categories_do_not_exist'] = 'Es gibt keine Kurskategorien mit den folgenden IDs: {$a}.'; 27 | $string['categories_noselection'] = 'Bitte wählen sie mindestens eine Kategorie aus.'; 28 | $string['exclude'] = 'Falls ausgewählt, werden gerade die Kurse der angegebenen Kategorien nicht ausgelöst.'; 29 | $string['plugindescription'] = 'Selektiert alle Kurse einer Kurskategorie.'; 30 | $string['pluginname'] = 'Kategorie-Trigger'; 31 | $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; 32 | -------------------------------------------------------------------------------- /trigger/categories/lang/en/lifecycletrigger_categories.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for categories trigger 19 | * 20 | * @package lifecycletrigger_categories 21 | * @copyright 2018 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['categories'] = 'Categories, for which the workflow should be triggered'; 26 | $string['categories_do_not_exist'] = 'There are no categories with the following ids: {$a}.'; 27 | $string['categories_noselection'] = 'Please choose at least one category.'; 28 | $string['exclude'] = 'If ticked, the named categories are excluded from triggering instead.'; 29 | $string['plugindescription'] = 'Selects all courses of a course category.'; 30 | $string['pluginname'] = 'Categories trigger'; 31 | $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; 32 | -------------------------------------------------------------------------------- /trigger/categories/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Categories Trigger 19 | * 20 | * @package lifecycletrigger_categories 21 | * @copyright 2025 Thomas Niedermaier Universität Münster 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die; 26 | 27 | $plugin->version = 2025050400; 28 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 29 | $plugin->supported = [401, 405]; 30 | $plugin->component = 'lifecycletrigger_categories'; 31 | $plugin->release = 'v4.5-r1'; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /trigger/customfielddelay/README.md: -------------------------------------------------------------------------------- 1 | # moodle-lifecycletrigger_customfielddelay 2 | This is a trigger subplugin for the admin tool [moodle-tool_lifecycle](https://github.com/learnweb/moodle-tool_lifecycle). 3 | A course will be triggered if the value of a specifiable date customfield is further in the past than a specified period. 4 | 5 | 6 | -------------------------------------------------------------------------------- /trigger/customfielddelay/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace lifecycletrigger_customfielddelay\privacy; 18 | 19 | use core_privacy\local\metadata\null_provider; 20 | 21 | /** 22 | * Privacy subsystem implementation for lifecycletrigger_customfielddelay. 23 | * 24 | * @package lifecycletrigger_customfielddelay 25 | * @copyright 2023 Justus Dieckmann WWU Münster 26 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 27 | */ 28 | class provider implements null_provider { 29 | 30 | /** 31 | * Get the language string identifier with the component's language 32 | * file to explain why this plugin stores no data. 33 | * 34 | * @return string 35 | */ 36 | public static function get_reason(): string { 37 | return 'privacy:metadata'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /trigger/customfielddelay/lang/de/lifecycletrigger_customfielddelay.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for start date delay trigger 19 | * 20 | * @package lifecycletrigger_customfielddelay 21 | * @copyright 2025 Thomas Niedermaier University Münster 22 | * @copyright 2020 Tobias Reischmann WWU 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | $string['customfield'] = 'Ein Customfield des Kurses'; 27 | $string['customfield_help'] = 'Der Trigger prüft den Wert dieses Customfields des Kurses.'; 28 | $string['delay'] = 'Zeit seit dem Datum des Customfield, bis ein Prozess gestartet wird'; 29 | $string['delay_help'] = 'Der Trigger wird ausgeführt, falls die Zeit, die seit dem Customfield-Datum des Kurses vergangen ist, größer ist, als der angegebene Zeitraum.'; 30 | $string['plugindescription'] = 'Löst aus wenn das Datum eines zu spezifizierenden Customfield vom Typ Datum nach einem Zeitpunkt in der Zukunft ist.'; 31 | $string['pluginname'] = 'Customfield Datum - Trigger'; 32 | $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; 33 | -------------------------------------------------------------------------------- /trigger/customfielddelay/lang/en/lifecycletrigger_customfielddelay.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for start date delay trigger 19 | * 20 | * @package lifecycletrigger_customfielddelay 21 | * @copyright 2025 Thomas Niedermaier University Münster 22 | * @copyright 2020 Tobias Reischmann WWU 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | $string['customfield'] = 'Customfield of the course'; 27 | $string['customfield_help'] = 'The trigger checks the value saved in the course for this customfield.'; 28 | $string['delay'] = 'Delay from customfield date of course until starting a process'; 29 | $string['delay_help'] = 'The trigger will be invoked if the time passed since the customfield date of the course is longer than this delay.'; 30 | $string['plugindescription'] = 'Triggers if the value of a specifiable datetype customfield is after a point in the future.'; 31 | $string['pluginname'] = 'Customfield date delay trigger'; 32 | $string['privacy:metadata'] = 'The lifecycletrigger_customfielddelay plugin does not store any personal data.'; 33 | -------------------------------------------------------------------------------- /trigger/customfielddelay/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Customfielddelay Trigger 19 | * 20 | * @package lifecycletrigger_customfielddelay 21 | * @copyright 2025 Thomas Niedermaier University Münster 22 | * @copyright 2020 Tobias Reischmann WWU 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | defined('MOODLE_INTERNAL') || die; 27 | 28 | $plugin->version = 2025050400; 29 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 30 | $plugin->supported = [401, 405]; 31 | $plugin->component = 'lifecycletrigger_customfielddelay'; 32 | $plugin->release = 'v4.5-r1'; 33 | $plugin->maturity = MATURITY_STABLE; 34 | $plugin->dependencies = ['customfield_semester' => 2020041304]; 35 | -------------------------------------------------------------------------------- /trigger/delayedcourses/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace lifecycletrigger_delayedcourses\privacy; 18 | 19 | use core_privacy\local\metadata\null_provider; 20 | 21 | /** 22 | * Privacy subsystem implementation for lifecycletrigger_delayedcourses. 23 | * 24 | * @package lifecycletrigger_delayedcourses 25 | * @copyright 2022 ISB Bayern 26 | * @author Philipp Memmel 27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 | */ 29 | class provider implements null_provider { 30 | 31 | /** 32 | * Get the language string identifier with the component's language 33 | * file to explain why this plugin stores no data. 34 | * 35 | * @return string the reason 36 | */ 37 | public static function get_reason(): string { 38 | return 'privacy:metadata'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /trigger/delayedcourses/lang/de/lifecycletrigger_delayedcourses.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for delayed course trigger 19 | * 20 | * @package lifecycletrigger_delayedcourses 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['delay'] = 'Dieser Trigger wird alle Kurse ausschließen, die durch Nutzerinteraktion verzögert wurden.'; 26 | $string['plugindescription'] = 'Schließt Kurse von diesem Workflow aus, die durch Nutzeraktion verzögert wurden.'; 27 | $string['pluginname'] = 'Verzögerte Kurse ausschließen - Trigger'; 28 | $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; 29 | 30 | -------------------------------------------------------------------------------- /trigger/delayedcourses/lang/en/lifecycletrigger_delayedcourses.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for delayed course trigger 19 | * 20 | * @package lifecycletrigger_delayedcourses 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['delay'] = 'This module will exclude all courses, which were delayed by user interaction'; 26 | $string['plugindescription'] = 'Exludes all courses which were delayed by user interaction.'; 27 | $string['pluginname'] = 'Exclude delayed courses trigger'; 28 | $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; 29 | -------------------------------------------------------------------------------- /trigger/delayedcourses/lib.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Trigger subplugin to exclude delayed courses. 19 | * 20 | * @package lifecycletrigger_delayedcourses 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | namespace tool_lifecycle\trigger; 25 | 26 | use tool_lifecycle\local\response\trigger_response; 27 | use tool_lifecycle\local\manager\delayed_courses_manager; 28 | 29 | defined('MOODLE_INTERNAL') || die(); 30 | require_once(__DIR__ . '/../lib.php'); 31 | 32 | /** 33 | * Class which implements the basic methods necessary for a life cycle trigger subplugin 34 | * @package lifecycletrigger_delayedcourses 35 | * @copyright 2017 Tobias Reischmann WWU 36 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 | */ 38 | class delayedcourses extends base_automatic { 39 | 40 | 41 | /** 42 | * Returns triggertype of trigger: trigger, triggertime or exclude. 43 | * @param object $course DEPRECATED. 44 | * @param int $triggerid DEPRECATED 45 | * @return trigger_response 46 | */ 47 | public function check_course($course, $triggerid) { 48 | return trigger_response::exclude(); 49 | } 50 | 51 | /** 52 | * Return sql which excludes delayed courses. 53 | * @param int $triggerid Id of the trigger. 54 | * @return array A list containing the constructed sql fragment and an array of parameters. 55 | */ 56 | public function get_course_recordset_where($triggerid) { 57 | return delayed_courses_manager::get_course_delayed_wheresql(); 58 | } 59 | 60 | 61 | /** 62 | * The return value should be equivalent with the name of the subplugin folder. 63 | * @return string technical name of the subplugin 64 | */ 65 | public function get_subpluginname() { 66 | return 'delayedcourses'; 67 | } 68 | 69 | /** 70 | * Has only one instance and results in a preset workflow. 71 | * @return bool 72 | */ 73 | public function has_multiple_instances() { 74 | return false; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /trigger/delayedcourses/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Delayed Course Trigger 19 | * 20 | * @package lifecycletrigger_delayedcourses 21 | * @subpackage delayedcourses 22 | * @copyright 2025 Thomas Niedermaier Universität Münster 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | defined('MOODLE_INTERNAL') || die; 27 | 28 | $plugin->version = 2025040600; 29 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 30 | $plugin->supported = [401, 405]; 31 | $plugin->component = 'lifecycletrigger_delayedcourses'; 32 | $plugin->release = 'v4.5-r1'; 33 | $plugin->maturity = MATURITY_STABLE; 34 | -------------------------------------------------------------------------------- /trigger/manual/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace lifecycletrigger_manual\privacy; 18 | 19 | use core_privacy\local\metadata\null_provider; 20 | 21 | /** 22 | * Privacy subsystem implementation for lifecycletrigger_manual. 23 | * 24 | * @package lifecycletrigger_manual 25 | * @copyright 2022 ISB Bayern 26 | * @author Philipp Memmel 27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 | */ 29 | class provider implements null_provider { 30 | 31 | /** 32 | * Get the language string identifier with the component's language 33 | * file to explain why this plugin stores no data. 34 | * 35 | * @return string the reason 36 | */ 37 | public static function get_reason(): string { 38 | return 'privacy:metadata'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /trigger/manual/lang/de/lifecycletrigger_manual.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for manual trigger 19 | * 20 | * @package lifecycletrigger_manual 21 | * @copyright 2018 WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['plugindescription'] = 'Dieser Trigger erlaubt berechtigten Nicht-Administrator/innen diesen Workflow zu starten.'; 26 | $string['pluginname'] = 'Manueller Trigger'; 27 | $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; 28 | $string['setting_capability'] = 'Berechtigung'; 29 | $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.'; 30 | $string['setting_displayname'] = 'Aktionsname'; 31 | $string['setting_displayname_default'] = 'Benutzer-Freigabe'; 32 | $string['setting_displayname_help'] = 'Der Name für die Triggeraktion, der dem Nutzer angezeigt wird.'; 33 | $string['setting_icon'] = 'Icon'; 34 | $string['setting_icon_default'] = 'e/tick'; 35 | $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.'; 36 | -------------------------------------------------------------------------------- /trigger/manual/lang/en/lifecycletrigger_manual.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for manual trigger 19 | * 20 | * @package lifecycletrigger_manual 21 | * @copyright 2018 WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['plugindescription'] = 'Entitles authorized not-admins to initiate this workflow.'; 26 | $string['pluginname'] = 'Manual trigger'; 27 | $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; 28 | $string['setting_capability'] = 'Capability'; 29 | $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.'; 30 | $string['setting_displayname'] = 'Action name'; 31 | $string['setting_displayname_default'] = 'User Confirmation'; 32 | $string['setting_displayname_help'] = 'A name for the trigger action displayed to the user.'; 33 | $string['setting_icon'] = 'Icon'; 34 | $string['setting_icon_default'] = 'e/tick'; 35 | $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.'; 36 | -------------------------------------------------------------------------------- /trigger/manual/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Manual Trigger 19 | * 20 | * @package lifecycletrigger_manual 21 | * @copyright 2025 Thomas Niedermaier Universität Münster 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die; 26 | 27 | $plugin->version = 2025050400; 28 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 29 | $plugin->supported = [401, 405]; 30 | $plugin->component = 'lifecycletrigger_manual'; 31 | $plugin->release = 'v4.5-r1'; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /trigger/semindependent/.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | sudo: false 4 | 5 | cache: 6 | directories: 7 | - $HOME/.composer/cache 8 | 9 | php: 10 | - 7.2 11 | 12 | addons: 13 | postgresql: "9.5" 14 | 15 | services: 16 | - mysql 17 | 18 | matrix: 19 | allow_failures: 20 | - env: DB=pgsql MOODLE_BRANCH=master 21 | - env: DB=mysqli MOODLE_BRANCH=master 22 | fast_finish: true 23 | 24 | env: 25 | global: 26 | - IGNORE_PATHS=amd/build 27 | matrix: 28 | - DB=pgsql MOODLE_BRANCH=MOODLE_38_STABLE 29 | - DB=pgsql MOODLE_BRANCH=master 30 | - DB=mysqli MOODLE_BRANCH=MOODLE_38_STABLE 31 | - DB=mysqli MOODLE_BRANCH=master 32 | 33 | before_install: 34 | - phpenv config-rm xdebug.ini 35 | - nvm install 8.9.4 36 | - cd ../.. 37 | - composer selfupdate 38 | - composer create-project -n --no-dev --prefer-dist blackboard-open-source/moodle-plugin-ci ci ^2 39 | - export PATH="$(cd ci/bin; pwd):$(cd ci/vendor/bin; pwd):$PATH" 40 | 41 | install: 42 | - moodle-plugin-ci add-plugin --branch master learnweb/moodle-tool_lifecycle 43 | - moodle-plugin-ci install 44 | 45 | script: 46 | - moodle-plugin-ci phplint 47 | - moodle-plugin-ci phpcpd 48 | - moodle-plugin-ci phpmd 49 | - moodle-plugin-ci codechecker 50 | - moodle-plugin-ci validate 51 | - moodle-plugin-ci phpunit --coverage-clover 52 | - moodle-plugin-ci behat 53 | 54 | after_success: 55 | - bash <(curl -s https://codecov.io/bash) 56 | -------------------------------------------------------------------------------- /trigger/semindependent/README.md: -------------------------------------------------------------------------------- 1 | # moodle-lifecycletrigger_semindependent 2 | This is a trigger-Subplugin for the admin tool [moodle-tool_lifecycle](https://github.com/learnweb/moodle-tool_lifecycle). 3 | The basic setting at our institution is, that courses with a start date before the 1.1.2000 4 | are considered semester independent. All others are belonging to a specific semester such as winter semester 19/20. 5 | This plugin can be used to filter semester independent courses from courses that belong to a semester. 6 | ## Settings 7 | For each trigger instance it can be defined if semester independent courses should be included or excluded. 8 | 9 | For detailed information on trigger plugins visit the 10 | [Wiki](https://github.com/learnweb/moodle-tool_lifecycle/wiki) of the lifecycle admin tool. -------------------------------------------------------------------------------- /trigger/semindependent/lang/de/lifecycletrigger_semindependent.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for semester independent trigger 19 | * 20 | * @package lifecycletrigger_semindependent 21 | * @copyright 2025 Thomas Niedermaier University Münster 22 | * @copyright 2019 Tobias Reischmann WWU 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | $string['exclude'] = 'Exkludiere semesterunabhängige Kurse'; 27 | $string['exclude_help'] = 'Ist diese Option aktiviert werden semesterunabhängige Kurse ausgeschlossen, wenn nicht werden sie inkludiert.'; 28 | $string['plugindescription'] = 'Inkludiert oder exkludiert Kurse ohne Startdatum.'; 29 | $string['pluginname'] = 'Semesterunabhängige Kurse Trigger'; 30 | -------------------------------------------------------------------------------- /trigger/semindependent/lang/en/lifecycletrigger_semindependent.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for semester independent trigger 19 | * 20 | * @package lifecycletrigger_semindependent 21 | * @copyright 2025 Thomas Niedermaier University Münster 22 | * @copyright 2019 Tobias Reischmann WWU 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | $string['exclude'] = 'Exclude semester independent'; 27 | $string['exclude_help'] = 'If true, semester independent courses are excluded from workflow, 28 | otherwise they are included.'; 29 | $string['plugindescription'] = 'Include or exclude courses that have no start date.'; 30 | $string['pluginname'] = 'Semester independent trigger'; 31 | -------------------------------------------------------------------------------- /trigger/semindependent/tests/generator/lib.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | use tool_lifecycle\local\entity\trigger_subplugin; 18 | use tool_lifecycle\local\entity\workflow; 19 | use tool_lifecycle\local\manager\settings_manager; 20 | use tool_lifecycle\local\manager\trigger_manager; 21 | use tool_lifecycle\local\manager\workflow_manager; 22 | use tool_lifecycle\settings_type; 23 | 24 | /** 25 | * lifecycletrigger_semindependent generator tests 26 | * 27 | * @package lifecycletrigger_semindependent 28 | * @category test 29 | * @copyright 2025 Thomas Niedermaier University Münster 30 | * @copyright 2018 Tobias Reischmann WWU 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | class tool_lifecycle_trigger_semindependent_generator extends testing_module_generator { 34 | 35 | /** 36 | * Creates a trigger semindependent for an artificial workflow without steps. 37 | * @param bool $exclude 38 | * @return trigger_subplugin the semindependent trigger. 39 | * @throws dml_exception 40 | * @throws dml_transaction_exception 41 | * @throws moodle_exception 42 | */ 43 | public static function create_workflow_with_semindependent($exclude) { 44 | // Create Workflow. 45 | $record = new stdClass(); 46 | $record->id = null; 47 | $record->title = 'myworkflow'; 48 | $workflow = workflow::from_record($record); 49 | workflow_manager::insert_or_update($workflow); 50 | // Create trigger. 51 | $record = new stdClass(); 52 | $record->subpluginname = 'semindependent'; 53 | $record->instancename = 'semindependent'; 54 | $record->workflowid = $workflow->id; 55 | $trigger = trigger_subplugin::from_record($record); 56 | trigger_manager::insert_or_update($trigger); 57 | // Set exclude setting. 58 | $settings = new stdClass(); 59 | $settings->exclude = $exclude; 60 | settings_manager::save_settings($trigger->id, settings_type::TRIGGER, $trigger->subpluginname, $settings); 61 | 62 | return $trigger; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /trigger/semindependent/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Semester independent Trigger 19 | * 20 | * @package lifecycletrigger_semindependent 21 | * @subpackage semindependent 22 | * @copyright 2019 Tobias Reischmann WWU 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | defined('MOODLE_INTERNAL') || die; 27 | 28 | $plugin->version = 2025050400; 29 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 30 | $plugin->supported = [401, 405]; 31 | $plugin->component = 'lifecycletrigger_semindependent'; 32 | $plugin->dependencies = [ 33 | 'tool_lifecycle' => 2025050400, 34 | ]; 35 | $plugin->release = 'v4.5-r1'; 36 | $plugin->maturity = MATURITY_STABLE; 37 | -------------------------------------------------------------------------------- /trigger/sitecourse/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace lifecycletrigger_sitecourse\privacy; 18 | 19 | use core_privacy\local\metadata\null_provider; 20 | 21 | /** 22 | * Privacy subsystem implementation for lifecycletrigger_sitecourse. 23 | * 24 | * @package lifecycletrigger_sitecourse 25 | * @copyright 2022 ISB Bayern 26 | * @author Philipp Memmel 27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 | */ 29 | class provider implements null_provider { 30 | 31 | /** 32 | * Get the language string identifier with the component's language 33 | * file to explain why this plugin stores no data. 34 | * 35 | * @return string the reason 36 | */ 37 | public static function get_reason(): string { 38 | return 'privacy:metadata'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /trigger/sitecourse/lang/de/lifecycletrigger_sitecourse.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for site course trigger 19 | * 20 | * @package lifecycletrigger_sitecourse 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['delay'] = 'Dieser Trigger wird den Startseitenkurs ausschließen.'; 26 | $string['plugindescription'] = 'Schließt den Startseitenkurs von diesen Workflow aus.'; 27 | $string['pluginname'] = 'Startseitenkurs ausschließen - Trigger'; 28 | $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; 29 | 30 | -------------------------------------------------------------------------------- /trigger/sitecourse/lang/en/lifecycletrigger_sitecourse.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for site course trigger 19 | * 20 | * @package lifecycletrigger_sitecourse 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['delay'] = 'This module will exclude the site course from processing'; 26 | $string['plugindescription'] = 'Excludes the site course from this workflow.'; 27 | $string['pluginname'] = 'Exclude site course trigger'; 28 | $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; 29 | 30 | -------------------------------------------------------------------------------- /trigger/sitecourse/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Site Course Trigger 19 | * 20 | * @package lifecycletrigger_sitecourse 21 | * @copyright 2025 Thomas Niedermaier Universität Münster 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die; 26 | 27 | $plugin->version = 2025040600; 28 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 29 | $plugin->supported = [401, 405]; 30 | $plugin->component = 'lifecycletrigger_sitecourse'; 31 | $plugin->release = 'v4.5-r1'; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /trigger/specificdate/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace lifecycletrigger_specificdate\privacy; 18 | 19 | use core_privacy\local\metadata\null_provider; 20 | 21 | /** 22 | * Privacy subsystem implementation for lifecycletrigger_specificdate. 23 | * 24 | * @package lifecycletrigger_specificdate 25 | * @copyright 2022 ISB Bayern 26 | * @author Philipp Memmel 27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 | */ 29 | class provider implements null_provider { 30 | 31 | /** 32 | * Get the language string identifier with the component's language 33 | * file to explain why this plugin stores no data. 34 | * 35 | * @return string the reason 36 | */ 37 | public static function get_reason(): string { 38 | return 'privacy:metadata'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /trigger/specificdate/lang/de/lifecycletrigger_specificdate.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for specific date trigger 19 | * 20 | * @package lifecycletrigger_specificdate 21 | * @copyright 2018 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['dates'] = 'Daten, an denen der Workflow ausgeführt werden soll.'; 26 | $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.'; 27 | $string['dates_not_parseable'] = 'Daten müssen in dem Format Tag.Monat sein!'; 28 | $string['plugindescription'] = 'Definiert Zeiträume, in denen dieser Workflow ausgeführt werden soll.'; 29 | $string['pluginname'] = 'Bestimmtes Datum - Trigger'; 30 | $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; 31 | $string['timelastrun'] = 'Datum, an dem der Trigger zuletzt ausgeführt wurde.'; 32 | $string['timelastrunactive'] = 'Nur einmal pro Tag'; 33 | -------------------------------------------------------------------------------- /trigger/specificdate/lang/en/lifecycletrigger_specificdate.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for specific date trigger 19 | * 20 | * @package lifecycletrigger_specificdate 21 | * @copyright 2018 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['dates'] = 'Dates at which the workflow should run.'; 26 | $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.'; 27 | $string['dates_not_parseable'] = 'Dates must be of the format Day.Month'; 28 | $string['plugindescription'] = 'Defines time slots at which this workflow should run.'; 29 | $string['pluginname'] = 'Specific date trigger'; 30 | $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; 31 | $string['timelastrun'] = 'Date when the trigger last run.'; 32 | $string['timelastrunactive'] = 'Only once a day'; 33 | -------------------------------------------------------------------------------- /trigger/specificdate/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Specific Date Trigger 19 | * 20 | * @package lifecycletrigger_specificdate 21 | * @copyright 2025 Thomas Niedermaier Universität Münster 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die; 26 | 27 | $plugin->version = 2025050400; 28 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 29 | $plugin->supported = [401, 405]; 30 | $plugin->component = 'lifecycletrigger_specificdate'; 31 | $plugin->release = 'v4.5-r1'; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /trigger/startdatedelay/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace lifecycletrigger_startdatedelay\privacy; 18 | 19 | use core_privacy\local\metadata\null_provider; 20 | 21 | /** 22 | * Privacy subsystem implementation for lifecycletrigger_startdatedelay. 23 | * 24 | * @package lifecycletrigger_startdatedelay 25 | * @copyright 2022 ISB Bayern 26 | * @author Philipp Memmel 27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 | */ 29 | class provider implements null_provider { 30 | 31 | /** 32 | * Get the language string identifier with the component's language 33 | * file to explain why this plugin stores no data. 34 | * 35 | * @return string the reason 36 | */ 37 | public static function get_reason(): string { 38 | return 'privacy:metadata'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /trigger/startdatedelay/lang/de/lifecycletrigger_startdatedelay.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for start date delay trigger 19 | * 20 | * @package lifecycletrigger_startdatedelay 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['delay'] = 'Zeit seit Kursstartdatum, bis ein Prozess gestartet wird'; 26 | $string['delay_help'] = 'Dieser Trigger wird ausgeführt, sobald die Zeit, die seit dem Start des Kurses vergangen ist, größer ist als der angegebene Zeitraum.'; 27 | $string['plugindescription'] = 'Trigger des Lifecycle-Tools, der bestimmt, wieviel Zeit nach dem Startdatum des Kurses verstreichen muss ehe dieser Workflow startet.'; 28 | $string['pluginname'] = 'Startdatumsabstand - Trigger'; 29 | $string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; 30 | 31 | -------------------------------------------------------------------------------- /trigger/startdatedelay/lang/en/lifecycletrigger_startdatedelay.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Lang strings for start date delay trigger 19 | * 20 | * @package lifecycletrigger_startdatedelay 21 | * @copyright 2017 Tobias Reischmann WWU 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['delay'] = 'Delay from start of course until starting a process'; 26 | $string['delay_help'] = 'The trigger will be invoked if the time passed since the course has started is longer than this delay.'; 27 | $string['plugindescription'] = 'Defines the time that has to pass after the course start date has been reached before this workflow starts.'; 28 | $string['pluginname'] = 'Start date delay trigger'; 29 | $string['privacy:metadata'] = 'This subplugin does not store any personal data.'; 30 | 31 | -------------------------------------------------------------------------------- /trigger/startdatedelay/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Life Cycle Startdate Trigger 19 | * 20 | * @package lifecycletrigger_startdatedelay 21 | * @copyright 2025 Thomas Niedermaier Universität Münster 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die; 26 | 27 | $plugin->version = 2025050400; 28 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 29 | $plugin->supported = [401, 405]; 30 | $plugin->component = 'lifecycletrigger_startdatedelay'; 31 | $plugin->release = 'v4.5-r1'; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Version details. 19 | * 20 | * @package tool_lifecycle 21 | * @copyright 2025 Thomas Niedermaier University Münster 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die; 26 | 27 | $plugin->maturity = MATURITY_STABLE; 28 | $plugin->version = 2025050403; 29 | $plugin->component = 'tool_lifecycle'; 30 | $plugin->requires = 2022112800; // Requires Moodle 4.1+. 31 | $plugin->supported = [401, 405]; 32 | $plugin->release = 'v4.5-r4'; 33 | --------------------------------------------------------------------------------