moodle_local_treestudyplan/classes/aggregator.php

249 lines
8.7 KiB
PHP
Raw Permalink Normal View History

<?php
2023-08-24 23:02:41 +02:00
// This file is part of the Studyplan plugin for Moodle
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
/**
2023-08-27 17:00:23 +02:00
* Base class for aggregators
2023-08-24 23:02:41 +02:00
* @package local_treestudyplan
* @copyright 2023 P.M. Kuipers
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace local_treestudyplan;
2023-08-27 15:12:54 +02:00
use \ValueError;
2023-08-25 12:04:27 +02:00
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir.'/externallib.php');
2023-08-27 17:00:23 +02:00
/**
* Base class for aggregators
*/
abstract class aggregator {
2023-08-27 17:00:23 +02:00
/** Fallback aggregator if method not found
2023-08-27 22:20:17 +02:00
* @var string
2023-08-27 17:00:23 +02:00
* */
private const FALLBACK = "core";
/** @var string[] */
2023-08-27 15:12:54 +02:00
private static $methodsupported = [];
/**
* Check if aggregation method is supported
* @param string $method Name of aggregation method
*/
public static function supported($method) {
if (!array_key_exists($method, self::$methodsupported)) {
self::$methodsupported[$method] = class_exists(self::aggregator_name($method));
}
2023-08-27 15:12:54 +02:00
return self::$methodsupported[$method];
}
2023-08-27 15:12:54 +02:00
/**
* Get class name for aggregation method
* @param string $method Name of aggregation method
*/
private static function aggregator_name($method) {
return "\local_treestudyplan\\local\\aggregators\\{$method}_aggregator";
}
2023-08-27 15:12:54 +02:00
/**
* Get names of supported aggregation methods
* @return string[] Names of aggregation methods
*/
2023-08-24 23:02:41 +02:00
public static function list() {
2023-08-25 09:44:34 +02:00
// 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 [
2023-08-25 10:41:56 +02:00
"core", // Use moodle core completion.
2023-08-24 23:02:41 +02:00
"bistate",
2023-08-25 10:41:56 +02:00
"tristate", // Deprecated.
];
}
2023-08-27 22:20:17 +02:00
2023-08-27 15:12:54 +02:00
/**
* Create a new aggregatior object based on the specified method
* @param mixed $method Aggregation method
* @param mixed $configstr Configuration string for aggregator
* @throws ValueError If method is not found
*/
2023-08-28 08:51:52 +02:00
public static function create($method, $configstr) : self {
2023-08-27 15:12:54 +02:00
if (self::supported($method)) {
$agclass = self::aggregator_name($method);
2023-08-25 09:33:42 +02:00
return new $agclass($configstr);
} else {
2023-08-27 15:12:54 +02:00
throw new \ValueError("Cannot find aggregator '{$method}'");
}
}
2023-08-27 15:12:54 +02:00
/**
2023-08-27 22:20:17 +02:00
* Create a new aggregatior object based on the specified method,
2023-08-27 15:12:54 +02:00
* but return a default aggregator if the method is not found
* @param mixed $method Aggregation method
* @param mixed $configstr Configuration string for aggregator
*/
2023-08-28 08:51:52 +02:00
public static function create_or_default($method, $configstr) : self {
try {
2023-08-27 15:12:54 +02:00
return self::create($method, $configstr);
2023-08-25 10:41:56 +02:00
} catch (\ValueError $x) {
2023-08-24 23:02:41 +02:00
return self::create(self::FALLBACK, "");
}
}
2023-08-24 23:02:41 +02:00
2023-08-27 15:12:54 +02:00
/**
* Create new instance of aggregation method
* @param string $configstr Aggregation configuration string
*/
private function __construct($configstr) {
$this->initialize($configstr);
}
2023-08-27 15:12:54 +02:00
/**
* Initialize the aggregation method
* @param string $configstr Aggregation configuration string
*/
2023-08-25 10:41:56 +02:00
protected function initialize($configstr) {
}
2023-08-27 15:12:54 +02:00
/**
* Determine if aggregation method wants to select gradables
* @return bool True if aggregation method needs gradables to be selected
*/
2023-08-25 13:34:31 +02:00
abstract public function select_gradables();
2023-08-27 15:12:54 +02:00
/**
* Determine if aggregation method is deprecated
* @return bool True if aggregation method is deprecated
*/
2023-08-25 13:34:31 +02:00
abstract public function deprecated();
2023-08-27 15:12:54 +02:00
/**
* Aggregate all completions in a course into one final course completion
* Possible states:
* completion::EXCELLENT - Completed with excellent results
* completion::GOOD - Completed with good results
* completion::COMPLETED - Completed
* completion::PROGRESS - Started, but not completed yey
* completion::FAILED - Failed
* completion::INCOMPLETE - Not yet started
* @param courseinfo $courseinfo Courseinfo object for the course to check
* @param studyitem $studyitem Studyitem object for the course to check
* @param int $userid Id of user to check this course for
* @return int Aggregated completion as completion class constant
*/
2023-08-25 11:52:05 +02:00
abstract public function aggregate_course(courseinfo $courseinfo, studyitem $studyitem, $userid);
2023-08-27 15:12:54 +02:00
/**
* Aggregate juncton/filter inputs into one final junction outcome
* @param int[] $completion List of completion inputs
* @param studyitem $studyitem Studyitem object for the junction
* @param int $userid Id of user to check completion for
* @return int Aggregated completion as completion class constant
*/
2023-08-25 11:52:05 +02:00
abstract public function aggregate_junction(array $completion, studyitem $studyitem, $userid);
2023-08-27 15:12:54 +02:00
/**
* Determine completion for a single grade and user
* @param gradeinfo $gradeinfo Gradeinfo object for grade to check
* @param mixed $userid Id of user to check completion for
* @return int Aggregated completion as completion class constant
*/
2023-08-25 11:52:05 +02:00
abstract public function grade_completion(gradeinfo $gradeinfo, $userid);
2023-08-27 15:12:54 +02:00
/**
* Determine if Aggregation method makes use of "required grades" in a course/module.
* @return bool True if Aggregation method makes use of "required grades" in a course/module.
*/
2023-08-25 13:34:31 +02:00
abstract public function use_required_grades();
2023-08-27 15:12:54 +02:00
/**
* Determine if aggregation method makes use of required grades
2023-08-27 22:20:17 +02:00
* @return bool True if aggregation method makes use of
2023-08-27 15:12:54 +02:00
*/
2023-08-25 13:34:31 +02:00
abstract public function use_item_conditions();
2023-08-27 15:12:54 +02:00
/**
* Determine if the aggregation method uses core_completion, or treestudyplan custom completion.
* @return bool True if the aggregation method uses core_completion
*/
2023-08-24 23:02:41 +02:00
public function usecorecompletioninfo() {
return false;
}
2023-08-27 15:12:54 +02:00
/**
* Return the current configuration string.
* @return string Configuration string
2023-08-27 22:20:17 +02:00
*/
public function config_string() {
return "";
}
2023-08-27 22:20:17 +02:00
2023-08-27 15:12:54 +02:00
/**
* Webservice structure for basic aggregator info
* @param int $value Webservice requirement constant
*/
2023-08-28 08:51:52 +02:00
public static function basic_structure($value = VALUE_REQUIRED) : \external_description {
return new \external_single_structure([
"useRequiredGrades" => new \external_value(PARAM_BOOL, 'id of studyplan'),
"useItemConditions" => new \external_value(PARAM_BOOL, 'name of studyplan'),
2023-08-24 23:02:41 +02:00
], "Aggregator requirements", $value);
}
2023-08-27 15:12:54 +02:00
/**
* Webservice model for basic aggregator info
* @return array Webservice data model
*/
2023-08-24 23:02:41 +02:00
public function basic_model() {
return [
2023-08-25 13:34:31 +02:00
"useRequiredGrades" => $this->use_required_grades(),
"useItemConditions" => $this->use_item_conditions(),
];
}
2023-08-27 15:12:54 +02:00
/**
* Webservice structure list of aggregators
* @param int $value Webservice requirement constant
* @return mixed Webservice output structure
*/
2023-08-28 08:51:52 +02:00
public static function list_structure($value = VALUE_REQUIRED) : \external_description {
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'),
2023-08-24 23:02:41 +02:00
], "Available aggregators", $value));
}
2023-08-27 15:12:54 +02:00
/**
* Webservice model for list of aggregators
* @return array Webservice data model
*/
2023-08-24 23:02:41 +02:00
public static function list_model() {
$list = [];
2023-08-24 23:02:41 +02:00
foreach (self::list() as $agid) {
2023-08-25 10:41:56 +02:00
$a = self::create($agid, ""); // Create new one with empty config string.
$list[] = [
'id' => $agid,
2023-08-24 23:02:41 +02:00
'name' => get_string("{$agid}_aggregator_title", "local_treestudyplan"),
2023-08-25 13:34:31 +02:00
'deprecated' => $a->deprecated(),
'defaultconfig' => $a->config_string(),
];
}
2023-08-24 23:02:41 +02:00
return $list;
}
2023-08-25 10:41:56 +02:00
}