diff --git a/README.md b/README.md index ae9ea96..7a58b43 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,9 @@ Rules can be processed by two mechanisms: ### Disabling realtime processing (processing on event) -There is a global admin setting that allows administrator to enable or disable realtime rule processing. This may be useful if processing taking too long and blocking the user interface. +Each rule can be configured to be processed realtime (if any of the related conditions support processing on event). + +There is also a global admin setting that allows administrator to enable or disable realtime rule processing globally overriding per rule configuration. # Configuration diff --git a/classes/observer.php b/classes/observer.php index 84e6b6f..7748cf8 100644 --- a/classes/observer.php +++ b/classes/observer.php @@ -37,7 +37,9 @@ public static function process_event(base $event): void { if (get_config('tool_dynamic_cohorts', 'realtime')) { foreach (condition_manager::get_conditions_with_event($event) as $condition) { foreach (rule_manager::get_rules_with_condition($condition) as $rule) { - rule_manager::process_rule($rule, self::get_userid_from_event($event)); + if ($rule->is_realtime()) { + rule_manager::process_rule($rule, self::get_userid_from_event($event)); + } } } } diff --git a/classes/reportbuilder/local/entities/rule_entity.php b/classes/reportbuilder/local/entities/rule_entity.php index 9cf60ef..a9fa6f6 100644 --- a/classes/reportbuilder/local/entities/rule_entity.php +++ b/classes/reportbuilder/local/entities/rule_entity.php @@ -67,6 +67,7 @@ public function initialise(): base { */ protected function get_all_columns(): array { $alias = $this->get_table_alias('tool_dynamic_cohorts'); + $globalrealtime = get_config('tool_dynamic_cohorts', 'realtime'); $columns[] = (new column( 'id', @@ -117,6 +118,30 @@ protected function get_all_columns(): array { return !empty($rule->is_bulk_processing()) ? get_string('yes') : get_string('no'); }); + $columns[] = (new column( + 'realtime', + new lang_string('rule_entity.realtime', 'tool_dynamic_cohorts'), + $this->get_entity_name() + )) + ->add_joins($this->get_joins()) + ->set_type(column::TYPE_TEXT) + ->add_field("{$alias}.realtime") + ->add_fields("{$alias}.id, {$alias}.name, {$alias}.realtime") + ->set_is_sortable(true) + ->add_callback(function ($value, $row) use ($globalrealtime) { + global $OUTPUT; + + $rule = new rule(0, $row); + $rulerealtime = $rule->is_realtime(); + $string = !empty($rulerealtime) ? get_string('yes') : get_string('no'); + + if (!empty($rulerealtime) && !$globalrealtime) { + $string .= $OUTPUT->pix_icon('i/warning', get_string('realtimedisabledglobally', 'tool_dynamic_cohorts')); + } + + return $string; + }); + $columns[] = (new column( 'status', new lang_string('rule_entity.status', 'tool_dynamic_cohorts'), diff --git a/classes/reportbuilder/local/systemreports/rules.php b/classes/reportbuilder/local/systemreports/rules.php index c415ca1..572b5c2 100644 --- a/classes/reportbuilder/local/systemreports/rules.php +++ b/classes/reportbuilder/local/systemreports/rules.php @@ -81,6 +81,7 @@ protected function initialise(): void { }); $this->add_column_from_entity('rule_entity:bulkprocessing'); + $this->add_column_from_entity('rule_entity:realtime'); $this->add_column(new column( 'conditions', diff --git a/classes/rule.php b/classes/rule.php index 31ed4ea..d4f4466 100644 --- a/classes/rule.php +++ b/classes/rule.php @@ -69,6 +69,10 @@ protected static function define_properties() { 'type' => PARAM_INT, 'default' => 0, ], + 'realtime' => [ + 'type' => PARAM_INT, + 'default' => 1, + ], ]; } @@ -110,6 +114,14 @@ public function is_bulk_processing(): bool { return (bool) $this->get('bulkprocessing'); } + /** + * Check if this rule should process realtime. + * @return bool + */ + public function is_realtime(): bool { + return (bool) $this->get('realtime'); + } + /** * Return if the rule is broken. * diff --git a/classes/rule_form.php b/classes/rule_form.php index d7651a2..aedbdf1 100644 --- a/classes/rule_form.php +++ b/classes/rule_form.php @@ -37,6 +37,8 @@ class rule_form extends \moodleform { * Form definition. */ protected function definition() { + global $OUTPUT; + $mform = $this->_form; $mform->addElement('hidden', 'id'); @@ -99,6 +101,26 @@ protected function definition() { ); $mform->addHelpButton('bulkprocessing', 'bulkprocessing', 'tool_dynamic_cohorts'); + $mform->addElement( + 'advcheckbox', + 'realtime', + get_string('realtime', 'tool_dynamic_cohorts'), + get_string('enable'), + [], + [0, 1] + ); + $mform->addHelpButton('realtime', 'realtime', 'tool_dynamic_cohorts'); + + if (!get_config('tool_dynamic_cohorts', 'realtime')) { + $mform->freeze(['realtime']); + $realtimeglobal = $OUTPUT->notification( + get_string('realtimedisabledglobally', 'tool_dynamic_cohorts'), + 'warning', + false + ); + $mform->addElement('static', 'realtimeglobal', '', $realtimeglobal); + } + $mform->addElement('select', 'operator', get_string('logical_operator', 'tool_dynamic_cohorts'), diff --git a/classes/rule_manager.php b/classes/rule_manager.php index 201321c..8e41bd7 100644 --- a/classes/rule_manager.php +++ b/classes/rule_manager.php @@ -132,6 +132,7 @@ public static function process_form(\stdClass $formdata): rule { 'description' => $formdata->description, 'bulkprocessing' => $formdata->bulkprocessing, 'operator' => $formdata->operator, + 'realtime' => $formdata->realtime, ]; $oldcohortid = 0; diff --git a/db/install.xml b/db/install.xml index aa7e2b9..8881901 100644 --- a/db/install.xml +++ b/db/install.xml @@ -1,5 +1,5 @@ - @@ -14,6 +14,7 @@ + diff --git a/db/upgrade.php b/db/upgrade.php index e78e999..104ac58 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -44,5 +44,20 @@ function xmldb_tool_dynamic_cohorts_upgrade($oldversion): bool { upgrade_plugin_savepoint(true, 2024032501, 'tool', 'dynamic_cohorts'); } + if ($oldversion < 2024051004) { + + // Define field realtime to be added to tool_dynamic_cohorts. + $table = new xmldb_table('tool_dynamic_cohorts'); + $field = new xmldb_field('realtime', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'operator'); + + // Conditionally launch add field realtime. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Dynamic_cohorts savepoint reached. + upgrade_plugin_savepoint(true, 2024051004, 'tool', 'dynamic_cohorts'); + } + return true; } diff --git a/index.php b/index.php index 606c418..2e6730d 100644 --- a/index.php +++ b/index.php @@ -40,6 +40,11 @@ notification::warning(get_string('brokenruleswarning', 'tool_dynamic_cohorts')); break; } + + if ($rule->is_realtime() && !get_config('tool_dynamic_cohorts', 'realtime')) { + notification::warning(get_string('realtimedisabledglobally', 'tool_dynamic_cohorts')); + break; + } } $report = system_report_factory::create(rules::class, context_system::instance(), 'tool_dynamic_cohorts'); diff --git a/lang/en/tool_dynamic_cohorts.php b/lang/en/tool_dynamic_cohorts.php index 600c09c..acf67d4 100644 --- a/lang/en/tool_dynamic_cohorts.php +++ b/lang/en/tool_dynamic_cohorts.php @@ -150,7 +150,7 @@ $string['settings:realtime'] = 'Real time processing'; $string['settings:realtime_desc'] = 'When enabled, rules with conditions that support triggering on the event will be processed synchronously as part of the event. Use caution when enabling as long running rule processing will block the user interface.'; $string['settings:releasemembers'] = 'Release members'; -$string['settings:releasemembers_desc'] = 'If enabled all members will be removed from a cohort once it\'s not managed by the plugin (e.g a rule is deleted or cohort for a rule is changed).
Please note: no cohort_member_removed events will be triggered when members are released from a cohort.'; +$string['settings:releasemembers_desc'] = 'If enabled all members will be removed from a cohort once it\'s not managed by the plugin (e.g a rule is deleted or cohort for a rule is changed).
Please note: no cohort_member_removed events will be triggered when members are released from a cohort. Otherwise, the rule will be processed via cron.'; $string['usercreated'] = 'User was created'; $string['usercreatedin'] = 'Users who were created in the last {$a}'; $string['usercreatedtime'] = 'Users who were created {$a->operator} {$a->time}'; @@ -158,3 +158,7 @@ $string['userlastlogin'] = 'User\'s last login'; $string['haverole'] = 'have role'; $string['donothaverole'] = 'do not have role'; +$string['realtime'] = 'Real time processing'; +$string['realtime_help'] = 'If enabled, the rule will be processed synchronously as part of the event (if conditions support triggering on the event). Use caution when enabling as long running rule processing will block the user interface.'; +$string['rule_entity.realtime'] = 'Realtime processing'; +$string['realtimedisabledglobally'] = 'Realtime processing disabled globally'; diff --git a/tests/observer_test.php b/tests/observer_test.php index 81b159b..c5edef2 100644 --- a/tests/observer_test.php +++ b/tests/observer_test.php @@ -51,7 +51,7 @@ public function setUp(): void { public function test_user_creation_triggers_rule_processing() { global $DB; - $rule = new rule(0, (object)['name' => 'Test rule 1', 'enabled' => 1, 'cohortid' => $this->cohort->id]); + $rule = new rule(0, (object)['name' => 'Test rule 1', 'enabled' => 1, 'cohortid' => $this->cohort->id, 'realtime' => 1]); $rule->save(); $condition = condition_base::get_instance(0, (object)[ @@ -87,7 +87,7 @@ public function test_user_updating_triggers_rule_processing() { $user1 = $this->getDataGenerator()->create_user(['username' => 'user1']); $user2 = $this->getDataGenerator()->create_user(['username' => 'user2']); - $rule = new rule(0, (object)['name' => 'Test rule 1', 'enabled' => 1, 'cohortid' => $this->cohort->id]); + $rule = new rule(0, (object)['name' => 'Test rule 1', 'enabled' => 1, 'cohortid' => $this->cohort->id, 'realtime' => 1]); $rule->save(); $condition = condition_base::get_instance(0, (object)[ @@ -123,7 +123,42 @@ public function test_realtime_rule_processing_when_disabled_globally() { set_config('realtime', 0, 'tool_dynamic_cohorts'); - $rule = new rule(0, (object)['name' => 'Test rule 1', 'enabled' => 1, 'cohortid' => $this->cohort->id]); + $rule = new rule(0, (object)['name' => 'Test rule 1', 'enabled' => 1, 'cohortid' => $this->cohort->id, 'realtime' => 1]); + $rule->save(); + + $condition = condition_base::get_instance(0, (object)[ + 'classname' => 'tool_dynamic_cohorts\local\tool_dynamic_cohorts\condition\user_profile', + ]); + + // Condition username starts with user to catch both users. + $condition->set_config_data([ + 'profilefield' => 'username', + 'username_operator' => user_profile::TEXT_STARTS_WITH, + 'username_value' => 'user', + ]); + + $record = $condition->get_record(); + $record->set('ruleid', $rule->get('id')); + $record->set('sortorder', 0); + $record->save(); + + $this->assertEquals(0, $DB->count_records('cohort_members', ['cohortid' => $this->cohort->id])); + + $this->getDataGenerator()->create_user(['username' => 'user1']); + $this->getDataGenerator()->create_user(['username' => 'user2']); + + $this->assertEquals(0, $DB->count_records('cohort_members', ['cohortid' => $this->cohort->id])); + } + + /** + * Test that user creation event doesn't trigger rule processing for that user if realtime processing is disabled for the rule. + */ + public function test_realtime_rule_processing_when_disabled_for_a_rule() { + global $DB; + + set_config('realtime', 1, 'tool_dynamic_cohorts'); + + $rule = new rule(0, (object)['name' => 'Test rule 1', 'enabled' => 1, 'realtime' => 0, 'cohortid' => $this->cohort->id]); $rule->save(); $condition = condition_base::get_instance(0, (object)[ diff --git a/tests/rule_manager_test.php b/tests/rule_manager_test.php index e837484..e425607 100644 --- a/tests/rule_manager_test.php +++ b/tests/rule_manager_test.php @@ -121,6 +121,7 @@ public function test_build_rule_data_for_form() { 'bulkprocessing' => 0, 'broken' => 0, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND, + 'realtime' => 1, 'id' => 0, 'timecreated' => 0, 'timemodified' => 0, @@ -149,6 +150,7 @@ public static function process_rule_form_with_invalid_data_provider(): array { [['name' => 'Test', 'enabled' => 1, 'description' => '', 'conditionjson' => '']], [['name' => 'Test', 'enabled' => 1, 'cohortid' => 1, 'conditionjson' => '']], [['name' => 'Test', 'enabled' => 1, 'cohortid' => 1, 'description' => '']], + [['name' => 'Test', 'enabled' => 1, 'cohortid' => 1, 'description' => '', 'conditionjson' => '']], ]; } @@ -179,7 +181,7 @@ public function test_process_rule_form_new_rule() { $cohort3 = $this->getDataGenerator()->create_cohort(); $formdata = ['name' => 'Test', 'cohortid' => $cohort1->id, 'description' => '', - 'conditionjson' => '', 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'conditionjson' => '', 'bulkprocessing' => 1, 'realtime' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; $rule = rule_manager::process_form((object)$formdata); $this->assertEquals(1, $DB->count_records(rule::TABLE)); @@ -191,7 +193,7 @@ public function test_process_rule_form_new_rule() { } $formdata = ['name' => 'Test', 'cohortid' => $cohort2->id, 'description' => '', - 'conditionjson' => '', 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'conditionjson' => '', 'bulkprocessing' => 1, 'realtime' => 0, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; $rule = rule_manager::process_form((object)$formdata); $this->assertEquals(2, $DB->count_records(rule::TABLE)); @@ -203,7 +205,7 @@ public function test_process_rule_form_new_rule() { $cohort = $this->getDataGenerator()->create_cohort(); $formdata = ['name' => 'Test1', 'cohortid' => $cohort3->id, 'description' => '', - 'conditionjson' => '', 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'conditionjson' => '', 'bulkprocessing' => 0, 'realtime' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; $rule = rule_manager::process_form((object)$formdata); $this->assertEquals(3, $DB->count_records(rule::TABLE)); @@ -236,7 +238,7 @@ public function test_process_rule_form_existing_rule() { $cohort = $this->getDataGenerator()->create_cohort(); $formdata = ['id' => $rule->get('id'), 'name' => 'Test1', 'cohortid' => $cohort->id, - 'description' => 'D', 'conditionjson' => '', 'bulkprocessing' => 1, + 'description' => 'D', 'conditionjson' => '', 'bulkprocessing' => 1, 'realtime' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; $rule = rule_manager::process_form((object)$formdata); $this->assertEquals(1, $DB->count_records(rule::TABLE)); @@ -256,7 +258,7 @@ public function test_process_rule_form_with_not_existing_cohort() { $this->expectExceptionMessage('Invalid rule data. Cohort is invalid: 999'); $formdata = ['name' => 'Test', 'cohortid' => 999, 'description' => '', 'conditionjson' => '', - 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'bulkprocessing' => 1, 'realtime' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; rule_manager::process_form((object)$formdata); } @@ -271,7 +273,7 @@ public function test_process_rule_form_with_cohort_managed_by_other_component() $this->expectExceptionMessage('Invalid rule data. Cohort is invalid: ' . $cohort->id); $formdata = ['name' => 'Test', 'cohortid' => $cohort->id, 'description' => '', - 'conditionjson' => '', 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'conditionjson' => '', 'bulkprocessing' => 1, 'realtime' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; rule_manager::process_form((object)$formdata); } @@ -288,13 +290,13 @@ public function test_process_rule_form_with_cohort_managed_by_another_rule() { $this->expectExceptionMessage('Cohort ' . $cohort->id . ' is already managed by tool_dynamic_cohorts'); $formdata = ['name' => 'Test1', 'cohortid' => $cohort->id, 'description' => 'D', 'conditionjson' => '', - 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'bulkprocessing' => 1, 'realtime' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; rule_manager::process_form((object)$formdata); $this->assertEquals('tool_dynamic_cohorts', $DB->get_field('cohort', 'component', ['id' => $cohort->id])); // Trying to make a new rule with a cohort that is already taken. Should throw exception. $formdata = ['name' => 'Test2', 'cohortid' => $cohort->id, 'description' => 'D', - 'conditionjson' => '', 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'conditionjson' => '', 'bulkprocessing' => 1, 'realtime' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; rule_manager::process_form((object)$formdata); } @@ -309,14 +311,14 @@ public function test_process_rule_form_update_rule_form_keeping_cohort() { $cohort = $this->getDataGenerator()->create_cohort(); $formdata = ['name' => 'Test1', 'cohortid' => $cohort->id, 'description' => 'D', - 'conditionjson' => '', 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'conditionjson' => '', 'bulkprocessing' => 1, 'realtime' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; $rule = rule_manager::process_form((object)$formdata); $this->assertEquals('tool_dynamic_cohorts', $DB->get_field('cohort', 'component', ['id' => $cohort->id])); // Update the rule, changing the name. Should work as cohort is the same. $formdata = ['id' => $rule->get('id'), 'name' => 'Test1', 'cohortid' => $cohort->id, 'description' => 'D', 'conditionjson' => '', - 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'bulkprocessing' => 1, 'realtime' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; rule_manager::process_form((object)$formdata); $this->assertEquals('tool_dynamic_cohorts', $DB->get_field('cohort', 'component', ['id' => $cohort->id])); @@ -332,7 +334,7 @@ public function test_process_rule_form_triggers_events() { $eventsink = $this->redirectEvents(); $formdata = ['name' => 'Test1', 'cohortid' => $cohort->id, 'description' => 'D', - 'conditionjson' => '', 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'conditionjson' => '', 'bulkprocessing' => 1, 'realtime' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; $rule = rule_manager::process_form((object) $formdata); $events = array_filter($eventsink->get_events(), function ($event) { @@ -346,7 +348,7 @@ public function test_process_rule_form_triggers_events() { // Update the rule, changing the name. Should work as cohort is the same. $formdata = ['id' => $rule->get('id'), 'name' => 'Test1', 'cohortid' => $cohort->id, 'description' => 'D', 'conditionjson' => '', 'bulkprocessing' => 1, - 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'realtime' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; rule_manager::process_form((object) $formdata); $events = array_filter($eventsink->get_events(), function ($event) { @@ -369,7 +371,7 @@ public function test_process_rule_form_without_condition_data() { $this->expectExceptionMessage('Invalid rule data. Missing condition data.'); $formdata = ['name' => 'Test', 'cohortid' => $cohort->id, 'description' => '', 'bulkprocessing' => 1, - 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'realtime' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; rule_manager::process_form((object)$formdata); } @@ -386,7 +388,7 @@ public function test_process_rule_form_with_conditions() { // Creating rule without conditions. $formdata = ['name' => 'Test', 'cohortid' => $cohort->id, 'description' => '', - 'conditionjson' => '', 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'conditionjson' => '', 'bulkprocessing' => 1, 'realtime' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; $rule = rule_manager::process_form((object)$formdata); // No conditions yet. Rule should be ok. @@ -406,7 +408,7 @@ public function test_process_rule_form_with_conditions() { $formdata = ['id' => $rule->get('id'), 'name' => 'Test', 'enabled' => 1, 'cohortid' => $cohort->id, 'description' => '', 'conditionjson' => $conditionjson, 'bulkprocessing' => 1, - 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'realtime' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; $rule = rule_manager::process_form((object)$formdata); $this->assertEquals(1, $DB->count_records(rule::TABLE)); $this->assertCount(0, $rule->get_condition_records()); @@ -419,7 +421,7 @@ public function test_process_rule_form_with_conditions() { // Updating the rule with 3 new conditions. Expecting 3 new conditions to be created. $formdata = ['id' => $rule->get('id'), 'name' => 'Test', 'enabled' => 1, 'cohortid' => $cohort->id, 'description' => '', 'conditionjson' => $conditionjson, 'isconditionschanged' => true, - 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'realtime' => 1, 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; $rule = rule_manager::process_form((object)$formdata); $this->assertEquals(1, $DB->count_records(rule::TABLE)); $this->assertCount(3, $rule->get_condition_records()); @@ -453,7 +455,7 @@ public function test_process_rule_form_with_conditions() { $formdata = ['id' => $rule->get('id'), 'name' => 'Test', 'enabled' => 1, 'cohortid' => $cohort->id, 'description' => '', 'conditionjson' => $conditionjson, 'isconditionschanged' => true, - 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'realtime' => 1, 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; $rule = rule_manager::process_form((object)$formdata); $this->assertEquals(1, $DB->count_records(rule::TABLE)); $this->assertCount(3, $rule->get_condition_records()); @@ -467,7 +469,7 @@ public function test_process_rule_form_with_conditions() { $formdata = ['id' => $rule->get('id'), 'name' => 'Test', 'enabled' => 1, 'cohortid' => $cohort->id, 'description' => '', 'conditionjson' => '', 'isconditionschanged' => true, - 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; + 'realtime' => 1, 'bulkprocessing' => 1, 'operator' => rule_manager::CONDITIONS_OPERATOR_AND]; $rule = rule_manager::process_form((object)$formdata); $this->assertEquals(1, $DB->count_records(rule::TABLE)); $this->assertCount(0, $rule->get_condition_records()); diff --git a/version.php b/version.php index a147e8b..9490a74 100644 --- a/version.php +++ b/version.php @@ -25,8 +25,8 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'tool_dynamic_cohorts'; -$plugin->release = 2024051001; -$plugin->version = 2024051003; +$plugin->release = 2024051004; +$plugin->version = 2024051004; $plugin->requires = 2022112800; $plugin->supported = [401, 403]; $plugin->maturity = MATURITY_STABLE;