+ case 'createElement':
+ // The first argument is the name.
+ $name = $arg[0];
+
+ // Set disable actions.
+ $caller->disabledIf($name.'[modgrade_scale]', $name.'[modgrade_type]', 'neq', 'scale');
+ $caller->disabledIf($name.'[modgrade_point]', $name.'[modgrade_type]', 'neq', 'point');
+
+ // Set validation rules for the sub-elements belonging to this element.
+ // A handy note: the parent scope of a closure is the function in which the closure was declared.
+ // Because of this using $this is safe despite the closures being called statically.
+ // A nasty magic hack!
+ $checkmaxgrade = function($val) {
+ // Closure to validate a max points value. See the note above about scope if this confuses you.
+ if (isset($val['modgrade_type']) && $val['modgrade_type'] === 'point') {
+ if (!isset($val['modgrade_point'])) {
+ return false;
+ }
+ return $this->validate_point($val['modgrade_point']);
+ }
+ return true;
+ };
+ $checkvalidscale = function($val) {
+ // Closure to validate a scale value. See the note above about scope if this confuses you.
+ if (isset($val['modgrade_type']) && $val['modgrade_type'] === 'scale') {
+ if (!isset($val['modgrade_scale'])) {
+ return false;
+ }
+ return $this->validate_scale($val['modgrade_scale']);
+ }
+ return true;
+ };
+
+ $maxgradeexceeded = get_string('modgradeerrorbadpoint', 'grades', get_config('core', 'gradepointmax'));
+ $invalidscale = get_string('modgradeerrorbadscale', 'grades');
+ // When creating the rules the sixth arg is $force, we set it to true because otherwise the form
+ // will attempt to validate the existence of the element, we don't want this because the element
+ // is being created right now and doesn't actually exist as a registered element yet.
+ $caller->addRule($name, $maxgradeexceeded, 'callback', $checkmaxgrade, 'server', false, true);
+ $caller->addRule($name, $invalidscale, 'callback', $checkvalidscale, 'server', false, true);
+
+ break;
+