moodlemoodle-api

Custom moodle completion rule does not work


I am developing a mod_plugin for Moodle and want to support the automatic activity completion with a custom rule. I followed the official documentation and implemented all necessary functions. In the lib.php [pluginname]_supports method I have registered, FEATURE_GRADE_HAS_GRADE, FEATURE_COMPLETION_TRACKS_VIEWS, FEATURE_COMPLETION_HAS_RULES.

The \mod_[pluginname]\completion\custom_completion class defines a custom rule named "completiontest" in get_defined_custom_rules(). During my tests I found out that the methods get_state(), get_sort_order() and get_custom_rule_descriptions() are never executed. Also I don't see any output via activity_information().

I have cleared all caches, created new instances of my activity module, with no result. My development environment uses Moodle 3.11.7 (Build: 20220509).

My custom_completion.php script:

<?php
declare(strict_types=1);

namespace mod_cwr\completion;

use core_completion\activity_custom_completion;

class custom_completion extends activity_custom_completion {

    public function get_state(string $rule): int {       
        return COMPLETION_INCOMPLETE;
    }

    public static function get_defined_custom_rules(): array {
        return [          
            'completiontest'
        ];
    }

    public function get_custom_rule_descriptions(): array {       
        return [
            'completiontest' => 'testout'
        ];
    }

    public function get_sort_order(): array {       
        return [
            'completionview',
            'completiontest',
            'completionusegrade'
        ];
    }    
}

Test at the view.php:

$completion = new completion_info($course);
$completion->set_module_viewed($coursemodule);
if($completion->is_enabled($coursemodule) == COMPLETION_TRACKING_AUTOMATIC){
    $completion->update_state($coursemodule, COMPLETION_INCOMPLETE, $USER->id);
}
$completiondetails = \core_completion\cm_completion_details::get_instance($coursemodule, $USER->id);
$activitydates = \core\activity_dates::get_dates_for_module($coursemodule, $USER->id);
echo $OUTPUT->activity_information($coursemodule, $completiondetails, $activitydates);

At the mod_form.php I check with completion_rule_enabled() if a custom rule is activated by the settings.

Does anyone have any idea what the problem could be?

Looking at the mod_forum plugin code showed me, that the get_state($rule) method does not observe all custom rules, only those selected in the settings. How do I tell Moodle to use a specific custom rule?


Solution

  • You appear to be calling update_state() and passing in the possible state change as COMPLETION_INCOMPLETE.

    This is a way of telling Moodle "if the state is already incomplete, don't bother doing any expensive completion calculations to check if it should change state".

    If you want Moodle to check and then (potentially) change the state to "complete", then pass COMPLETION_COMPLETE. If you really don't know which way it could be switching, then leave the param at the default COMPLETION_UNKNOWN (a good example would be forum completion - if you have just created a forum post, then you might cause the forum to be marked as "complete", but you certainly can't cause the forum to be marked as "incomplete", so you can pass the COMPLETION_COMPLETE parameter, so Moodle knows it only needs to check for changes if the forum is not already "complete").

    Also, don't bother passing $USER->id as the third parameter - that's the default which is used of you don't pass anything.

    As for telling Moodle which rules to use - it is up to you, when your function is called, to check your plugins settings to determine which rules are in use (and any other relevant configuration - e.g. with mod_forum, it needs to check how many posts are required for completion).