Dynamic cohorts

Dynamic cohorts

Dynamic cohort rule API

A dynamic cohort is a cohort whose members are determined based on a query. The query is composed of a number of "rules". The rules are grouped together into rulesets, stored in mdl_cohort_rulesets. Within each ruleset are multiple rules, stored in mdl_cohort_rules. Each rule, in turn has two main components:

  1. A "rule type". Much like the Moodle admin tree, or report builder column & filter options, rule types are defined via an array in a PHP file. The file is cohort/rules/settings.php, and the array is the

    $rules

    array returned by

    '''cohort_rules_list()'''
  2. Several "rule parameters", which are unique to that rule instance and stored in cohort_rule_params.

Examples

Rule: All users whose language type is not French or Spanish

  • rule type: User's language preference

  • rule parameters:

    • equal = 0

    • listofvalues={fr, sp}

Rule: All users who have completed the courses "Algebra I", "Trigonometery", and "Advanced Swimming" before October 31, 2011

  • rule type: Course completion date

  • rule parameters:

    • operator = 'before'

    • date = October 31, 2011

    • courses = {Algebra I, Trigonometry, Advanced Swimming}

Rule types

The rule types (and thus the rule menu) are defined in the

'''$rules'''

array in

'''cohort_rules_list()'''

in cohort/rules/settings.php. Each item in the array should be an instance of the

'''cohort_rule_option'''

class, taking four parameters:

  1. First two parameters: rules' group & name.

    • This combination should be unique, and it's used to identify the rules in the database.

    • Each time Totara needs to do anything with the rule, it will look up its group and name in the database, then pull the array from cohort_rule_option(), and get the right value from the array based on that group and name.

  2. It maps to*mdl_cohort_rules, the ruletype and name columns. (I should refactor ruletype to "rulegroup" or "grp" or something... unfortunately "group" is a SQL reserved word.).

    • Additionally, in the rule selector menu there's a heading for each group, with its name being

      get_string('rulegroup-'''\{$group\}'''', 'local_cohort')
    • Each rule's name should be in

      get_string('rulename-'''\{$group\}'''-'''\{$name\}'''', 'local_cohort')
  3. Rule's sqlhandler instance, which retrieves/stores the rule's parameters from the database, and generates the rule's SQL snippet

    • Each sqlhandler class represents one particular parameterized SQL snippet. For instance, the most basic, cohort_rule_sqlhandler_in_userfield_int, which handles rules which check whether an INTEGER column of the mdl_user table has a value in a particular list of values, i.e. "u.{$column} {$not} IN ({$listofvalues})"

  4. Rule's ui instance, which handles the dialog to create/edit the rule, and display a summary of it to the admin user

    • Each ui class represents one particular rule dialog type. The subclasses of cohort_rule_ui_form are particularly versatile, since most of them only display a dialog with a simple form

To add a new rule type to the menu:

  1. Identify the sqlhandler and ui you will need for your new rule type. 

  2. The sqlhandler and ui classes you use must have identical $params values.

  3. Add an entry to $rules

  4. If you've added a new group, define its name string, which will be

    get_string(''''rulegroup-\{$group\}'''', ''''local_cohort'''');
  5. . Define the rule type's name string, which will be

    get_string(''''rulename-\{$group\}-\{$name\}'''',''''local_cohort'''');

sqlhandlers

A little background, to explain what each sqlhandler does. The query that identifies the users in a dynamic cohort looks like this:

select u.* from mdl_user u where {SQL snippet for rule 1} AND {SQL snippet for rule 2} AND {SQL snippet for rule 3} ...

In other words, each of the dynamic cohort's rules adds one condition to its WHERE clause. These are referred to here as "SQL snippets". Many of the rule types have very similar SQL snippets, for instance:

"u.lang \{$not\} in ($lov)"

,

"u.idnumber \{$not\} in (\{$lov\})"

,

"u.username \{$not\} in (\{$lov\})"

We've grouped those together to be handled by a single sqlhandler class, which takes parameters at its instantiation to distinguish them.

There's the potential for a little confusion here. sqlhandlers have two types of parameters:

  1. Parameters passed to the sqlhandler's constructor in settings.php 

    • These distinguish multiple*rule types that use the same sqlhandler class e.g. the "user's language preference", "user's idnumber", and "user's username" rule types all use

      cohort_rule_sqlhandler_in class

      Its constructor has the parameter "$column", with $column equal to 'lang', 'idnumber', or 'username'.

    • These are not configurable via the user interface; instead, the user chooses between them by their selection in the "add a rule" menu

  2. Parameters retrieved from the database table mdl_cohort_rule_params

    • These are the settings that the admin user has chosen, for this particular*instance of this rule type e.g. the rule "user's idnumber is 0001", "user's idnumber is 0002", etc. 

    • These are usually directly configurable via the user interface