. /** * * @package local_treestudyplan * @copyright 2023 P.M. Kuipers * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace local_treestudyplan; defined('MOODLE_INTERNAL') || die(); require_once($CFG->libdir.'/externallib.php'); abstract class aggregator { private const FALLBACK = "bistate"; private static $modsupported = []; public static function supported($mod) { if (!array_key_exists($mod, self::$modsupported)) { self::$modsupported[$mod] = class_exists(self::aggregator_name($mod)); } return self::$modsupported[$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)) { $agclass = self::aggregator_name($mod); return new $agclass($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) { } abstract public function needSelectGradables(); abstract public function isDeprecated(); abstract public function aggregate_course(courseinfo $courseinfo, studyitem $studyitem, $userid); abstract public function aggregate_junction(array $completion, studyitem $studyitem, $userid); abstract public function grade_completion(gradeinfo $gradeinfo, $userid); // Aggregation method makes use of "required grades" in a course/module. abstract public function useRequiredGrades(); // Aggregation method makes use of . abstract public 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; } }