diff --git a/classes/plugininfo/trigger.php b/classes/plugininfo/trigger.php new file mode 100644 index 0000000..9f30fd3 --- /dev/null +++ b/classes/plugininfo/trigger.php @@ -0,0 +1,59 @@ +. + +/** + * Subplugin info class. + * + * @package tool_trigger + * @author David Castro + * @copyright 2024 Moodle US + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace tool_trigger\plugininfo; + +use core\plugininfo\base, moodle_url, part_of_admin_tree, admin_settingpage; + +/** + * Plugin info class for logging store plugins. + */ +class trigger extends base { + + /** + * Loads plugin settings to the settings tree. + * + * This function usually includes settings.php file in plugins folder. + * Alternatively it can create a link to some settings page (instance of admin_externalpage) + * + * @param \part_of_admin_tree $adminroot + * @param string $parentnodename + * @param bool $hassiteconfig whether the current user has moodle/site:config capability + */ + public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { + global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + $ADMIN = $adminroot; // May be used in settings.php. + $plugininfo = $this; // Also can be used inside settings.php. + + if (!$this->is_installed_and_upgraded()) { + return; + } + + if (!$hassiteconfig or !file_exists($this->full_path('settings.php'))) { + return; + } + + include($this->full_path('settings.php')); + } +} diff --git a/classes/steps/lookups/course_lookup_step.php b/classes/steps/lookups/course_lookup_step.php index 1b3f324..ec6cfb0 100644 --- a/classes/steps/lookups/course_lookup_step.php +++ b/classes/steps/lookups/course_lookup_step.php @@ -125,6 +125,17 @@ public function execute($step, $trigger, $event, $stepresults) { foreach ($coursedata as $key => $value) { $stepresults[$this->outputprefix . $key] = $value; } + + $handler = \core_customfield\handler::get_handler('core_course', 'course'); + $datas = $handler->get_instance_data($courseid); + foreach ($datas as $data) { + if (empty($data->get_value())) { + continue; + } + $key = $data->get_field()->get('shortname'); + $stepresults[$this->outputprefix . $key] = $data->get_value(); + } + return [true, $stepresults]; } @@ -175,7 +186,12 @@ public static function get_privacyfields() { * @return array $stepfields The fields this step provides. */ public static function get_fields() { - return self::$stepfields; + $handler = \core_customfield\handler::get_handler('core_course', 'course'); + $customfields = []; + foreach ($handler->get_fields() as $field) { + $customfields[] = $field->get('shortname'); + } + return array_merge(self::$stepfields, $customfields); } } diff --git a/classes/workflow_manager.php b/classes/workflow_manager.php index 69dd2fb..8f7fff7 100644 --- a/classes/workflow_manager.php +++ b/classes/workflow_manager.php @@ -226,16 +226,39 @@ public function get_step_class_names($steptype = null) { $matchedsteps = array(); $matches = array(); - foreach ($steptypes as $steptype) { - $stepdir = __DIR__ . '/steps/' . $steptype; - $handle = opendir($stepdir); - while (($file = readdir($handle)) !== false) { - preg_match('/\b(?!base)(.*step)/', $file, $matches); - foreach ($matches as $classname) { - $matchedsteps[] = '\tool_trigger\steps\\' . $steptype . '\\' . $classname; + $plugins = \core_component::get_plugin_list('trigger'); + + $dirs = [ + (object)[ + 'path' => __DIR__, + 'namespace' => 'tool_trigger', + ] + ]; + foreach ($plugins as $plugin => $dir) { + if (!PHPUNIT_TEST && $plugin == 'testplugin') { + continue; + } + $dirs[] = (object)[ + 'path' => $dir . '/classes', + 'namespace' => "trigger_$plugin", + ]; + } + + foreach ($dirs as $dir) { + foreach ($steptypes as $steptype) { + $stepdir = $dir->path . '/steps/' . $steptype; + if (!is_dir($stepdir)) { + continue; + } + $handle = opendir($stepdir); + while (($file = readdir($handle)) !== false) { + preg_match('/\b(?!base)(.*step)/', $file, $matches); + foreach ($matches as $classname) { + $matchedsteps[] = '\\' . $dir->namespace . '\steps\\' . $steptype . '\\' . $classname; + } } + closedir($handle); } - closedir($handle); } $matchedsteps = array_unique($matchedsteps); diff --git a/custom/.gitkeep b/custom/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom/testplugin/classes/steps/lookups/subplugin_lookup_test_step.php b/custom/testplugin/classes/steps/lookups/subplugin_lookup_test_step.php new file mode 100644 index 0000000..39b5784 --- /dev/null +++ b/custom/testplugin/classes/steps/lookups/subplugin_lookup_test_step.php @@ -0,0 +1,91 @@ +. + +namespace trigger_testplugin\steps\lookups; +use tool_trigger\steps\lookups\base_lookup_step; + +/** + * A lookup step for testing purposes. + * + * @package trigger_testplugin + * @copyright 2025 Moodle US + * @author Oscar Nadjar + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class subplugin_lookup_test_step extends base_lookup_step { + + /** + * The fields supplied by this step. + * A string containing all the cohorts a user is assigned to. + * + * @var array + */ + private static $stepfields = array( + 'testlookupresult' + ); + + protected function init() { + } + + /** + * {@inheritDoc} + * @see \tool_trigger\steps\base\base_step::execute() + */ + public function execute($step, $trigger, $event, $stepresults) { + global $DB; + $stepresults = [ 'testlookupresult' => 'test' ]; + return [true, $stepresults]; + } + + /** + * {@inheritDoc} + * @see \tool_trigger\steps\base\base_step::form_definition_extra() + */ + public function form_definition_extra($form, $mform, $customdata) { + } + + /** + * {@inheritDoc} + * @see \tool_trigger\steps\base\base_step::get_step_desc() + */ + public static function get_step_desc() { + return get_string('subplugin_lookup_test_step_desc', 'trigger_testplugin'); + } + + /** + * {@inheritDoc} + * @see \tool_trigger\steps\base\base_step::get_step_name() + */ + public static function get_step_name() { + return get_string('subplugin_lookup_test_step_name', 'trigger_testplugin'); + } + + /** + * {@inheritDoc} + * @see \tool_trigger\steps\base\base_step::get_privacyfields() + */ + public static function get_privacyfields() { + } + + /** + * Get a list of fields this step provides. + * + * @return array $stepfields The fields this step provides. + */ + public static function get_fields() { + return self::$stepfields; + } +} diff --git a/custom/testplugin/lang/en/trigger_testplugin.php b/custom/testplugin/lang/en/trigger_testplugin.php new file mode 100755 index 0000000..a3cf314 --- /dev/null +++ b/custom/testplugin/lang/en/trigger_testplugin.php @@ -0,0 +1,31 @@ +. + +/** + * Language file for trigger_testplugin. + * + * @package trigger_testplugin + * @copyright 2025 Moodle US + * @author Oscar Nadjar + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$string['pluginname'] = 'Test Trigger Subplugin'; +$string['pluginname_help'] = 'This plugin is used for testing the subplugin functionality of the Tool Trigger plugin.'; +$string['subplugin_lookup_test_step_desc'] = 'This is a test subplugin step for the Tool Trigger plugin. It is used to test the functionality of the subplugin system.'; +$string['subplugin_lookup_test_step_name'] = 'Test Subplugin Step'; diff --git a/custom/testplugin/version.php b/custom/testplugin/version.php new file mode 100755 index 0000000..84c2021 --- /dev/null +++ b/custom/testplugin/version.php @@ -0,0 +1,33 @@ +. + +/** + * Plugin version and other meta-data are defined here. + * + * @package trigger_testplugin + * @copyright 2025 Moodle US + * @author Oscar Nadjar + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->component = 'trigger_testplugin'; +$plugin->version = 2025042200; +$plugin->requires = 2021051701; +$plugin->supported = [404, 405]; +$plugin->maturity = MATURITY_STABLE; +$plugin->release = '1.0.0'; diff --git a/db/subplugins.json b/db/subplugins.json new file mode 100644 index 0000000..f0b3302 --- /dev/null +++ b/db/subplugins.json @@ -0,0 +1,5 @@ +{ + "plugintypes": { + "trigger": "admin\/tool\/trigger\/custom" + } +} \ No newline at end of file diff --git a/settings.php b/settings.php index 4aaf60d..c11264e 100644 --- a/settings.php +++ b/settings.php @@ -91,5 +91,9 @@ $ADMIN->add('tool_trigger', $settings); $ADMIN->add('tool_trigger', $workflowsettings); + foreach (core_plugin_manager::instance()->get_plugins_of_type('trigger') as $plugin) { + $plugin->load_settings($ADMIN, 'trigger', $hassiteconfig); + } + $settings = null; } diff --git a/tests/course_lookup_step_test.php b/tests/course_lookup_step_test.php index ac21c1c..b8ee165 100644 --- a/tests/course_lookup_step_test.php +++ b/tests/course_lookup_step_test.php @@ -90,6 +90,35 @@ public function test_execute_basic() { $this->assertEquals($context->id, $stepresults['course_contextid']); } + /** + * Basic test, but this time with additional custom course field. + */ + public function test_execute_basic_with_custom_profile_fields() { + // Create custom course field. + $customfieldg = $this->getDataGenerator()->get_plugin_generator('core_customfield'); + $category = $customfieldg->create_category(); + $customfield = $customfieldg->create_field([ + 'categoryid' => $category->get('id'), + 'type' => 'text', + 'shortname' => 'testfield1', + 'configdata' => [], + ]); + + // Add data to the customfield_data table. + $this->add_course_custom_course_field_data($customfield->get('id'), $this->course->id, 'CourseFieldValue'); + $step = new \tool_trigger\steps\lookups\course_lookup_step( + json_encode([ + 'courseidfield' => 'objectid', + 'outputprefix' => 'course_' + ]) + ); + + list($status, $stepresults) = $step->execute(null, null, $this->event, []); + $this->assertTrue($status); + // Check that the custom field data is returned as a step result. + $this->assertEquals('CourseFieldValue', $stepresults['course_testfield1']); + } + /** * Test for exception if an invalid field name is entered. */ @@ -222,4 +251,22 @@ public function test_execute_course_id_string() { $this->assertEquals($this->course->fullname, $stepresults['course_fullname']); $this->assertEquals($context->id, $stepresults['course_contextid']); } + + public function add_course_custom_course_field_data($fieldid, $courseid, $customfielddata) { + global $DB; + + // Add data to the customfield_data table. + $data = new \stdClass(); + $data->fieldid = $fieldid; + $data->instanceid = $courseid; + $data->value = $customfielddata; + $data->charvalue = $customfielddata; + $data->timecreated = time(); + $data->timemodified = time(); + $data->valueformat = 0; + $data->valuetrust = 0; + $data->contextid = \context_course::instance($courseid)->id; + + return $DB->insert_record('customfield_data', $data); + } } diff --git a/tests/subplugin_step_test.php b/tests/subplugin_step_test.php new file mode 100644 index 0000000..caf308a --- /dev/null +++ b/tests/subplugin_step_test.php @@ -0,0 +1,78 @@ +. + +/** + * "Fail" filter step's unit tests. + * + * @package tool_trigger + * @author Aaron Wells + * @copyright Catalyst IT 2018 + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_trigger; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; + +class subplugin_step_test extends \advanced_testcase { + + /** + * Test user. + * @var + */ + protected $user; + + /** + * Test event. + * @var + */ + protected $event; + + /** + * Create an event to use for testing. + */ + public function setup():void { + + // Create a user event. + $this->user = \core_user::get_user_by_username('admin'); + $this->event = \core\event\user_profile_viewed::create([ + 'objectid' => $this->user->id, + 'relateduserid' => $this->user->id, + 'context' => \context_user::instance($this->user->id), + 'other' => [ + 'courseid' => 1, + 'courseshortname' => 'short name', + 'coursefullname' => 'full name' + ] + ]); + } + + /** + * Basic use-case, with default values for settings. Find the + * user identified at "userid", and add their data with the + * prefix "user_". + */ + public function test_execute_basic() { + $step = new \trigger_testplugin\steps\lookups\subplugin_lookup_test_step(json_encode([])); + + list($status, $stepresults) = $step->execute(null, null, $this->event, []); + + $this->assertTrue($status); + $this->assertEquals('test', $stepresults['testlookupresult']); + } +} diff --git a/tests/workflow_manager_test.php b/tests/workflow_manager_test.php index 491652a..884b9fa 100644 --- a/tests/workflow_manager_test.php +++ b/tests/workflow_manager_test.php @@ -79,6 +79,20 @@ public function test_get_steps_by_type() { ); } + /** + * Test getting step from custom plugin. + */ + public function test_custom_step_names() { + + $stepclasses = ['\trigger_testplugin\steps\lookups\subplugin_lookup_test_step']; + $stepobj = new \tool_trigger\workflow_manager(); + $steps = $stepobj->lookup_step_names($stepclasses); + $this->assertEquals( + get_string('subplugin_lookup_test_step_name', 'trigger_testplugin'), + $steps['\trigger_testplugin\steps\lookups\subplugin_lookup_test_step'] + ); + } + /** * Test the code for validating the name of a step class and instantiating it. *