libdir.'/externallib.php'); abstract class aggregator { private const FALLBACK = "bistate"; private static $mod_supported = []; public static function supported($mod){ if(!array_key_exists($mod,self::$mod_supported)){ self::$mod_supported[$mod] = class_exists(self::aggregator_name($mod)); } return self::$mod_supported[$mod]; } private static function aggregator_name($mod){ return "\local_treestudyplan\\local\\aggregators\\{$mod}_aggregator"; } public static function list(){ // static list, since we'd need to implement a lot of static data for new aggregation methods anyway // and this is faster than any dynamic method. return [ "core", # use moodle core completion "bistate", "tristate", # deprecated ]; } public static function create($mod,$configstr){ if(self::supported($mod)){ $ag_class = self::aggregator_name($mod); return new $ag_class($configstr); } else { throw new \InvalidArgumentException("Cannot find aggregator '{$mod}'"); } } public static function createOrDefault($mod,$configstr){ try { return self::create($mod,$configstr); } catch(\ValueError $x){ return self::create(self::FALLBACK,""); } } private function __construct($configstr) { $this->initialize($configstr); } protected function initialize($configstr) {} public abstract function needSelectGradables(); public abstract function isDeprecated(); public abstract function aggregate_course(courseinfo $courseinfo, studyitem $studyitem, $userid); public abstract function aggregate_junction(array $completion, studyitem $studyitem, $userid); public abstract function grade_completion(gradeinfo $gradeinfo, $userid); // Aggregation method makes use of "required grades" in a course/module public abstract function useRequiredGrades(); // Aggregation method makes use of public abstract function useItemConditions(); // Whether the aggregation method uses core_completion, or treestudyplan custom completion public function usecorecompletioninfo(){ return false; } // Parameter editing functions - override in child class to implement parameter config for aggregation // Return the current configuration string public function config_string() { return ""; } public static function basic_structure($value=VALUE_REQUIRED){ return new \external_single_structure([ "useRequiredGrades" => new \external_value(PARAM_BOOL, 'id of studyplan'), "useItemConditions" => new \external_value(PARAM_BOOL, 'name of studyplan'), ],"Aggregator requirements",$value); } public function basic_model(){ return [ "useRequiredGrades" => $this->useRequiredGrades(), "useItemConditions" => $this->useItemConditions(), ]; } public static function list_structure($value=VALUE_REQUIRED){ return new \external_multiple_structure(new \external_single_structure([ "id" => new \external_value(PARAM_TEXT, 'id of aggregator'), "name" => new \external_value(PARAM_TEXT, 'name of agregator'), "deprecated" => new \external_value(PARAM_BOOL, 'if method is deprecated'), "defaultconfig" => new \external_value(PARAM_TEXT, 'default config of agregator'), ],"Available aggregators",$value)); } public static function list_model(){ $list = []; foreach(self::list() as $agid){ $a = self::create($agid,""); // create new one with empty config string $list[] = [ 'id' => $agid, 'name' => get_string("{$agid}_aggregator_title","local_treestudyplan"), 'deprecated' => $a->isDeprecated(), 'defaultconfig' => $a->config_string(), ]; } return $list; } }