Code style

This commit is contained in:
PMKuipers 2024-06-02 19:23:40 +02:00
parent 4c669ff08c
commit e72be595aa
60 changed files with 1327 additions and 1447 deletions

View File

@ -80,7 +80,7 @@ abstract class aggregator {
* @param mixed $configstr Configuration string for aggregator
* @throws ValueError If method is not found
*/
public static function create($method, $configstr) : self {
public static function create($method, $configstr): self {
if (self::supported($method)) {
$agclass = self::aggregator_name($method);
return new $agclass($configstr);
@ -95,7 +95,7 @@ abstract class aggregator {
* @param mixed $method Aggregation method
* @param mixed $configstr Configuration string for aggregator
*/
public static function create_or_default($method, $configstr) : self {
public static function create_or_default($method, $configstr): self {
try {
return self::create($method, $configstr);
} catch (\ValueError $x) {
@ -190,7 +190,7 @@ abstract class aggregator {
* 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.
*/
public function use_required_grades(){
public function use_required_grades() {
return false;
}
@ -198,11 +198,10 @@ abstract class aggregator {
* Determine if aggregation method makes use of item conditions
* @return bool True if aggregation method makes use of
*/
public function use_item_conditions(){
public function use_item_conditions() {
return false;
}
/**
* Return the current configuration string.
* @return string Configuration string
@ -211,12 +210,11 @@ abstract class aggregator {
return "";
}
/**
* Webservice structure for basic aggregator info
* @param int $value Webservice requirement constant
*/
public static function basic_structure($value = VALUE_REQUIRED) : \external_description {
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'),
@ -239,7 +237,7 @@ abstract class aggregator {
* @param int $value Webservice requirement constant
* @return mixed Webservice output structure
*/
public static function list_structure($value = VALUE_REQUIRED) : \external_description {
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'),

View File

@ -50,7 +50,7 @@ class associationservice extends \external_api {
/**
* Webservice structure to use in describing a user
*/
public static function user_structure() : \external_description {
public static function user_structure(): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'user id'),
"username" => new \external_value(PARAM_TEXT, 'username'),
@ -80,7 +80,7 @@ class associationservice extends \external_api {
/**
* Webservice structure to use in describing a cohort
*/
public static function cohort_structure() : \external_description {
public static function cohort_structure(): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'cohort id'),
"name" => new \external_value(PARAM_TEXT, 'name'),
@ -124,14 +124,14 @@ class associationservice extends \external_api {
"shortpath" => array_map(function($c) {
return \context::instance_by_id($c)->get_context_name(false, true);
}, $ctxpath),
]
],
];
return $result;
}
public static function user_lastaccess($userid,$studyplanid=null) {
public static function user_lastaccess($userid, $studyplanid=null) {
global $DB;
if (!empty($studyplanid)) {
$lasql = "SELECT MAX(a.timeaccess) FROM {user_lastaccess} a
@ -139,22 +139,20 @@ class associationservice extends \external_api {
INNER JOIN {local_treestudyplan_line} l ON l.id = i.line_id
INNER JOIN {local_treestudyplan_page} p ON l.page_id = p.id
WHERE a.userid = :userid AND p.studyplan_id = :studyplanid";
$lastaccess = $DB->get_field_sql($lasql,["userid" => $userid, "studyplanid" => $studyplanid]);
$lastaccess = $DB->get_field_sql($lasql, ["userid" => $userid, "studyplanid" => $studyplanid]);
} else {
$lasql = "SELECT MAX(a.timeaccess) FROM {user_lastaccess} a
WHERE a.userid = :userid";
$lastaccess = $DB->get_field_sql($lasql,["userid" => $userid]);
$lastaccess = $DB->get_field_sql($lasql, ["userid" => $userid]);
}
return $lastaccess;
}
/**
* Parameter description for webservice function list_cohort
*/
public static function list_cohort_parameters() : \external_function_parameters {
public static function list_cohort_parameters(): \external_function_parameters {
return new \external_function_parameters( [
'like' => new \external_value(PARAM_TEXT, 'search text'),
'studyplan_id' => new \external_value(PARAM_INT, 'id of studyplan to list for'),
@ -164,32 +162,32 @@ class associationservice extends \external_api {
/**
* Return value description for webservice function list_cohort
*/
public static function list_cohort_returns() : \external_description {
public static function list_cohort_returns(): \external_description {
return new \external_multiple_structure(self::cohort_structure());
}
/**
* Search cohorts for matching string
* @param string $like String to match cohorts with
* @param int $studyplan_id Do not include these cohorts
* @param int $studyplanid Do not include these cohorts
* @return array
*/
public static function list_cohort($like, $studyplan_id) {
public static function list_cohort($like, $studyplanid) {
global $CFG, $DB;
// Only allow this if the user has the right to edit in this context.
$studyplan = studyplan::find_by_id($studyplan_id);
$studyplan = studyplan::find_by_id($studyplanid);
$context = $studyplan->context();
webservicehelper::require_capabilities(self::CAP_EDIT, $context);
$pattern = "%{$like}%";
$params = ["pattern_nm" => $pattern, "pattern_id" => $pattern, ];
$params = ["pattern_nm" => $pattern, "pattern_id" => $pattern ];
$sql = "SELECT DISTINCT c.* from {cohort} c LEFT JOIN {local_treestudyplan_cohort} j ON c.id = j.cohort_id
WHERE c.visible = 1 AND(name LIKE :pattern_nm OR idnumber LIKE :pattern_id)
AND (j.studyplan_id IS NULL OR j.studyplan_id != :exclude_id)";
$params['exclude_id'] = $studyplan_id;
$params['exclude_id'] = $studyplanid;
$cohorts = [];
$rs = $DB->get_recordset_sql($sql, $params);
@ -203,7 +201,7 @@ class associationservice extends \external_api {
/**
* Parameter description for webservice function find_user
*/
public static function find_user_parameters() : \external_function_parameters {
public static function find_user_parameters(): \external_function_parameters {
return new \external_function_parameters( [
'like' => new \external_value(PARAM_TEXT, 'search text'),
'studyplan_id' => new \external_value(PARAM_INT, 'id of studyplan to list for'),
@ -213,7 +211,7 @@ class associationservice extends \external_api {
/**
* Return value description for webservice function find_user
*/
public static function find_user_returns() : \external_description {
public static function find_user_returns(): \external_description {
return new \external_multiple_structure(self::user_structure());
}
@ -224,11 +222,11 @@ class associationservice extends \external_api {
* @param int $contextid Context to search (default system)
* @return array
*/
public static function find_user($like, $studyplan_id) {
public static function find_user($like, $studyplanid) {
global $CFG, $DB;
// Only allow this if the user has the right to edit in this context.
$studyplan = studyplan::find_by_id($studyplan_id);
$studyplan = studyplan::find_by_id($studyplanid);
$context = $studyplan->context();
webservicehelper::require_capabilities(self::CAP_EDIT, $context);
@ -240,7 +238,7 @@ class associationservice extends \external_api {
$sql = "SELECT DISTINCT u.* from {user} u LEFT JOIN {local_treestudyplan_user} j ON u.id = j.user_id
WHERE u.deleted != 1 AND (firstname LIKE :pattern_fn OR lastname LIKE :pattern_ln OR username LIKE :pattern_un)
AND (j.studyplan_id IS NULL OR j.studyplan_id != :exclude_id)";
$params['exclude_id'] = $studyplan_id;
$params['exclude_id'] = $studyplanid;
$users = [];
$rs = $DB->get_recordset_sql($sql, $params);
@ -256,7 +254,7 @@ class associationservice extends \external_api {
/**
* Parameter description for webservice function connect_cohort
*/
public static function connect_cohort_parameters() : \external_function_parameters {
public static function connect_cohort_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL),
"cohort_id" => new \external_value(PARAM_INT, 'id of cohort to link', VALUE_OPTIONAL),
@ -266,7 +264,7 @@ class associationservice extends \external_api {
/**
* Return value description for webservice function connect_cohort
*/
public static function connect_cohort_returns() : \external_description {
public static function connect_cohort_returns(): \external_description {
return new \external_single_structure([
"success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'),
"msg" => new \external_value(PARAM_TEXT, 'message'),
@ -303,7 +301,7 @@ class associationservice extends \external_api {
/**
* Parameter description for webservice function disconnect_cohort
*/
public static function disconnect_cohort_parameters() : \external_function_parameters {
public static function disconnect_cohort_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL),
"cohort_id" => new \external_value(PARAM_INT, 'id of cohort to link', VALUE_OPTIONAL),
@ -313,7 +311,7 @@ class associationservice extends \external_api {
/**
* Return value description for webservice function disconnect_cohort
*/
public static function disconnect_cohort_returns() : \external_description {
public static function disconnect_cohort_returns(): \external_description {
return new \external_single_structure([
"success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'),
"msg" => new \external_value(PARAM_TEXT, 'message'),
@ -350,7 +348,7 @@ class associationservice extends \external_api {
/**
* Parameter description for webservice function connect_user
*/
public static function connect_user_parameters() : \external_function_parameters {
public static function connect_user_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL),
"user_id" => new \external_value(PARAM_INT, 'id of user to link', VALUE_OPTIONAL),
@ -360,7 +358,7 @@ class associationservice extends \external_api {
/**
* Return value description for webservice function connect_user
*/
public static function connect_user_returns() : \external_description {
public static function connect_user_returns(): \external_description {
return new \external_single_structure([
"success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'),
"msg" => new \external_value(PARAM_TEXT, 'message'),
@ -396,7 +394,7 @@ class associationservice extends \external_api {
/**
* Parameter description for webservice function disconnect_user
*/
public static function disconnect_user_parameters() : \external_function_parameters {
public static function disconnect_user_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL),
"user_id" => new \external_value(PARAM_INT, 'id of user to link', VALUE_OPTIONAL),
@ -406,7 +404,7 @@ class associationservice extends \external_api {
/**
* Return value description for webservice function disconnect_user
*/
public static function disconnect_user_returns() : \external_description {
public static function disconnect_user_returns(): \external_description {
return new \external_single_structure([
"success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'),
"msg" => new \external_value(PARAM_TEXT, 'message'),
@ -441,7 +439,7 @@ class associationservice extends \external_api {
/**
* Parameter description for webservice function associated_users
*/
public static function associated_users_parameters() : \external_function_parameters {
public static function associated_users_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL),
] );
@ -450,7 +448,7 @@ class associationservice extends \external_api {
/**
* Return value description for webservice function associated_users
*/
public static function associated_users_returns() : \external_description {
public static function associated_users_returns(): \external_description {
return new \external_multiple_structure(self::user_structure());
}
@ -481,7 +479,7 @@ class associationservice extends \external_api {
$users = [];
foreach ($rs as $u) {
$user = self::make_user_model($u);
$user["lastaccess"] = self::user_lastaccess($u->id,$studyplanid);
$user["lastaccess"] = self::user_lastaccess($u->id, $studyplanid);
$users[] = $user;
}
@ -493,7 +491,7 @@ class associationservice extends \external_api {
/**
* Parameter description for webservice function associated_cohorts
*/
public static function associated_cohorts_parameters() : \external_function_parameters {
public static function associated_cohorts_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL),
] );
@ -502,7 +500,7 @@ class associationservice extends \external_api {
/**
* Return value description for webservice function associated_cohorts
*/
public static function associated_cohorts_returns() : \external_description {
public static function associated_cohorts_returns(): \external_description {
return new \external_multiple_structure(self::cohort_structure());
}
@ -530,7 +528,7 @@ class associationservice extends \external_api {
/**
* Parameter description for webservice function all_associated
*/
public static function all_associated_parameters() : \external_function_parameters {
public static function all_associated_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL),
] );
@ -539,7 +537,7 @@ class associationservice extends \external_api {
/**
* Return value description for webservice function all_associated
*/
public static function all_associated_returns() : \external_description {
public static function all_associated_returns(): \external_description {
return new \external_multiple_structure(self::user_structure());
}
@ -577,10 +575,10 @@ class associationservice extends \external_api {
return $users;
}
/**
/**
* Parameter description for webservice function all_associated
*/
public static function all_associated_grouped_parameters() : \external_function_parameters {
public static function all_associated_grouped_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL),
] );
@ -589,10 +587,10 @@ class associationservice extends \external_api {
/**
* Return value description for webservice function all_associated
*/
public static function all_associated_grouped_returns() : \external_description {
public static function all_associated_grouped_returns(): \external_description {
return new \external_multiple_structure(new \external_single_structure([
'id' => new \external_value(PARAM_INT, 'id of group'),
'label' => new \external_value(PARAM_TEXT,'group label'),
'label' => new \external_value(PARAM_TEXT, 'group label'),
'users' => new \external_multiple_structure(self::user_structure()),
]));
}
@ -615,9 +613,9 @@ class associationservice extends \external_api {
$userlist = [
[
'id' => 0,
'label' => get_string("individuals",'local_treestudyplan'),
'label' => get_string("individuals", 'local_treestudyplan'),
'users' => self::associated_users($studyplanid),
]
],
];
$sql = "SELECT DISTINCT c.* FROM {cohort} c INNER JOIN {local_treestudyplan_cohort} j ON j.cohort_id = c.id
@ -634,7 +632,7 @@ class associationservice extends \external_api {
foreach ($rs as $u) {
$user = self::make_user_model($u);
$user["lastaccess"] = self::user_lastaccess($u->id,$studyplanid);
$user["lastaccess"] = self::user_lastaccess($u->id, $studyplanid);
$users[] = $user;
}
$rs->close();
@ -650,7 +648,6 @@ class associationservice extends \external_api {
return $userlist;
}
/**
* Sort a list of user models by firstname->lastname
* @param array $list Reference to list of user models
@ -676,7 +673,7 @@ class associationservice extends \external_api {
/**
* Parameter description for webservice function cascade_cohortsync
*/
public static function cascade_cohortsync_parameters() : \external_function_parameters {
public static function cascade_cohortsync_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL),
] );
@ -685,7 +682,7 @@ class associationservice extends \external_api {
/**
* Return value description for webservice function cascade_cohortsync
*/
public static function cascade_cohortsync_returns() : \external_description {
public static function cascade_cohortsync_returns(): \external_description {
return success::structure();
}
@ -705,11 +702,10 @@ class associationservice extends \external_api {
}
/**
/**
* Parameter description for webservice function connect_user
*/
public static function connect_coach_parameters() : \external_function_parameters {
public static function connect_coach_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL),
"user_id" => new \external_value(PARAM_INT, 'id of user to link', VALUE_OPTIONAL),
@ -719,7 +715,7 @@ class associationservice extends \external_api {
/**
* Return value description for webservice function connect_user
*/
public static function connect_coach_returns() : \external_description {
public static function connect_coach_returns(): \external_description {
return new \external_single_structure([
"success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'),
"msg" => new \external_value(PARAM_TEXT, 'message'),
@ -738,8 +734,8 @@ class associationservice extends \external_api {
$studyplan = studyplan::find_by_id($studyplanid);
webservicehelper::require_capabilities(self::CAP_EDIT, $studyplan->context());
$user = $DB->get_record("user",["id" => $userid]);
if( has_capability(self::CAP_COACH,$studyplan->context(),$user)) {
$user = $DB->get_record("user", ["id" => $userid]);
if ( has_capability(self::CAP_COACH, $studyplan->context(), $user)) {
if (!$DB->record_exists('local_treestudyplan_coach', ['studyplan_id' => $studyplanid, 'user_id' => $userid])) {
$id = $DB->insert_record('local_treestudyplan_coach', [
'studyplan_id' => $studyplanid,
@ -759,7 +755,7 @@ class associationservice extends \external_api {
/**
* Parameter description for webservice function disconnect_user
*/
public static function disconnect_coach_parameters() : \external_function_parameters {
public static function disconnect_coach_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL),
"user_id" => new \external_value(PARAM_INT, 'id of user to link', VALUE_OPTIONAL),
@ -769,7 +765,7 @@ class associationservice extends \external_api {
/**
* Return value description for webservice function disconnect_user
*/
public static function disconnect_coach_returns() : \external_description {
public static function disconnect_coach_returns(): \external_description {
return new \external_single_structure([
"success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'),
"msg" => new \external_value(PARAM_TEXT, 'message'),
@ -793,18 +789,16 @@ class associationservice extends \external_api {
'user_id' => $userid,
]);
return ['success' => true, 'msg' => 'User Disconnected as coach'];
} else {
return ['success' => true, 'msg' => 'Connection does not exist'];
}
}
/**
/**
* Parameter description for webservice function find_user
*/
public static function find_coach_parameters() : \external_function_parameters {
public static function find_coach_parameters(): \external_function_parameters {
return new \external_function_parameters( [
'like' => new \external_value(PARAM_TEXT, 'search text'),
'studyplan_id' => new \external_value(PARAM_INT, 'studyplan id to associate for', VALUE_OPTIONAL),
@ -814,7 +808,7 @@ class associationservice extends \external_api {
/**
* Return value description for webservice function find_user
*/
public static function find_coach_returns() : \external_description {
public static function find_coach_returns(): \external_description {
return new \external_multiple_structure(self::user_structure());
}
@ -825,12 +819,11 @@ class associationservice extends \external_api {
* @param int $contextid Context to search (default system)
* @return array
*/
public static function find_coach($like, $studyplan_id) {
public static function find_coach($like, $studyplanid) {
global $CFG, $DB;
// Only allow this if the user has the right to edit in this context.
$studyplan = studyplan::find_by_id($studyplan_id);
$studyplan = studyplan::find_by_id($studyplanid);
$context = $studyplan->context();
webservicehelper::require_capabilities(self::CAP_EDIT, $context);
@ -849,7 +842,7 @@ class associationservice extends \external_api {
$users = [];
$rs = $DB->get_recordset_sql($sql, $params);
foreach ($rs as $r) {
if (has_capability(self::CAP_COACH,$context,$r)) {
if (has_capability(self::CAP_COACH, $context, $r)) {
$users[] = static::make_user_model($r);
}
}
@ -861,7 +854,7 @@ class associationservice extends \external_api {
/**
* Parameter description for webservice function associated_users
*/
public static function associated_coaches_parameters() : \external_function_parameters {
public static function associated_coaches_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL),
] );
@ -870,7 +863,7 @@ class associationservice extends \external_api {
/**
* Return value description for webservice function associated_users
*/
public static function associated_coaches_returns() : \external_description {
public static function associated_coaches_returns(): \external_description {
return new \external_multiple_structure(self::user_structure());
}

View File

@ -97,15 +97,14 @@ class badgeinfo {
*/
public static function exists($id) {
global $DB;
return is_numeric($id) && $DB->record_exists('badge', array('id' => $id));
return is_numeric($id) && $DB->record_exists('badge', ['id' => $id]);
}
/**
* Webservice structure for editor info
* @param int $value Webservice requirement constant
*/
public static function simple_structure($value = VALUE_REQUIRED) : \external_description {
public static function simple_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of badge'),
"infolink" => new \external_value(PARAM_RAW, 'badge issue information link', VALUE_OPTIONAL),
@ -147,7 +146,7 @@ class badgeinfo {
* Webservice structure for editor info
* @param int $value Webservice requirement constant
*/
public static function editor_structure($value = VALUE_REQUIRED) : \external_description {
public static function editor_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of badge'),
"infolink" => new \external_value(PARAM_RAW, 'badge issue information link', VALUE_OPTIONAL),
@ -209,7 +208,7 @@ class badgeinfo {
* Webservice structure for userinfo
* @param int $value Webservice requirement constant
*/
public static function user_structure($value = VALUE_REQUIRED) : \external_description {
public static function user_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of badge'),
"infolink" => new \external_value(PARAM_TEXT, 'badge issue information link', VALUE_OPTIONAL),
@ -258,9 +257,8 @@ class badgeinfo {
"active" => $this->badge->is_active(),
];
if ($issued) {
$issueinfo = $DB->get_record('badge_issued', array('badgeid' => $this->badge->id, 'userid' => $userid));
$issueinfo = $DB->get_record('badge_issued', ['badgeid' => $this->badge->id, 'userid' => $userid]);
$badge['dateissued'] = date("Y-m-d", $issueinfo->dateissued);
if ($issueinfo->expiredate) {
$badge['dateexpire'] = date("Y-m-d", $issueinfo->dateexpire);
@ -272,48 +270,47 @@ class badgeinfo {
return $badge;
}
protected static function badge_completion_structure($value) {
return new \external_single_structure([
"types" => new \external_multiple_structure(new \external_single_structure([
'criteria' => new \external_multiple_structure(new \external_single_structure([
"title" => new \external_value(PARAM_RAW, 'criterion title'),
"description" => new \external_value(PARAM_RAW, 'criterion description'),
"link"=> new \external_value(PARAM_RAW, 'link to criterion resource',VALUE_OPTIONAL),
"link"=> new \external_value(PARAM_RAW, 'link to criterion resource', VALUE_OPTIONAL),
"requirements" => new \external_multiple_structure(new \external_single_structure([
"title" => new \external_value(PARAM_RAW, 'requirment title'),
"completed" => new \external_value(PARAM_BOOL, 'criterion is completed or not', VALUE_OPTIONAL),
]), "criterion specific requirements", VALUE_OPTIONAL),
"completed" => new \external_value(PARAM_BOOL, 'criterion is completed or not'),
]),'specific criteria'),
]), 'specific criteria'),
"title" => new \external_value(PARAM_RAW, 'type title'),
"aggregation" => new \external_value(PARAM_TEXT, 'any|all'),
"count" => new \external_value(PARAM_INT, 'effective number of critera for type progress'),
"progress" => new \external_value(PARAM_INT, 'effective number of completed criteria for type progress'),
"fraction" => new \external_value(PARAM_FLOAT, 'fraction of completed type criteria as float'),
]), "criteria types",VALUE_OPTIONAL),
]), "criteria types", VALUE_OPTIONAL),
"aggregation" => new \external_value(PARAM_TEXT, 'any|all'),
"count" => new \external_value(PARAM_INT, 'total number of critera for progress'),
"progress" => new \external_value(PARAM_INT, 'number of completed criteria for progress'),
"fraction" => new \external_value(PARAM_FLOAT, 'fraction of completed criteria as float'),
"title" => new \external_value(PARAM_RAW, 'completion title'),
],'badge completion information', $value);
], 'badge completion information', $value);
}
protected function badge_completion_data($userid) : array {
protected function badge_completion_data($userid): array {
$count = 0;
$progress = 0;
$fraction = 0;
$badgeagg = $this->badge->get_aggregation_method();
$types = [];
foreach ($this->badge->criteria as $type => $bc) {
if ($type != BADGE_CRITERIA_TYPE_OVERALL) {
$typeagg = $this->badge->get_aggregation_method($type);
$typecrit = $this->get_award_subcriteria($bc,$userid);
$typecrit = $this->get_award_subcriteria($bc, $userid);
$typecount = count($typecrit);
$typeprogress = 0;
foreach ($typecrit as $subcrit) {
@ -330,10 +327,10 @@ class badgeinfo {
}
// Determine how to patch this data into the overall progress numbers, depending on the OVERALL aggregation.
if($badgeagg == BADGE_CRITERIA_AGGREGATION_ANY) {
if ($badgeagg == BADGE_CRITERIA_AGGREGATION_ANY) {
/* If ANY completion overall, count only the criteria type with the highest completion percentage -.
Overwrite data if current type is more complete */
$typefraction = ($typecount > 0)?($typeprogress / $typecount):0;
$typefraction = ($typecount > 0) ? ($typeprogress / $typecount):0;
if ($typefraction > $fraction || ($fraction == 0 && $typecount > $count)) {
$fraction = $typefraction;
$count = $typecount;
@ -345,10 +342,10 @@ class badgeinfo {
$progress += $typeprogress;
}
$aggrgation_handle = ($typeagg == BADGE_CRITERIA_AGGREGATION_ALL)?"all":"any";
$aggrgationhandle = ($typeagg == BADGE_CRITERIA_AGGREGATION_ALL)?"all":"any";
$typeinfo = [
'title' => ucfirst(get_string("criteria_descr_$type","badges", get_string($aggrgation_handle,"core"))),
'aggregation' => $aggrgation_handle,
'title' => ucfirst(get_string("criteria_descr_$type", "badges", get_string($aggrgationhandle, "core"))),
'aggregation' => $aggrgationhandle,
'criteria' => $typecrit,
'count' => $typecount,
'progress' => $typeprogress,
@ -358,11 +355,11 @@ class badgeinfo {
}
}
$aggrgation_handle = ($badgeagg == BADGE_CRITERIA_AGGREGATION_ALL)?"all":"any";
$aggrgationhandle = ($badgeagg == BADGE_CRITERIA_AGGREGATION_ALL)?"all":"any";
return [
"types" => $types,
"title" => ucfirst(get_string("criteria_descr_0","badges", mb_strtolower(get_string($aggrgation_handle,"core")))),
"aggregation" => $aggrgation_handle,
"title" => ucfirst(get_string("criteria_descr_0", "badges", mb_strtolower(get_string($aggrgationhandle, "core")))),
"aggregation" => $aggrgationhandle,
"count" => $count,
"progress" => $progress,
"fraction" => $fraction,
@ -386,7 +383,6 @@ class badgeinfo {
return $issuecount;
}
/**
* Gets the module instance from the database and returns it.
@ -400,7 +396,7 @@ class badgeinfo {
FROM {course_modules} cm,
{modules} md
WHERE cm.id = ? AND
md.id = cm.module", array($cmid));
md.id = cm.module", [$cmid]);
if ($rec) {
return get_coursemodule_from_id($rec->name, $cmid);
@ -417,7 +413,7 @@ class badgeinfo {
*/
private static function get_role_name($rid) {
global $DB, $PAGE;
$rec = $DB->get_record('role', array('id' => $rid));
$rec = $DB->get_record('role', ['id' => $rid]);
if ($rec) {
return role_get_name($rec, \context_system::instance(), ROLENAME_BOTH);
@ -430,18 +426,18 @@ class badgeinfo {
* [Description for get_award_subcriteria]
*
* @param award_criteria $crit
*
*
* @return array
*
*
*/
protected function get_award_subcriteria(award_criteria $crit, $userid = null) : array {
protected function get_award_subcriteria(award_criteria $crit, $userid = null): array {
global $DB, $CFG;
$list = [];
if ($crit->criteriatype == BADGE_CRITERIA_TYPE_ACTIVITY) {
foreach ($crit->params as $p) {
$mod = self::get_mod_instance($p["module"]);
if(!$mod) {
if (!$mod) {
$title = get_string('error:nosuchmod', 'badges');
$description = get_string('error:nosuchmod', 'badges');
} else {
@ -457,9 +453,9 @@ class badgeinfo {
"description" => $description,
"requirements" => [
'completion' => [
'title' => get_string('completeactivity','core').
'title' => get_string('completeactivity', 'core').
get_string('modulename', $mod->modname) . ' - ' . $mod->name,
]
],
]
];
@ -469,7 +465,7 @@ class badgeinfo {
];
}
if(isset($userid)) {
if (isset($userid)) {
$info = new \completion_info($crit->course);
$cm = new \stdClass();
$cm->id = $p['module'];
@ -482,27 +478,27 @@ class badgeinfo {
// Any grade is required. Issue a badge even when state is COMPLETION_COMPLETE_FAIL.
$completionstates = [COMPLETION_COMPLETE, COMPLETION_COMPLETE_PASS, COMPLETION_COMPLETE_FAIL];
}
$modcompleted = in_array($data->completionstate, $completionstates);
$subcrit["requirements"]["completion"]["completed"] = $modcompleted;
$check_date = true;
$checkdate = true;
if (isset($p["bydate"])) {
$date = $data->timemodified;
$check_date = ($date <= $p['bydate']);
$subcrit["requirements"]["bydate"]["completed"] = $check_date;
$checkdate = ($date <= $p['bydate']);
$subcrit["requirements"]["bydate"]["completed"] = $checkdate;
}
$subcrit["completed"] = $modcompleted && $check_date;
$subcrit["completed"] = $modcompleted && $checkdate;
}
$list[] = $subcrit;
}
} else if ($crit->criteriatype == BADGE_CRITERIA_TYPE_MANUAL) {
foreach ($crit->params as $p) {
$role = self::get_role_name($p['role']);
if(!$role) {
if (!$role) {
$title = get_string('error:nosuchrole', 'badges');
$description = get_string('error:nosuchrole', 'badges');
} else {
@ -513,11 +509,11 @@ class badgeinfo {
$subcrit = [
"title" => $title,
"description" => $description,
"requirements" => []
"requirements" => [],
];
if(isset($userid)) {
$crit = $DB->get_record('badge_manual_award', array('issuerrole' => $p['role'], 'recipientid' => $userid, 'badgeid' => $crit->badgeid));
if (isset($userid)) {
$crit = $DB->get_record('badge_manual_award', ['issuerrole' => $p['role'], 'recipientid' => $userid, 'badgeid' => $crit->badgeid]);
$subcrit["completed"] = $crit !== false;
}
$list[] = $subcrit;
@ -533,8 +529,8 @@ class badgeinfo {
foreach ($params as $p) {
$course = get_course($p["course"]);
if(!$course) {
$description = get_string('error:nosuchcourse',"badges");
if (!$course) {
$description = get_string('error:nosuchcourse', "badges");
} else {
$description = \html_writer::tag('b', '"' . $course->fullname . '"');
if (isset($p['bydate'])) {
@ -547,18 +543,18 @@ class badgeinfo {
$subcrit = [
"title" => $course->fullname,
"link" => (new moodle_url($CFG->wwwroot."/course/view.php",["id" => $course->id]))->out(),
"link" => (new moodle_url($CFG->wwwroot."/course/view.php", ["id" => $course->id]))->out(),
"description" => $description,
"requirements" => [
'completion' => [
'title' => get_string('coursecompleted','completion'),
]
'title' => get_string('coursecompleted', 'completion'),
],
]
];
if (isset($p["grade"])) {
$subcrit["requirements"]["grade"] = [
'title' => get_string('criteria_descr_grade','badges',$p["grade"]),
'title' => get_string('criteria_descr_grade', 'badges', $p["grade"]),
];
}
@ -568,24 +564,24 @@ class badgeinfo {
];
}
if(isset($userid)) {
if (isset($userid)) {
$coursecompletion = new \completion_completion(["userid" => $userid, "course" => $course->id]);
$coursecompleted = $coursecompletion->is_complete();
$subcrit["requirements"]["completion"]["completed"] = (bool) $coursecompleted;
$check_grade = true;
$checkgrade = true;
if (isset($p["grade"])) {
$grade = \grade_get_course_grade($userid,$course->id);
$check_grade = ($grade->grade >= $p['grade']);
$subcrit["requirements"]["grade"]["completed"] = (bool) $check_grade;
$grade = \grade_get_course_grade($userid, $course->id);
$checkgrade = ($grade->grade >= $p['grade']);
$subcrit["requirements"]["grade"]["completed"] = (bool) $checkgrade;
}
$check_date = true;
$checkdate = true;
if (isset($p["bydate"])) {
$check_date = ((bool) $coursecompletion->timecompleted) && ($coursecompletion->timecompleted <= $p["bydate"]);
$subcrit["requirements"]["bydate"]["completed"] = (bool) $check_date;
$checkdate = ((bool) $coursecompletion->timecompleted) && ($coursecompletion->timecompleted <= $p["bydate"]);
$subcrit["requirements"]["bydate"]["completed"] = (bool) $checkdate;
}
$subcrit["completed"] = $coursecompleted && $check_grade && $check_date;
$subcrit["completed"] = $coursecompleted && $checkgrade && $checkdate;
}
$list[] = $subcrit;
}
@ -596,12 +592,12 @@ class badgeinfo {
$fields = profile_get_custom_fields();
// Get formatted field name if such field exists.
$fieldname = isset($fields[$p['field']]->name) ?
format_string($fields[$p['field']]->name) : null;
format_string($fields[$p['field']]->name): null;
} else {
$fieldname = \core_user\fields::get_display_name($p['field']);
}
if(!$fieldname) {
if (!$fieldname) {
$title = get_string('error:nosuchfield', 'badges');
$description = get_string('error:nosuchfield', 'badges');
} else {
@ -612,10 +608,10 @@ class badgeinfo {
$subcrit = [
"title" => $title,
"description" => $description,
"requirements" => []
"requirements" => [],
];
if(isset($userid)) {
if (isset($userid)) {
$join = '';
$where = '';
$sqlparams = [ 'userid'=> $userid];
@ -643,8 +639,8 @@ class badgeinfo {
}
} else if ($crit->criteriatype == BADGE_CRITERIA_TYPE_BADGE) {
foreach ($crit->params as $p) {
$badgename = $DB->get_field('badge', 'name', array('id' => $p['badge']));
if(!$badgename) {
$badgename = $DB->get_field('badge', 'name', ['id' => $p['badge']]);
if (!$badgename) {
$title = get_string('error:nosuchbadge', 'badges');
$description = get_string('error:nosuchbadge', 'badges');
} else {
@ -655,15 +651,15 @@ class badgeinfo {
$subcrit = [
"title" => $title,
"description" => $description,
"link" => (new \moodle_url($CFG->wwwroot."/badges/overview.php",["id" => $p["badge"]]))->out(),
"requirements" => []
"link" => (new \moodle_url($CFG->wwwroot."/badges/overview.php", ["id" => $p["badge"]]))->out(),
"requirements" => [],
];
if(isset($userid)) {
$badge = $DB->get_record('badge', array('id' => $p['badge']));
if (isset($userid)) {
$badge = $DB->get_record('badge', ['id' => $p['badge']]);
// See if the user has earned this badge.
if($badge) {
$awarded = $DB->get_record('badge_issued', array('badgeid' => $p['badge'], 'userid' => $userid));
if ($badge) {
$awarded = $DB->get_record('badge_issued', ['badgeid' => $p['badge'], 'userid' => $userid]);
$awarded = isset($awarded);
} else {
$awarded = false;
@ -674,8 +670,8 @@ class badgeinfo {
}
} else if ($crit->criteriatype == BADGE_CRITERIA_TYPE_COHORT) {
foreach ($crit->params as $p) {
$cohortname = $DB->get_field('cohort', 'name', array('id' => $p['cohort']));
if(!$cohortname) {
$cohortname = $DB->get_field('cohort', 'name', ['id' => $p['cohort']]);
if (!$cohortname) {
$title = get_string('error:nosuchcohort', 'badges');
$description = get_string('error:nosuchcohort', 'badges');
} else {
@ -686,11 +682,11 @@ class badgeinfo {
$subcrit = [
"title" => $title,
"description" => $description,
"requirements" => []
"requirements" => [],
];
if(isset($userid)) {
$cohort = $DB->get_record('cohort', array('id' => $p['cohort']));
if (isset($userid)) {
$cohort = $DB->get_record('cohort', ['id' => $p['cohort']]);
$ismember = (bool) \cohort_is_member($cohort->id, $userid);
$subcrit["completed"] = $ismember;
}
@ -700,11 +696,11 @@ class badgeinfo {
foreach ($crit->params as $p) {
$competency = new \core_competency\competency($p['competency']);
$competency->set('description', ''); // Will use 'short' description.
/* Below must be one of the most convoluted ways of calling tool_lp_render_competency_summary.
Since I'm pretty sure it's not an actually good idea to implement <plugin>_render_competency_summary
Since I'm pretty sure it's not an actually good idea to implement <plugin>_render_competency_summary
in a custom plugin, even though the system appearently allows you to add competency descriptions,
it's probably a case of premature optimization. Still, since this is the way that
it's probably a case of premature optimization. Still, since this is the way that
'badges/criteria/award_criteria_competency.php does it, we'll copy its example, to avoid
differences in display....
*/
@ -720,34 +716,34 @@ class badgeinfo {
}
\core_competency\api::check_enabled();
if(count($output) < 1) {
if (count($output) < 1) {
$title = get_string('error:nosuchcompetency', 'local_treestudyplan');
$description = get_string('error:nosuchcompetency', 'local_treestudyplan');
} else {
/* Might as wel implode the output, just in case someone was actually stupid enough to implement
/* Might as wel implode the output, just in case someone was actually stupid enough to implement
<plugin>_render_competency_summary in a custom plugin...
*/
$title = implode(" ",$output);
$description = implode(" ",$output);
$title = implode(" ", $output);
$description = implode(" ", $output);
}
$subcrit = [
"title" => $title,
"description" => $description,
"requirements" => []
"requirements" => [],
];
if(isset($userid)) {
if (isset($userid)) {
/* Slightly modified from award_criteria_competency.php::review()
to use criteria api class instead of direct calls....
*/
$proficiency = false;
$badge = $DB->get_record('badge', array('id' => $crit->badgeid));
$badge = $DB->get_record('badge', ['id' => $crit->badgeid]);
if ($badge->type == BADGE_TYPE_SITE) {
$uc = \core_competency\api::get_user_competency($userid,$p['competency']);
$uc = \core_competency\api::get_user_competency($userid, $p['competency']);
$proficiency = $uc->get('proficiency');
} else if ($badge->type == BADGE_TYPE_COURSE) {
$uc = \core_competency\api::get_user_competency_in_course($badge->courseid,$userid,$p['competency']);
$uc = \core_competency\api::get_user_competency_in_course($badge->courseid, $userid, $p['competency']);
$proficiency = $uc->get('proficiency');
}
@ -755,7 +751,7 @@ class badgeinfo {
}
$list[] = $subcrit;
}
}
}
return $list;
}
@ -767,17 +763,17 @@ class badgeinfo {
* @param bool $active Only list active badges
* @return array of int
*/
public static function find_badges_by_course_relation($course,$search='', $active=false) {
public static function find_badges_by_course_relation($course, $search='', $active=false) {
global $DB;
if (is_int($course)) {
$courseid = $course;
} else if(is_object($course)) {
} else if (is_object($course)) {
$courseid = $course->id;
} else {
throw new \moodle_exception("\$course argument must be course id or course object","local_treestudyplan");
throw new \moodle_exception("\$course argument must be course id or course object", "local_treestudyplan");
}
/*
/*
$crit->citeriatype = BADGE_CRITERIA_TYPE_COURSE
$badge->params[0] = ["course"=> $courseid]
$crit->citeriatype = BADGE_CRITERIA_TYPE_COURSESET
@ -793,41 +789,38 @@ class badgeinfo {
$basesqlparams = ['courseid' => $courseid];
if (strlen($search) > 0) {
$conditions .= " AND ".$DB->sql_like('b.name',':search');
$conditions .= " AND ".$DB->sql_like('b.name', ':search');
$basesqlparams["search"] = "%$search%";
}
if ($active) {
[$insql, $inparams] = $DB->get_in_or_equal([BADGE_STATUS_ACTIVE, BADGE_STATUS_ACTIVE_LOCKED],SQL_PARAMS_NAMED);
[$insql, $inparams] = $DB->get_in_or_equal([BADGE_STATUS_ACTIVE, BADGE_STATUS_ACTIVE_LOCKED], SQL_PARAMS_NAMED);
$conditions .= " AND b.status $insql";
$basesqlparams = array_merge($basesqlparams,$inparams);
$basesqlparams = array_merge($basesqlparams, $inparams);
}
[$ctypesql, $ctypeinparams] = $DB->get_in_or_equal([BADGE_CRITERIA_TYPE_COURSESET,BADGE_CRITERIA_TYPE_COURSE],SQL_PARAMS_NAMED);
[$ctypesql, $ctypeinparams] = $DB->get_in_or_equal([BADGE_CRITERIA_TYPE_COURSESET, BADGE_CRITERIA_TYPE_COURSE], SQL_PARAMS_NAMED);
$sqlparams = array_merge($basesqlparams, $ctypeinparams);
$sql = "SELECT DISTINCT b.id from {badge} b
$sql = "SELECT DISTINCT b.id from {badge} b
INNER JOIN {badge_criteria} crit ON b.id = crit.badgeid
INNER JOIN {badge_criteria_param} p on p.critid = crit.id
WHERE p.value = :courseid AND crit.criteriatype $ctypesql $conditions";
$courserelids = $DB->get_fieldset_sql($sql, $sqlparams);
[$ctypesql, $ctypeinparams] = $DB->get_in_or_equal([BADGE_CRITERIA_TYPE_COMPETENCY],SQL_PARAMS_NAMED);
$sqlparams = array_merge($basesqlparams,$ctypeinparams);
$sql = "SELECT DISTINCT b.id from {badge} b
[$ctypesql, $ctypeinparams] = $DB->get_in_or_equal([BADGE_CRITERIA_TYPE_COMPETENCY], SQL_PARAMS_NAMED);
$sqlparams = array_merge($basesqlparams, $ctypeinparams);
$sql = "SELECT DISTINCT b.id from {badge} b
INNER JOIN {badge_criteria} crit ON b.id = crit.badgeid
INNER JOIN {badge_criteria_param} p on p.critid = crit.id
INNER JOIN {competency_coursecomp} cc on cc.competencyid = p.value
WHERE cc.courseid = :courseid AND crit.criteriatype $ctypesql $conditions";
$competencyrelids = $DB->get_fieldset_sql($sql,$sqlparams);
$competencyrelids = $DB->get_fieldset_sql($sql, $sqlparams);
$badgeids = [];
foreach ([$courserelids,$competencyrelids] as $list) {
foreach ([$courserelids, $competencyrelids] as $list) {
foreach ($list as $id) {
$badgeids[] = $id;
}
@ -843,38 +836,37 @@ class badgeinfo {
* @param bool $active Only list active badges
* @return array of int
*/
public static function find_course_badges($course,$search='', $active=false) {
public static function find_course_badges($course, $search='', $active=false) {
global $DB;
if (is_int($course)) {
$courseid = $course;
} else if(is_object($course)) {
} else if (is_object($course)) {
$courseid = $course->id;
} else {
throw new \moodle_exception("\$course argument must be course id or course object","local_treestudyplan");
throw new \moodle_exception("\$course argument must be course id or course object", "local_treestudyplan");
}
$search = trim($search);
$conditions = "";
$basesqlparams = ['courseid' => $courseid];
if (strlen($search) > 0) {
$conditions .= " AND ".$DB->sql_like('b.name',':search');
$conditions .= " AND ".$DB->sql_like('b.name', ':search');
$basesqlparams["search"] = "%$search%";
}
if ($active) {
[$insql, $inparams] = $DB->get_in_or_equal([BADGE_STATUS_ACTIVE, BADGE_STATUS_ACTIVE_LOCKED]);
$conditions .= " AND b.status $insql";
$basesqlparams = array_merge($basesqlparams,$inparams);
$basesqlparams = array_merge($basesqlparams, $inparams);
}
// Get all course badges for this course
$badgesids = [];
$sql = "SELECT DISTINCT b.id from {badge} b
$sql = "SELECT DISTINCT b.id from {badge} b
WHERE b.courseid = :courseid AND $conditions";
$badgesids = $DB->get_fieldset_sql($sql,$basesqlparams);
$badgesids = $DB->get_fieldset_sql($sql, $basesqlparams);
return $badgesids;
}
@ -885,23 +877,23 @@ class badgeinfo {
* @param mixed $search=""
* @param mixed $active=false
* @param mixed $includecoursebadges=true
*
*
* @return array of badgeinfo
*
*
*/
public static function find_page_related_badges(studyplanpage $page,$search="",$active=false,$includecoursebadges=true) {
public static function find_page_related_badges(studyplanpage $page, $search="", $active=false, $includecoursebadges=true) {
$badgeids = [];
foreach (studyline::find_page_children($page) as $line) {
foreach (studyitem::find_studyline_children($line) as $item) {
if ($item->type() == studyitem::COURSE && $item->courseid() ) {
$courseid = $item->courseid();
$relatedbadges = badgeinfo::find_badges_by_course_relation($courseid,$search,$active);
$relatedbadges = badgeinfo::find_badges_by_course_relation($courseid, $search, $active);
foreach ($relatedbadges as $id) {
$badgeids[] = $id;
}
if ($includecoursebadges) {
$coursebadges = badgeinfo::find_course_badges($courseid,$search,$active);
$coursebadges = badgeinfo::find_course_badges($courseid, $search, $active);
foreach ($coursebadges as $id) {
$badgeids[] = $id;
}
@ -914,7 +906,7 @@ class badgeinfo {
$badges[] = new self(new badge($id));
}
usort($badges,function($a,$b) {
usort($badges, function($a, $b) {
return $a->name() <=> $b->name();
});
@ -929,38 +921,37 @@ class badgeinfo {
*/
public static function search_site_badges($search='', $active=false) {
global $DB;
$search = trim($search);
$conditions = "TRUE";
$basesqlparams = ['type' => \BADGE_TYPE_SITE];
if (strlen($search) > 0) {
$conditions .= " AND ".$DB->sql_like('b.name',':search');
$conditions .= " AND ".$DB->sql_like('b.name', ':search');
$basesqlparams["search"] = "%$search%";
}
if ($active) {
[$insql, $inparams] = $DB->get_in_or_equal([BADGE_STATUS_ACTIVE, BADGE_STATUS_ACTIVE_LOCKED]);
$conditions .= " AND b.status $insql";
$basesqlparams = array_merge($basesqlparams,$inparams);
$basesqlparams = array_merge($basesqlparams, $inparams);
}
// Get all course badges for this course
$sql = "SELECT DISTINCT b.id from {badge} b
$sql = "SELECT DISTINCT b.id from {badge} b
WHERE $conditions";
$badgeids = $DB->get_fieldset_sql($sql,$basesqlparams);
$badgeids = $DB->get_fieldset_sql($sql, $basesqlparams);
$badges = [];
foreach (array_unique($badgeids) as $id) {
$badges[] = new self(new badge($id));
}
usort($badges,function($a,$b) {
usort($badges, function($a, $b) {
return $a->name() <=> $b->name();
});
return $badges;
}
}

View File

@ -92,8 +92,8 @@ class cascadecohortsync {
require_once($CFG->dirroot.'/group/lib.php');
// Check to see if the group name already exists in this course.
if ($DB->record_exists('groups', array('name' => $groupname, 'courseid' => $courseid))) {
$group = $DB->get_record('groups', array('name' => $groupname, 'courseid' => $courseid));
if ($DB->record_exists('groups', ['name' => $groupname, 'courseid' => $courseid])) {
$group = $DB->get_record('groups', ['name' => $groupname, 'courseid' => $courseid]);
return $group->id;
}
// The named group doesn't exist, so create a new one in the course.
@ -129,7 +129,7 @@ class cascadecohortsync {
return $list;
}
/**
/**
* Remove this studyplan reference from cohort sync
* @param object $enrollinstance
*/
@ -175,17 +175,16 @@ class cascadecohortsync {
// Find the study lines associated to this studyplan.
$lines = $this->studyplan->get_all_studylines();
foreach($lines as $line) {
$this->syncline($line);
}
}
/**
/**
* Enroll all cohorts associated to the studyplan in the courses linked to the specified study line
*/
public function syncline(studyline $line){
public function syncline(studyline $line) {
global $DB;
// Find the courses that need to be synced to the associated cohorts.
$courseids = $line->get_linked_course_ids();
@ -201,7 +200,7 @@ class cascadecohortsync {
$instanceparams = ['courseid' => $courseid, 'enrol' => 'manual'];
if (!($instance = $DB->get_record('enrol', $instanceparams))) {
if ($instanceid = $this->manualenrol->add_default_instance($course)) {
$instance = $DB->get_record('enrol', array('id' => $instanceid));
$instance = $DB->get_record('enrol', ['id' => $instanceid]);
} else {
// Instance not added for some reason, so report an error somewhere.
// (or not).
@ -297,7 +296,7 @@ class cascadecohortsync {
// Also record the (as of yet only) studyplans id requiring this association.
// In the customtext4 field in json format.
$instance = $DB->get_record('enrol', array('id' => $instanceid));
$instance = $DB->get_record('enrol', ['id' => $instanceid]);
$this->enrol->update_instance($instance, (object)["customtext4" => json_encode([(int)($this->studyplanid)])]);
// Successfully added a valid new instance, so now instantiate it.
@ -323,7 +322,7 @@ class cascadecohortsync {
if (get_config("local_treestudyplan", "csync_autoremove")) {
// Only try the autoremove if the option is enabled.
foreach($this->list_cohortsyncs($courseid) as $instance){
foreach($this->list_cohortsyncs($courseid) as $instance) {
// Only check the records that have studyplan information in the customtext4 field.
// First check if the cohort is not one of the cohort id's we have associated.
if (!in_array($instance->customint1, $this->cohortids)) {

View File

@ -58,7 +58,6 @@ class cascadeusersync {
$this->userids = $this->studyplan->get_linked_user_ids();
}
/**
* Enroll all users associated to the studyplan in the courses linked to this studyplan
*/
@ -84,33 +83,33 @@ class cascadeusersync {
}
}
/**
/**
* Enroll all cohorts associated to the studyplan in the courses linked to the specified study line
*/
public function syncline(studyline $line){
public function syncline(studyline $line) {
// Find the courses that need to be synced to the associated cohorts.
$courseids = $line->get_linked_course_ids();
if ($line->enrollable()) {
$lineuids = $line->get_enrolled_userids();
// Next, for each course that is linked:.
foreach ($courseids as $courseid) {
$this->perform_enrol($courseid,$lineuids);
$this->perform_enrol($courseid, $lineuids);
// We do not do any autoremoval for user syncs, to avoid students losing access to the course data.
}
} else {
// Next, for each course that is linked:.
foreach ($courseids as $courseid) {
$this->perform_enrol($courseid,$this->userids);
$this->perform_enrol($courseid, $this->userids);
// We do not do any autoremoval for user syncs, to avoid students losing access to the course data.
}
}
}
/** Enrol a list of users into a specific course
*
*
*
*
*/
private function perform_enrol($courseid,$userids) {
private function perform_enrol($courseid, $userids) {
global $DB;
$course = \get_course($courseid);
if (count($userids) > 0) {
@ -118,7 +117,7 @@ class cascadeusersync {
$instanceparams = ['courseid' => $courseid, 'enrol' => 'manual'];
if (!($instance = $DB->get_record('enrol', $instanceparams))) {
if ($instanceid = $this->enrol->add_default_instance($course)) {
$instance = $DB->get_record('enrol', array('id' => $instanceid));
$instance = $DB->get_record('enrol', ['id' => $instanceid]);
} else {
// Instance not added for some reason, so report an error somewhere.
// (or not).

View File

@ -75,7 +75,7 @@ class completion {
* Webservice structure for basic info
* @param int $value Webservice requirement constant
*/
public static function structure($value = VALUE_REQUIRED) : \external_description {
public static function structure($value = VALUE_REQUIRED): \external_description {
return new \external_value( PARAM_TEXT,
'completion state (failed|incomplete|pending|progress|completed|good|excellent)',
$value);

View File

@ -69,7 +69,7 @@ class completionscanner {
* Check if a certain activity type is supported for scanning pending results
* @param string $mod name of activity module
*/
public static function supported($mod) : bool {
public static function supported($mod): bool {
if (!array_key_exists($mod, self::$modsupported)) {
self::$modsupported[$mod] = class_exists("\local_treestudyplan\\local\\ungradedscanners\\{$mod}_scanner");
}
@ -82,7 +82,7 @@ class completionscanner {
* @param int[] $studentlist Array of student id's
* @return int[]
*/
private function filter_studentlist(array $studentlist) : array {
private function filter_studentlist(array $studentlist): array {
$coursestudents = courseinfo::get_course_students($this->courseid);
return array_intersect($studentlist, $coursestudents);
}
@ -130,7 +130,7 @@ class completionscanner {
* Check if the criteria this scanner scans has pending submissions for a specific user
* @param int $userid ID of the user to check for
*/
public function pending($userid) : bool {
public function pending($userid): bool {
if (!array_key_exists($userid, $this->pendingcache)) {
if ($this->scanner === null) {
$this->pendingcache[$userid] = false;
@ -145,7 +145,7 @@ class completionscanner {
* Webservice structure for basic info
* @param int $value Webservice requirement constant
*/
public static function structure($value = VALUE_OPTIONAL) : \external_description {
public static function structure($value = VALUE_OPTIONAL): \external_description {
return new \external_single_structure([
"ungraded" => new \external_value(PARAM_INT, 'number of ungraded submissions'),
"completed" => new \external_value(PARAM_INT, 'number of completed students'),
@ -159,7 +159,7 @@ class completionscanner {
* Webservice model for basic info
* @param int[]|null $studentlist Array of student userids to use for checking. Leave empty to use all course students
*/
public function model(array $studentlist = null) : array {
public function model(array $studentlist = null): array {
/*
If an array of students is provided (usually the case if called from a courecompletioninfo object),
make sure to filter it out, so only the students enrolled in the course are included.. Otherwise

View File

@ -46,7 +46,7 @@ class contextinfo {
* Describe the result for the webservice model
* @param int $value Webservice requirement constant
*/
public static function structure($value = VALUE_REQUIRED) : \external_description {
public static function structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"name" => new \external_value(PARAM_TEXT, 'context name'),
"shortname" => new \external_value(PARAM_TEXT, 'context short name'),
@ -61,7 +61,6 @@ class contextinfo {
*/
public function model() {
return [
"name" => $this->context->get_context_name(false, false),
"shortname" => $this->context->get_context_name(false, true),
@ -75,7 +74,7 @@ class contextinfo {
* @param $short Use short names of contexts in path
* @return array of context path names
*/
public function path($short=false){
public function path($short=false) {
if ($short) {
return array_map(function($c) {
return \context::instance_by_id($c)->get_context_name(false, true);
@ -92,11 +91,10 @@ class contextinfo {
* @param $short Use short names of contexts in path
* @return string Concatenated string of paths
*/
public function pathstr($short=false){
public function pathstr($short=false) {
return implode(" / ", $this->path($short));
}
/**
* Make new Contextinfo for context id
* @param int $contextid Context id

View File

@ -123,7 +123,7 @@ class corecompletioninfo {
* Webservice editor structure for completion_item
* @param int $value Webservice requirement constant
*/
public static function completion_item_editor_structure($value = VALUE_REQUIRED) : \external_description {
public static function completion_item_editor_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'criteria id', VALUE_OPTIONAL),
"title" => new \external_value(PARAM_RAW, 'name of subitem', VALUE_OPTIONAL),
@ -142,7 +142,7 @@ class corecompletioninfo {
* Webservice editor structure for completion_type
* @param int $value Webservice requirement constant
*/
public static function completion_type_editor_structure($value = VALUE_REQUIRED) : \external_description {
public static function completion_type_editor_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"items" => new \external_multiple_structure(self::completion_item_editor_structure(), 'subitems', VALUE_OPTIONAL),
"title" => new \external_value(PARAM_RAW, 'optional title', VALUE_OPTIONAL),
@ -160,7 +160,7 @@ class corecompletioninfo {
* Webservice structure for editor info
* @param int $value Webservice requirement constant
*/
public static function editor_structure($value = VALUE_REQUIRED) : \external_description {
public static function editor_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"conditions" => new \external_multiple_structure(self::completion_type_editor_structure(), 'completion conditions'),
"aggregation" => new \external_value(PARAM_TEXT, 'completion aggregation ["all", "any"]'),
@ -172,7 +172,7 @@ class corecompletioninfo {
* Webservice user view structure for completion_item
* @param int $value Webservice requirement constant
*/
public static function completion_item_user_structure($value = VALUE_REQUIRED) : \external_description {
public static function completion_item_user_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of completion', VALUE_OPTIONAL),
"title" => new \external_value(PARAM_RAW, 'name of subitem', VALUE_OPTIONAL),
@ -198,7 +198,7 @@ class corecompletioninfo {
* Webservice user view structure for completion_type
* @param int $value Webservice requirement constant
*/
public static function completion_type_user_structure($value = VALUE_REQUIRED) : \external_description {
public static function completion_type_user_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"items" => new \external_multiple_structure(self::completion_item_user_structure(), 'subitems', VALUE_OPTIONAL),
"title" => new \external_value(PARAM_RAW, 'optional title', VALUE_OPTIONAL),
@ -217,7 +217,7 @@ class corecompletioninfo {
* Webservice structure for userinfo
* @param int $value Webservice requirement constant
*/
public static function user_structure($value = VALUE_REQUIRED) : \external_description {
public static function user_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"progress" => new \external_value(PARAM_INT, 'completed sub-conditions'),
"enabled" => new \external_value(PARAM_BOOL, "whether completion is enabled here"),
@ -314,10 +314,10 @@ class corecompletioninfo {
} else {
$details['criteria'] = $cm->get_formatted_name();
}
// Set title based on cm formatted name
// Set title based on cm formatted name
$title = $cm->get_formatted_name();
// Build requirements.
$details['requirement'] = array();
$details['requirement'] = [];
if ($cm->completion == COMPLETION_TRACKING_MANUAL) {
$details['requirement'][] = get_string('markingyourselfcomplete', 'completion');
@ -349,8 +349,8 @@ class corecompletioninfo {
$displaytype = \grade_get_setting($this->course->id, 'displaytype', $CFG->grade_displaytype);
$gradepass = $criteria->gradepass;
// Find grade item for course result.
$gi = new \grade_item(['courseid' => $this->course->id,'itemtype' => 'course']);
$displaygrade = \grade_format_gradevalue($gradepass,$gi,true,$displaytype,1);
$gi = new \grade_item(['courseid' => $this->course->id, 'itemtype' => 'course']);
$displaygrade = \grade_format_gradevalue($gradepass, $gi, true, $displaytype, 1);
$details = [
"type" => get_string('coursegrade', 'completion'),
"criteria" => get_string('graderequired', 'completion'),
@ -359,7 +359,7 @@ class corecompletioninfo {
.": ".$displaygrade,
"status" => "",
];
$title = get_string('graderequired','completion').': '.$displaygrade;
$title = get_string('graderequired', 'completion').': '.$displaygrade;
} else if ($type == COMPLETION_CRITERIA_TYPE_ROLE) {
$details = [
@ -371,7 +371,7 @@ class corecompletioninfo {
} else if ($type == COMPLETION_CRITERIA_TYPE_COURSE) {
$prereq = get_course($criteria->courseinstance);
$coursecontext = \context_course::instance($prereq->id, MUST_EXIST);
$fullname = format_string($prereq->fullname, true, array('context' => $coursecontext));
$fullname = format_string($prereq->fullname, true, ['context' => $coursecontext]);
$details = [
"type" => $criteria->get_title(),
"criteria" => '<a href="'.$CFG->wwwroot.'/course/view.php?id='.
@ -394,7 +394,7 @@ class corecompletioninfo {
// Only add the items list if we actually have items...
$cinfo["items"][] = [
"id" => $criteria->id,
"title" => isset($title)?$title:$criteria->get_title_detailed(),
"title" => isset($title) ? $title : $criteria->get_title_detailed(),
"details" => $details,
"progress" => $scanner->model($studentlist),
];
@ -479,7 +479,7 @@ class corecompletioninfo {
"details" => $criteria->get_details($completion),
"completed" => $completion->is_complete(), // Make sure to override for activi.
"status" => self::completion_handle(
$completion->is_complete() ? COMPLETION_COMPLETE : COMPLETION_INCOMPLETE),
$completion->is_complete() ? COMPLETION_COMPLETE : COMPLETION_INCOMPLETE),
];
if ($type == COMPLETION_CRITERIA_TYPE_ACTIVITY) {
@ -544,7 +544,7 @@ class corecompletioninfo {
$rq = floatval($iinfo['details']['requirement']);
$iinfo['details']['requirement'] = $this->format_course_grade($rq);
;
$iinfo["status"] = $completion->is_complete() ? "complete-pass" : "complete-fail";
$iinfo["status"] = $completion->is_complete() ? "complete-pass" : "complete-fail";
if ($cinfo["status"] == "incomplete") {
$cinfo["status"] = "progress";
}
@ -603,7 +603,7 @@ class corecompletioninfo {
$result = new \stdClass;
// Check if the final grade is available and numeric (safety check).
if (!empty($grade) && !empty($grade->finalgrade) && is_numeric($grade->finalgrade)) {
$result->grade = \grade_format_gradevalue($grade->finalgrade,$gi,true,null,1);
$result->grade = \grade_format_gradevalue($grade->finalgrade, $gi, true, null, 1);
$result->feedback = \trim($grade->feedback);
$result->pending = (new gradingscanner($gi))->pending($userid);
} else {
@ -629,7 +629,7 @@ class corecompletioninfo {
'courseid' => $this->course->id]);
if ($gi) {
return \grade_format_gradevalue($grade,$gi,true,null,1);
return \grade_format_gradevalue($grade, $gi, true, null, 1);
}
return "x"; // Course cannot be graded (Shouldn't be happening, but still....).
@ -740,7 +740,7 @@ class corecompletioninfo {
$result = new \stdClass;
$result->count = $count;
$result->completed = $completed;
$result->percentage = ($count > 0) ? (($completed / $count) * 100) : 0;
$result->percentage = ($count > 0) ? (($completed / $count) * 100): 0;
return $result;
}

View File

@ -69,7 +69,7 @@ class coursecompetencyinfo {
* Webservice structure for completion stats
* @param int $value Webservice requirement constant
*/
public static function completionstats_structure($value = VALUE_OPTIONAL) : \external_description {
public static function completionstats_structure($value = VALUE_OPTIONAL): \external_description {
return new \external_single_structure([
"ungraded" => new \external_value(PARAM_INT, 'number of ungraded submissions'),
"completed" => new \external_value(PARAM_INT, 'number of completed students'),
@ -79,7 +79,7 @@ class coursecompetencyinfo {
], "details about gradable submissions", $value);
}
protected static function completionstats($stats){
protected static function completionstats($stats) {
return [
"students" => $stats->count,
"completed" => 0,
@ -93,7 +93,7 @@ class coursecompetencyinfo {
* Generic competency info structure for individual competency stats
* @param $recurse True if child competencies may be included
*/
public static function competencyinfo_structure($recurse=true) : \external_description {
public static function competencyinfo_structure($recurse=true): \external_description {
$struct = [
"id" => new \external_value(PARAM_INT, 'competency id'),
"title" => new \external_value(PARAM_RAW, 'competency display title'),
@ -106,22 +106,22 @@ class coursecompetencyinfo {
"title" => new \external_value(PARAM_RAW),
"type" => new \external_value(PARAM_TEXT),
]), 'competency path'),
'ucid' => new \external_value(PARAM_INT, 'user competencyid',VALUE_OPTIONAL),
'ucid' => new \external_value(PARAM_INT, 'user competencyid', VALUE_OPTIONAL),
"grade" => new \external_value(PARAM_TEXT, 'competency grade', VALUE_OPTIONAL),
"coursegrade" => new \external_value(PARAM_TEXT, 'course competency grade', VALUE_OPTIONAL),
"proficient" => new \external_value(PARAM_BOOL, 'competency proficiency',VALUE_OPTIONAL),
"courseproficient" => new \external_value(PARAM_BOOL, 'course competency proficiency',VALUE_OPTIONAL),
"needreview" => new \external_value(PARAM_BOOL, 'waiting for review or review in progress',VALUE_OPTIONAL),
"proficient" => new \external_value(PARAM_BOOL, 'competency proficiency', VALUE_OPTIONAL),
"courseproficient" => new \external_value(PARAM_BOOL, 'course competency proficiency', VALUE_OPTIONAL),
"needreview" => new \external_value(PARAM_BOOL, 'waiting for review or review in progress', VALUE_OPTIONAL),
"completionstats" => static::completionstats_structure(VALUE_OPTIONAL),
"count" => new \external_value(PARAM_INT, 'number of students in stats',VALUE_OPTIONAL),
"required" => new \external_value(PARAM_BOOL, 'if required in parent competency rule',VALUE_OPTIONAL),
"points" => new \external_value(PARAM_INT, 'number of points in parent competency rule',VALUE_OPTIONAL),
"progress" => new \external_value(PARAM_INT, 'number completed child competencies/points',VALUE_OPTIONAL),
"count" => new \external_value(PARAM_INT, 'number of child competencies/points required',VALUE_OPTIONAL),
"feedback" => new \external_value(PARAM_RAW, 'feedback provided with this competency',VALUE_OPTIONAL),
"count" => new \external_value(PARAM_INT, 'number of students in stats', VALUE_OPTIONAL),
"required" => new \external_value(PARAM_BOOL, 'if required in parent competency rule', VALUE_OPTIONAL),
"points" => new \external_value(PARAM_INT, 'number of points in parent competency rule', VALUE_OPTIONAL),
"progress" => new \external_value(PARAM_INT, 'number completed child competencies/points', VALUE_OPTIONAL),
"count" => new \external_value(PARAM_INT, 'number of child competencies/points required', VALUE_OPTIONAL),
"feedback" => new \external_value(PARAM_RAW, 'feedback provided with this competency', VALUE_OPTIONAL),
];
if($recurse) {
$struct["children"] = new \external_multiple_structure(self::competencyinfo_structure(false),'child competencies',VALUE_OPTIONAL);
if ($recurse) {
$struct["children"] = new \external_multiple_structure(self::competencyinfo_structure(false), 'child competencies', VALUE_OPTIONAL);
}
return new \external_single_structure($struct, 'course completion info');
}
@ -130,11 +130,11 @@ class coursecompetencyinfo {
* Webservice structure for editor info
* @param int $value Webservice requirement constant
*/
public static function editor_structure($value = VALUE_REQUIRED) : \external_description {
public static function editor_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"competencies" => new \external_multiple_structure(self::competencyinfo_structure(), 'competencies'),
"proficient" => new \external_value(PARAM_INT, 'number of proficient user/competencys ',VALUE_OPTIONAL),
"total" => new \external_value(PARAM_INT, 'total number of gradable user/competencies',VALUE_OPTIONAL),
"proficient" => new \external_value(PARAM_INT, 'number of proficient user/competencys ', VALUE_OPTIONAL),
"total" => new \external_value(PARAM_INT, 'total number of gradable user/competencies', VALUE_OPTIONAL),
], 'course completion info', $value);
}
@ -142,11 +142,11 @@ class coursecompetencyinfo {
* Webservice structure for userinfo
* @param int $value Webservice requirement constant
*/
public static function user_structure($value = VALUE_REQUIRED) : \external_description {
public static function user_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"competencies" => new \external_multiple_structure(self::competencyinfo_structure(), 'competencies'),
"progress" => new \external_value(PARAM_INT, 'number completed competencies'),
"count" => new \external_value(PARAM_INT, 'number of competencies',VALUE_OPTIONAL),
"count" => new \external_value(PARAM_INT, 'number of competencies', VALUE_OPTIONAL),
], 'course completion info', $value);
}
@ -154,14 +154,14 @@ class coursecompetencyinfo {
* Create basic competency information model from competency
* @param Object $competency
*/
private function competencyinfo_model($competency,$userid=null) : array {
$displayfield = get_config("local_treestudyplan","competency_displayname");
$detailfield = get_config("local_treestudyplan","competency_detailfield");
private function competencyinfo_model($competency, $userid=null): array {
$displayfield = get_config("local_treestudyplan", "competency_displayname");
$detailfield = get_config("local_treestudyplan", "competency_detailfield");
$headingfield = ($displayfield != 'description')?$displayfield:"shortname";
$framework = $competency->get_framework();
$heading = $framework->get($headingfield);
if(empty(trim($heading))) {
if (empty(trim($heading))) {
$heading = $framework->get('shortname'); // Fall back to shortname if heading field is empty
}
$path = [[
@ -173,7 +173,7 @@ class coursecompetencyinfo {
foreach ($competency->get_ancestors() as $c) {
$competencypath[] = $c->get('shortname');
$heading = $c->get($headingfield);
if(empty(trim($heading))) {
if (empty(trim($heading))) {
$heading = $c->get('shortname'); // Fall back to shortname if heading field is empty
}
$path[] = [
@ -183,9 +183,9 @@ class coursecompetencyinfo {
'type' => 'competency',
];
}
$heading = $competency->get($headingfield);
if(empty(trim($heading))) {
if (empty(trim($heading))) {
$heading = $competency->get('shortname'); // Fall back to shortname if heading field is empty
}
$path[] = [
@ -196,7 +196,7 @@ class coursecompetencyinfo {
];
$title = $competency->get($displayfield);
if(empty(trim($title))) {
if (empty(trim($title))) {
$title = $competency->get('shortname'); // Fall back to shortname if heading field is empty
}
$model = [
@ -224,12 +224,12 @@ class coursecompetencyinfo {
$count = 0;
$nproficient = 0;
$cis = [];
foreach($coursecompetencies as $c) {
$ci = $this->competencyinfo_model($c);
if(!empty($studentlist)){
$stats = $this->proficiency_stats($c,$studentlist);
if (!empty($studentlist)) {
$stats = $this->proficiency_stats($c, $studentlist);
$count += $stats->count;
$nproficient += $stats->nproficient;
// Copy proficiency stats to model.
@ -243,10 +243,10 @@ class coursecompetencyinfo {
$rule = $c->get_rule_object();
$ruleoutcome = $c->get('ruleoutcome');
if($rule && $ruleoutcome != competency::OUTCOME_NONE) {
if ($rule && $ruleoutcome != competency::OUTCOME_NONE) {
$ruletext = $rule->get_name();
$ruleconfig = $c->get('ruleconfig');
if ($ruleoutcome == competency::OUTCOME_EVIDENCE) {
$outcometag = "evidence";
} else if ($ruleoutcome == competency::OUTCOME_COMPLETE) {
@ -256,35 +256,35 @@ class coursecompetencyinfo {
} else {
$outcometag = "none";
}
$ci["ruleoutcome"] = get_string("coursemodulecompetencyoutcome_{$outcometag}","core_competency");
$ci["ruleoutcome"] = get_string("coursemodulecompetencyoutcome_{$outcometag}", "core_competency");
if ($rule instanceof competency_rule_points) {
$ruleconfig = json_decode($ruleconfig);
$points = $ruleconfig->base->points;
// Make a nice map of the competency rule config
$crlist = [];
foreach($ruleconfig->competencies as $cr){
foreach($ruleconfig->competencies as $cr) {
$crlist[$cr->id] = $cr;
}
$ci["rule"] = $ruletext . " ({$points} ".get_string("points","core_grades").")";
$ci["rule"] = $ruletext . " ({$points} ".get_string("points", "core_grades").")";
} else {
$ci["rule"] = $ruletext;
}
// get one level of children
$dids = competency::get_descendants_ids($c);
if(count($dids) > 0) {
if (count($dids) > 0) {
$children = [];
foreach($dids as $did) {
$cc = new competency($did);
$cci = $this->competencyinfo_model($cc);
if(!empty($studentlist)){
$stats = $this->proficiency_stats($cc,$studentlist);
if (!empty($studentlist)) {
$stats = $this->proficiency_stats($cc, $studentlist);
$cci['completionstats'] = self::completionstats($stats);
}
if($rule instanceof competency_rule_points) {
if(array_key_exists($did,$crlist)) {
if ($rule instanceof competency_rule_points) {
if (array_key_exists($did, $crlist)) {
$cr = $crlist[$did];
$cci["points"] = (int) $cr->points;
$cci["required"] = (int) $cr->required;
@ -292,7 +292,7 @@ class coursecompetencyinfo {
}
$children[] = $cci;
}
$ci["children"] = $children;
}
}
@ -301,7 +301,7 @@ class coursecompetencyinfo {
$info = [
"competencies" => $cis,
];
if(!empty($studentlist)){
if (!empty($studentlist)) {
$info["proficient"] = $nproficient;
$info["total"] = $count;
}
@ -319,9 +319,9 @@ class coursecompetencyinfo {
$cis = [];
foreach ($competencies as $c) {
$ci = $this->competencyinfo_model($c,$userid);
$ci = $this->competencyinfo_model($c, $userid);
// Add user info if $userid is set.
$p = $this->proficiency($c,$userid);
$p = $this->proficiency($c, $userid);
// Copy proficiency info to model.
foreach ((array)$p as $key => $value) {
$ci[$key] = $value;
@ -332,15 +332,14 @@ class coursecompetencyinfo {
}
// Retrieve feedback.
$ci["feedback"] = $this->retrievefeedback($c,$userid);
$ci["feedback"] = $this->retrievefeedback($c, $userid);
$rule = $c->get_rule_object();
$ruleoutcome = $c->get('ruleoutcome');
if($rule && $ruleoutcome != competency::OUTCOME_NONE) {
if ($rule && $ruleoutcome != competency::OUTCOME_NONE) {
$ruletext = $rule->get_name();
$ruleconfig = $c->get('ruleconfig');
if ($ruleoutcome == competency::OUTCOME_EVIDENCE) {
$outcometag = "evidence";
} else if ($ruleoutcome == competency::OUTCOME_COMPLETE) {
@ -350,15 +349,15 @@ class coursecompetencyinfo {
} else {
$outcometag = "none";
}
$ci["ruleoutcome"] = get_string("coursemodulecompetencyoutcome_{$outcometag}","core_competency");
$ci["ruleoutcome"] = get_string("coursemodulecompetencyoutcome_{$outcometag}", "core_competency");
if ($rule instanceof competency_rule_points) {
$ruleconfig = json_decode($ruleconfig);
$pointsreq = $ruleconfig->base->points;
$points = 0;
// Make a nice map of the competency rule config
$crlist = [];
foreach($ruleconfig->competencies as $cr){
foreach($ruleconfig->competencies as $cr) {
$crlist[$cr->id] = $cr;
}
@ -366,27 +365,27 @@ class coursecompetencyinfo {
// get one level of children
$dids = competency::get_descendants_ids($c);
if(count($dids) > 0) {
if (count($dids) > 0) {
$dcount = 0;
$dprogress = 0;
$children = [];
foreach($dids as $did) {
$cc = new competency($did);
$cci = $this->competencyinfo_model($cc,$userid);
$cp = $p = $this->proficiency($cc,$userid);
$cci = $this->competencyinfo_model($cc, $userid);
$cp = $p = $this->proficiency($cc, $userid);
// Copy proficiency info to model.
foreach ((array)$cp as $key => $value) {
$cci[$key] = $value;
}
// Retrieve feedback.
$cci["feedback"] = $this->retrievefeedback($cc,$userid);
$cci["feedback"] = $this->retrievefeedback($cc, $userid);
if($rule instanceof competency_rule_points) {
if(array_key_exists($did,$crlist)) {
if ($rule instanceof competency_rule_points) {
if (array_key_exists($did, $crlist)) {
$cr = $crlist[$did];
$cci["points"] = (int) $cr->points;
$cci["required"] = (int) $cr->required;
if($cp->proficient) {
if ($cp->proficient) {
$points += (int) $cr->points;
}
}
@ -398,13 +397,13 @@ class coursecompetencyinfo {
}
$children[] = $cci;
}
$ci["children"] = $children;
}
if ($rule instanceof competency_rule_points) {
$ci["rule"] = $ruletext . " ({$points} / {$pointsreq} ".get_string("points","core_grades").")";
$ci["rule"] = $ruletext . " ({$points} / {$pointsreq} ".get_string("points", "core_grades").")";
$ci["count"] = $pointsreq;
$ci["progress"] = $points;
} else {
@ -413,7 +412,6 @@ class coursecompetencyinfo {
$ci["progress"] = $dprogress;
}
}
$cis[] = $ci;
}
@ -444,7 +442,7 @@ class coursecompetencyinfo {
return $list;
}
protected function proficiency_stats($competency,$studentlist) {
protected function proficiency_stats($competency, $studentlist) {
$r = new \stdClass();
$r->count = 0;
$r->nproficient = 0;
@ -453,12 +451,12 @@ class coursecompetencyinfo {
$r->nfailed = 0;
foreach ($studentlist as $sid) {
$p = $this->proficiency($competency,$sid);
$p = $this->proficiency($competency, $sid);
$r->count += 1;
$r->nproficient += ($p->proficient === true)?1:0;
$r->nfailed += ($p->proficient === false)?1:0;
$r->ncourseproficient += ($p->courseproficient)?1:0;
$r->nneedreview += ($p->needreview)?1:0;
$r->ncourseproficient += ($p->courseproficient) ? 1 : 0;
$r->nneedreview += ($p->needreview) ? 1 : 0;
}
return $r;
}
@ -472,7 +470,7 @@ class coursecompetencyinfo {
*/
public static function get_user_competency($userid, $competencyid) {
c_api::require_enabled();
$existing = user_competency::get_multiple($userid, array($competencyid));
$existing = user_competency::get_multiple($userid, [$competencyid]);
$uc = array_pop($existing);
if (!$uc) {
@ -499,7 +497,7 @@ class coursecompetencyinfo {
// This will throw an exception if the competency does not belong to the course.
$competency = course_competency::get_competency($courseid, $competencyid);
$params = array('courseid' => $courseid, 'userid' => $userid, 'competencyid' => $competencyid);
$params = ['courseid' => $courseid, 'userid' => $userid, 'competencyid' => $competencyid];
$exists = user_competency_course::get_record($params);
// Create missing.
if ($exists) {
@ -512,15 +510,14 @@ class coursecompetencyinfo {
return $ucc;
}
/**
* Retrieve course proficiency and overall proficiency for a competency and user
*
* @param \core_competency\competency $competency
* @param int $userid
*
* @return stdClass
*
*
* @return stdClass
*
*/
public function proficiency($competency, $userid) {
$scale = $competency->get_scale();
@ -535,7 +532,7 @@ class coursecompetencyinfo {
$r->failed = $proficiency === false;
try {
// Only add course grade and proficiency if the competency is included in the course.
$ucc = self::get_user_competency_in_course($this->course->id,$userid,$competencyid);
$ucc = self::get_user_competency_in_course($this->course->id, $userid, $competencyid);
$r->courseproficient = $ucc->get('proficiency');
$r->coursegrade = $scale->get_nearest_item($ucc->get('grade'));
} catch (\Exception $x) {}
@ -547,20 +544,20 @@ class coursecompetencyinfo {
*
* @param \core_competency\competency $competency
* @param int $userid
*
* @return stdClass
*
*
* @return stdClass
*
*/
public function retrievefeedback($competency, $userid) {
$competencyid = $competency->get('id');
$uc = self::get_user_competency($userid, $competencyid);
// Get evidences and sort by creation date (newest first)
$evidence = evidence::get_records_for_usercompetency($uc->get('id'),\context_system::instance(),'timecreated', "DESC");
$evidence = evidence::get_records_for_usercompetency($uc->get('id'), \context_system::instance(), 'timecreated', "DESC");
// Get the first valid note and return it;
foreach($evidence as $e) {
if ( in_array($e->get('action'),[evidence::ACTION_OVERRIDE,evidence::ACTION_COMPLETE] )) {
if ( in_array($e->get('action'), [evidence::ACTION_OVERRIDE, evidence::ACTION_COMPLETE] )) {
return $e->get('note');
break;
}
@ -581,7 +578,7 @@ class coursecompetencyinfo {
// Make sure conditions are properly configured;
$conditions = [];
try {
$conditions = json_decode($item->conditions(),true);
$conditions = json_decode($item->conditions(), true);
} catch (\Exception $x) {}
// Make sure the competencied field exists
@ -590,7 +587,7 @@ class coursecompetencyinfo {
}
// Make sure a record exits.
if (!array_key_exists($competencyid,$conditions["competencies"])){
if (!array_key_exists($competencyid, $conditions["competencies"])) {
$conditions["competencies"][$competencyid] = [
"required" => boolval($required),
];
@ -611,11 +608,11 @@ class coursecompetencyinfo {
if ($this->studyitem) {
$conditions = [];
try {
$conditions = json_decode($this->studyitem->conditions(),true);
$conditions = json_decode($this->studyitem->conditions(), true);
} catch (\Exception $x) {}
// Make sure the competencied field exists
if ( isset($conditions["competencies"])
if ( isset($conditions["competencies"])
&& is_array($conditions["competencies"])
&& isset($conditions["competencies"][$competency->get("id")])
&& isset($conditions["competencies"][$competency->get("id")]["required"])

View File

@ -114,7 +114,7 @@ class courseinfo {
* Check if current user is teacher in this course
* @return book
*/
protected function am_teacher() : bool {
protected function am_teacher(): bool {
global $USER;
return is_enrolled($this->coursecontext, $USER, 'mod/assign:grade');
}
@ -246,7 +246,7 @@ class courseinfo {
* Webservice structure for basic info
* @param int $value Webservice requirement constant
*/
public static function simple_structure($value = VALUE_REQUIRED) : \external_description {
public static function simple_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'linked course id'),
"fullname" => new \external_value(PARAM_TEXT, 'linked course name'),
@ -277,7 +277,7 @@ class courseinfo {
* Webservice structure for editor info
* @param int $value Webservice requirement constant
*/
public static function editor_structure($value = VALUE_REQUIRED) : \external_description {
public static function editor_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'linked course id'),
"fullname" => new \external_value(PARAM_TEXT, 'linked course name'),
@ -343,7 +343,7 @@ class courseinfo {
foreach ($gradables as $gradable) {
$info['grades'][] = $gradable->editor_model($this->studyitem);
}
}
}
if ($aggregator->use_corecompletioninfo()) {
$cc = new corecompletioninfo($this->course, $this->studyitem);
$studentlist = $this->studyitem->studyline()->studyplan()->find_linked_userids();
@ -353,7 +353,7 @@ class courseinfo {
$ci = new coursecompetencyinfo($this->course, $this->studyitem);
$studentlist = $this->studyitem->studyline()->studyplan()->find_linked_userids();
$info['competency'] = $ci->editor_model($studentlist);
}
}
}
return $info;
}
@ -362,7 +362,7 @@ class courseinfo {
* Webservice structure for userinfo
* @param int $value Webservice requirement constant
*/
public static function user_structure($value = VALUE_REQUIRED) : \external_description {
public static function user_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'linked course id'),
"fullname" => new \external_value(PARAM_TEXT, 'linked course name'),
@ -387,7 +387,7 @@ class courseinfo {
* @param int $courseid Course id of the course to check
* @return int[] Array if user ids
*/
public static function get_course_students($courseid) : array {
public static function get_course_students($courseid): array {
global $CFG;
if (!array_key_exists($courseid, self::$coursestudents)) {
$students = [];
@ -406,9 +406,9 @@ class courseinfo {
* (Has a gradebook role)
* @param int $userid The user Id to check
*/
public function is_enrolled_student($userid) : bool {
public function is_enrolled_student($userid): bool {
global $CFG;
foreach (explode(',', $CFG->gradebookroles) as $roleid) {
foreach (explode(', ', $CFG->gradebookroles) as $roleid) {
if (user_has_role_assignment($userid, $roleid, $this->coursecontext->id)) {
return true;
}
@ -455,10 +455,9 @@ class courseinfo {
'grades' => [],
'enrolled' => $this->is_enrolled_student($userid),
'extrafields' => $this->extrafields_model(),
'showprogressbar' => get_config("local_treestudyplan","courseprogressbar"),
'showprogressbar' => get_config("local_treestudyplan", "courseprogressbar"),
];
if (isset($this->studyitem)) {
$aggregator = $this->studyitem->studyline()->studyplan()->aggregator();
@ -467,7 +466,7 @@ class courseinfo {
foreach ($gradables as $gi) {
$info['grades'][] = $gi->user_model($userid);
}
}
}
if ($aggregator->use_corecompletioninfo()) {
$cc = new corecompletioninfo($this->course, $this->studyitem);
$info['completion'] = $cc->user_model($userid);
@ -475,24 +474,23 @@ class courseinfo {
if ($aggregator->use_coursecompetencies()) {
$ci = new coursecompetencyinfo($this->course, $this->studyitem);
$info['competency'] = $ci->user_model($userid);
}
}
}
return $info;
}
/**
* Webservice structure for extra fields
* @param int $value Webservice requirement constant
*/
public static function extrafields_structure($value = VALUE_REQUIRED) : \external_description {
public static function extrafields_structure($value = VALUE_REQUIRED): \external_description {
return new \external_multiple_structure(new \external_single_structure([
"title" => new \external_value(PARAM_RAW, 'title'),
"value" => new \external_value(PARAM_RAW, 'value'),
"position" => new \external_value(PARAM_TEXT, 'position'),
"type" => new \external_value(PARAM_TEXT, 'value type'),
"fieldname" => new \external_value(PARAM_TEXT, 'field name'),
"checked" => new \external_value(PARAM_BOOL, 'checkbox value',VALUE_OPTIONAL),
"checked" => new \external_value(PARAM_BOOL, 'checkbox value', VALUE_OPTIONAL),
"courseid" => new \external_value(PARAM_TEXT, 'course id number'),
], 'referenced course information'), $value);
}
@ -505,11 +503,11 @@ class courseinfo {
public function extrafields_model($includeteachervisible=false) {
$list = [];
for ($i=1; $i <= 5; $i++) {
$field = get_config('local_treestudyplan','courseinfo'.$i.'_field');
$field = get_config('local_treestudyplan', 'courseinfo'.$i.'_field');
if ($field) {
$title = self::extrafields_localize_title(get_config('local_treestudyplan','courseinfo'.$i.'_title'));
$pos = get_config('local_treestudyplan','courseinfo'.$i.'_position');
[$value,$type, $raw] = $this->extrafields_value($field,$includeteachervisible);
$title = self::extrafields_localize_title(get_config('local_treestudyplan', 'courseinfo'.$i.'_title'));
$pos = get_config('local_treestudyplan', 'courseinfo'.$i.'_position');
[$value, $type, $raw] = $this->extrafields_value($field, $includeteachervisible);
if ($type) {
$list[] = [
"title" => $title,
@ -518,7 +516,7 @@ class courseinfo {
"type" => $type,
"fieldname" => $field,
"courseid" => $this->course->id,
"checked" => ($type=="checkbox")?($raw?true:false):null,
"checked" => ($type=="checkbox") ? ($raw ? true : false):null,
];
}
}
@ -528,11 +526,11 @@ class courseinfo {
protected static function extrafields_localize_title($field) {
$lang = trim(current_language());
$lines = explode("\n",$field);
$lines = explode("\n", $field);
$title = "";
$fallback = ""; // Fallback to first title
foreach ($lines as $l) {
$parts = explode("|",$l,2);
$parts = explode("|", $l, 2);
if (count($parts) > 0) {
// Set the first line as fallback.
if (empty($firsttitle) && !empty($parts[0])) {
@ -543,7 +541,7 @@ class courseinfo {
$title = trim($parts[0]);
} else if (trim($parts[1]) == $lang) {
return trim($parts[0]);
}
}
}
}
@ -553,9 +551,9 @@ class courseinfo {
/**
* Determine value and type of an extra field for this course
* @return array [value,type] of the field for this
* @return array [value, type] of the field for this
*/
protected function extrafields_value($fieldname,$includeteachervisible=false) {
protected function extrafields_value($fieldname, $includeteachervisible=false) {
global $PAGE;
if ($fieldname == "description") {
// Process embedded files.
@ -580,7 +578,7 @@ class courseinfo {
$contacts = $cle->get_course_contacts();
$value = "";
foreach ($contacts as $uid => $contact) {
if(strlen($value) > 0) {
if (strlen($value) > 0) {
$value .= ", ";
}
$value .= $contact["username"];
@ -610,7 +608,7 @@ class courseinfo {
$value = "";
} else {
// Convert to YYYY-MM-DD format.
$value = date("Y-m-d", $raw);
$value = date("Y-m-d", $raw);
}
} else {
// Everything else can just use the export value.
@ -618,12 +616,12 @@ class courseinfo {
$value = $data->export_value();
}
return [$value,$type,$raw];
return [$value, $type, $raw];
}
}
}
}
// Fallback to empty if finding a match fails.
return [null,null,null];
return [null, null, null];
}
}

View File

@ -49,32 +49,31 @@ class courseservice extends \external_api {
*/
const CAP_VIEW = "local/treestudyplan:viewuserreports";
/**
* Get the topmost categories for the specicied user.
* Most of the work is offloaded to an SQL query in the interest of speed, but moodle functions are used to double check access permissions.
* @param int $userid Id of the user
* @return array of core_course_category
* @return array of core_course_category
*/
public static function user_tops($userid=null,$capability='moodle/category:viewcourselist') {
public static function user_tops($userid=null, $capability='moodle/category:viewcourselist') {
global $DB, $USER;
if ($userid == null) {
$userid = $USER->id;
}
$tops = [];
if (has_capability($capability,\context_system::instance(),$userid)) {
if (has_capability($capability, \context_system::instance(), $userid)) {
if ($capability == 'moodle/category:viewcourselist') {
// We are now just looking for the visible main level categories.
// Add all categories of depth = 1;
$rs = $DB->get_recordset("course_categories",["depth" => 1],'sortorder');
$rs = $DB->get_recordset("course_categories", ["depth" => 1], 'sortorder');
foreach( $rs as $rcat) {
// Get the category, and double check if the category is visible to the current user.
// Just in case it is a hidden category and the user does not have the viewhidden permission.
$cat = \core_course_category::get($rcat->id, \IGNORE_MISSING, false, $userid);
if ($cat !== null) {
// Register the category.
array_push($tops,$cat);
array_push($tops, $cat);
}
}
$rs->close();
@ -99,42 +98,42 @@ class courseservice extends \external_api {
// Use recordset to handle the eventuality of a really big and complex moodle setup.
$recordset = $DB->get_records_sql($sql, ["userid" => $userid, "capability" => $capability,
"ctxl_coursecat" => \CONTEXT_COURSECAT,]);
"ctxl_coursecat" => \CONTEXT_COURSECAT ]);
$params = ["userid" => $userid, "capability" => $capability,
"ctxl_coursecat" => \CONTEXT_COURSECAT,];
"ctxl_coursecat" => \CONTEXT_COURSECAT ];
$contextids = [];
foreach ($recordset as $r) {
// Get the paths as an array.
$parents = explode("/",$r->path);
$parents = explode("/", $r->path);
// Strip the first item, since it is an empty one.
array_shift($parents);
// Strip the last item, since it refers to self.
array_pop($parents);
// Figure out if any of the remaining parent contexts are already contexts with permission.
$intersect = array_intersect($contextids,$parents);
$intersect = array_intersect($contextids, $parents);
if (count($intersect) == 0) {
// Double check permissions according to the moodle capability system.
$ctx = \context::instance_by_id($r->id);
if (has_capability($capability,$ctx,$userid)) {
if (has_capability($capability, $ctx, $userid)) {
// Get the category, and double check if the category is visible to the current user.
// Just in case it is a hidden category and the user does not have the viewhidden permission.
$cat = \core_course_category::get($r->instanceid, \IGNORE_MISSING, false, $userid);
if ($cat !== null) {
// Register the context id in the list now, since we know the category is really visible.
array_push($contextids,$r->id);
array_push($contextids, $r->id);
// Register the category.
array_push($tops,$cat);
array_push($tops, $cat);
} else {
// The category is not visible. Add the first known visible subcategories.
$children = self::get_first_visible_children($r->id,$userid);
$children = self::get_first_visible_children($r->id, $userid);
foreach ($children as $cat) {
array_push($tops,$cat);
array_push($tops, $cat);
}
}
}
}
}
}
//$recordset->close();
//$recordset->close();
}
return $tops;
@ -142,7 +141,7 @@ class courseservice extends \external_api {
/**
* Find the top-most child categories for a given category that are visible.
*
*
* @param int $parentid The category to search for
* @return array of \core_course_category
*/
@ -151,7 +150,7 @@ class courseservice extends \external_api {
$capability = 'moodle/category:viewcourselist';
$tops = [];
$path_like = $DB->sql_like('ctx.path',':pathsearch');
$pathlike = $DB->sql_like('ctx.path', ':pathsearch');
$sql = "SELECT UNIQUE ctx.* FROM {context} AS ctx
INNER JOIN {role_assignments} AS ra ON ra.contextid = ctx.id
@ -159,51 +158,50 @@ class courseservice extends \external_api {
LEFT JOIN {course_categories} AS cat ON ctx.instanceid = cat.id
WHERE ( ctx.contextlevel = :ctxl_coursecat )
AND ra.userid = :userid AND rc.capability = :capability
AND {$path_like}
AND {$pathlike}
ORDER BY ctx.depth ASC, cat.sortorder ASC";
// Use recordset to handle the eventuality of a really big and complex moodle setup.
$recordset = $DB->get_recordset_sql($sql, ["userid" => $userid,
$recordset = $DB->get_recordset_sql($sql, ["userid" => $userid,
"capability" => $capability,
"ctxl_coursecat" => \CONTEXT_COURSECAT,
"ctxl_coursecat" => \CONTEXT_COURSECAT,
"pathsearch" => "%/{$parentid}/%",
]);
$contextids = [];
foreach ($recordset as $r) {
// Get the paths as an array.
$parents = explode("/",$r->path);
$parents = explode("/", $r->path);
// Strip the first item, since it is an empty one.
array_shift($parents);
// Strip the last item, since it refers to self.
array_pop($parents);
// Figure out if any of the remaining parent contexts are already contexts with permission.
$intersect = array_intersect($contextids,$parents);
$intersect = array_intersect($contextids, $parents);
if (count($intersect) == 0) {
// Double check permissions according to the moodle capability system.
$ctx = \context::instance_by_id($r->id);
if (has_capability($capability,$ctx,$userid)) {
if (has_capability($capability, $ctx, $userid)) {
// Get the category, and double check if the category is visible to the current user.
// Just in case it is a hidden category and the user does not have the viewhidden permission.
$cat = \core_course_category::get($r->instanceid, \IGNORE_MISSING, false, $userid);
if ($cat !== null) {
// Register the context id in the list now, since we know the category is really visible.
array_push($contextids,$r->id);
array_push($contextids, $r->id);
// Register the category.
array_push($tops,$cat);
}
}
array_push($tops, $cat);
}
}
}
}
$recordset->close();
$recordset->close();
return $tops;
}
/**
* Return value description for map_categories function
*/
public static function map_categories_parameters() : \external_function_parameters {
public static function map_categories_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'ID of studyplan to map the categories for', VALUE_DEFAULT),
] );
@ -212,7 +210,7 @@ class courseservice extends \external_api {
/**
* Parameter description for map_categories function
*/
public static function map_categories_returns() : \external_description {
public static function map_categories_returns(): \external_description {
return new \external_multiple_structure(static::map_category_structure(false));
}
@ -247,7 +245,6 @@ class courseservice extends \external_api {
public static function map_categories($studyplanid = 0) {
global $USER;
// Determine top categories from provided context.
if ($studyplanid == 0) {
@ -255,22 +252,22 @@ class courseservice extends \external_api {
// This uses a custom function, since moodle's "core_course_category::user_top()" is somewhat deficient.
$children = self::user_tops();
if (count($children) == 0) {
throw new moodle_exception("error:nocategoriesvisible","local_treestudyplan");
throw new moodle_exception("error:nocategoriesvisible", "local_treestudyplan");
}
} else {
if (\get_config("local_treestudyplan","limitcourselist")) { // TODO: Insert config setting here
if (\get_config("local_treestudyplan", "limitcourselist")) { // TODO: Insert config setting here
$studyplan = studyplan::find_by_id($studyplanid);
$context = $studyplan->context();
if ($context->contextlevel == \CONTEXT_SYSTEM) {
$children = self::user_tops();
} else if ($context->contextlevel == \CONTEXT_COURSECAT) {
$cat = \core_course_category::get($context->instanceid,\MUST_EXIST,true);
if ($cat->is_uservisible()) {
$cat = \core_course_category::get($context->instanceid, \MUST_EXIST, true);
if ($cat->is_uservisible()) {
$children = [$cat];
} else {
$ci = new contextinfo($context);
$contextname = $ci->pathstr();
throw new moodle_exception("error:cannotviewcategory","local_treestudyplan",'',$contextname);
throw new moodle_exception("error:cannotviewcategory", "local_treestudyplan", '', $contextname);
}
} else {
$children = [];
@ -278,7 +275,7 @@ class courseservice extends \external_api {
} else {
$children = self::user_tops();
if (count($children) == 0) {
throw new moodle_exception("error:nocategoriesvisible","local_treestudyplan");
throw new moodle_exception("error:nocategoriesvisible", "local_treestudyplan");
}
}
}
@ -293,7 +290,7 @@ class courseservice extends \external_api {
/**
* Return value description for get_category function
*/
public static function get_category_parameters() : \external_function_parameters {
public static function get_category_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"id" => new \external_value(PARAM_INT, 'id of category'),
] );
@ -302,7 +299,7 @@ class courseservice extends \external_api {
/**
* Parameter description for get_category function
*/
public static function get_category_returns() : \external_description {
public static function get_category_returns(): \external_description {
return static::map_category_structure(false);
}
@ -362,8 +359,8 @@ class courseservice extends \external_api {
global $USER;
// List the categories in which the user has a specific capability.
$list = [];
$parents = self::user_tops($USER->id,$capability);
array_merge($list,$parents);
$parents = self::user_tops($USER->id, $capability);
array_merge($list, $parents);
foreach ($parents as $parent) {
// For optimization purposes, we include all its children now, since they will have inherited the permission.
@ -394,7 +391,7 @@ class courseservice extends \external_api {
/**
* Return value description for list_available_categories function
*/
public static function list_available_categories_parameters() : \external_function_parameters {
public static function list_available_categories_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"operation" => new \external_value(PARAM_TEXT, 'type of operation ["view"|"edit"]', VALUE_DEFAULT),
"refcontext_id" => new \external_value(PARAM_INT, 'id of reference context', VALUE_DEFAULT),
@ -404,7 +401,7 @@ class courseservice extends \external_api {
/**
* Parameter description for list_available_categories function
*/
public static function list_available_categories_returns() : \external_description {
public static function list_available_categories_returns(): \external_description {
return new \external_multiple_structure(static::map_category_structure(true));
}
@ -421,10 +418,10 @@ class courseservice extends \external_api {
} else { // Operation == "view" || default.
$capability = self::CAP_VIEW;
}
// Get the context ids of all categories the user has access to view and wich have the given permission.
$contextids = [];
$tops = self::user_tops(null,$capability);
$tops = self::user_tops(null, $capability);
foreach ($tops as $cat) {
$ctx = \context_coursecat::instance($cat->id);
$contextids[] = $ctx->id;
@ -440,7 +437,7 @@ class courseservice extends \external_api {
$contextcounts[$r->context_id] = $r->num;
// Add any of the categories containing studyplans to the list.
$ctx = \context::instance_by_id($r->context_id);
if (has_capability($capability,$ctx) && !in_array($r->context_id,$contextids)) {
if (has_capability($capability, $ctx) && !in_array($r->context_id, $contextids)) {
$insertctxs[] = $ctx;
}
}
@ -451,11 +448,11 @@ class courseservice extends \external_api {
// If the reference context id is not in the list, push it there if the user has proper permissions in that context
if ($refctxid > 1 && !in_array($refctxid, $contextids)) {
try {
try {
// Get the context.
$refctx = \context::instance_by_id($refctxid);
// Double check permissions.
if (has_capability($capability,$refctx)) {
if (has_capability($capability, $refctx)) {
$insertctxs[] = $refctx;
}
} catch(\dml_missing_record_exception $x) {
@ -468,12 +465,12 @@ class courseservice extends \external_api {
$ipath = $ictx->get_parent_context_ids(true);
$found = false;
foreach ($ipath as $i => $pid) {
$idx = array_search($pid,$contextids);
if($idx !== false) {
$idx = array_search($pid, $contextids);
if ($idx !== false) {
$contextids = array_merge(
array_slice($contextids, 0, $idx+1),
array_reverse(array_slice($ipath,0,$i)),
array_reverse(array_slice($ipath, 0, $i)),
array_slice($contextids, $idx+1, count($contextids) - 1)
) ;
@ -481,12 +478,11 @@ class courseservice extends \external_api {
break;
}
}
if(!$found) {
array_unshift($contextids,$ictx->id);
if (!$found) {
array_unshift($contextids, $ictx->id);
}
}
// Now translate this to the list of categories.
foreach ($contextids as $ctxid ) {
try {
@ -494,7 +490,7 @@ class courseservice extends \external_api {
if ($ctx->contextlevel == CONTEXT_SYSTEM) {
$cat = \core_course_category::top();
} else if ($ctx->contextlevel == CONTEXT_COURSECAT) {
$cat = \core_course_category::get($ctx->instanceid,\MUST_EXIST,false);
$cat = \core_course_category::get($ctx->instanceid, \MUST_EXIST, false);
}
$cats[] = $cat;
// In edit mode, also include direct children of the currently selected context.
@ -502,7 +498,7 @@ class courseservice extends \external_api {
// Include direct children for navigation purposes.
foreach ($cat->get_children() as $ccat) {
$ccatctx = \context_coursecat::instance($ccat->id);
if (!in_array($ccatctx->id,$contextids)) {
if (!in_array($ccatctx->id, $contextids)) {
$cats[] = $ccat;
}
}
@ -529,7 +525,6 @@ class courseservice extends \external_api {
}
/**************************************
*
* Progress scanners for teacherview
@ -540,7 +535,7 @@ class courseservice extends \external_api {
* Return value description for scan_grade_progress function
* @return external_function_parameters
*/
public static function scan_grade_progress_parameters() : \external_function_parameters {
public static function scan_grade_progress_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"gradeitemid" => new \external_value(PARAM_INT, 'Grade item ID to scan progress for', VALUE_DEFAULT),
"studyplanid" => new \external_value(PARAM_INT, 'Study plan id to check progress in', VALUE_DEFAULT),
@ -551,7 +546,7 @@ class courseservice extends \external_api {
/**
* Parameter description for scan_grade_progress function
*/
public static function scan_grade_progress_returns() : \external_description {
public static function scan_grade_progress_returns(): \external_description {
return gradingscanner::structure(VALUE_REQUIRED);
}
@ -585,7 +580,7 @@ class courseservice extends \external_api {
/**
* Return value description for scan_completion_progress function
*/
public static function scan_completion_progress_parameters() : \external_function_parameters {
public static function scan_completion_progress_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"criteriaid" => new \external_value(PARAM_INT, 'CriteriaID to scan progress for', VALUE_DEFAULT),
"studyplanid" => new \external_value(PARAM_INT, 'Study plan id to check progress in', VALUE_DEFAULT),
@ -596,7 +591,7 @@ class courseservice extends \external_api {
/**
* Parameter description for scan_completion_progress function
*/
public static function scan_completion_progress_returns() : \external_description {
public static function scan_completion_progress_returns(): \external_description {
return completionscanner::structure(VALUE_REQUIRED);
}
@ -621,7 +616,7 @@ class courseservice extends \external_api {
/**
* Return value description for scan_badge_progress function
*/
public static function scan_badge_progress_parameters() : \external_function_parameters {
public static function scan_badge_progress_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"badgeid" => new \external_value(PARAM_INT, 'Badge to scan progress for', VALUE_DEFAULT),
"studyplanid" => new \external_value(PARAM_INT,
@ -632,7 +627,7 @@ class courseservice extends \external_api {
/**
* Parameter description for scan_badge_progress function
*/
public static function scan_badge_progress_returns() : \external_description {
public static function scan_badge_progress_returns(): \external_description {
return new \external_single_structure([
"total" => new \external_value(PARAM_INT, 'Total number of students scanned'),
"issued" => new \external_value(PARAM_INT, 'Number of issued badges'),

View File

@ -33,18 +33,18 @@ class debug {
* @param $filename File to write to
* @return any The object
*/
public static function &dump(&$object,$filename="/tmp/debug.log") {
public static function &dump(&$object, $filename="/tmp/debug.log") {
try {
$f = fopen($filename,"a+");
$f = fopen($filename, "a+");
try {
$json = \json_encode($object,JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR );
fwrite($f,$json."\n");
$json = \json_encode($object, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR );
fwrite($f, $json."\n");
} catch (JsonException $x) {
fwrite($f,"Error processing json: ". $x->getMessage()."\n");
fwrite($f,"Print_r dump: \n".print_r($object,true)."\n");
fwrite($f, "Error processing json: ". $x->getMessage()."\n");
fwrite($f, "Print_r dump: \n".print_r($object, true)."\n");
}
} catch (\Exception $x){
} catch (\Exception $x) {
} finally {
fclose($f);
@ -57,26 +57,25 @@ class debug {
* @param $filename File to write to
* @return any The object
*/
public static function &print_r(&$object,$filename="/tmp/debug.log") {
public static function &print_r(&$object, $filename="/tmp/debug.log") {
try {
$f = fopen($filename,"a+");
fwrite($f,"Print_r dump: \n".print_r($object,true)."\n");
$f = fopen($filename, "a+");
fwrite($f, "Print_r dump: \n".print_r($object, true)."\n");
} catch (\Exception $x) {
} finally {
fclose($f);
}
}
/**
* @param $object Object to dump
* @param $filename File to write to
* @return any The object
*/
public static function write($text,$filename="/tmp/debug.log") {
public static function write($text, $filename="/tmp/debug.log") {
try {
$f = fopen($filename,"a+");
fwrite($f,$text."\n");
$f = fopen($filename, "a+");
fwrite($f, $text."\n");
} catch (\Exception $x) {
} finally {
fclose($f);

View File

@ -25,7 +25,7 @@ abstract class formbase extends \moodleform {
/**
* Generate custom data from parameters
* Also validate parameters and access permissions here
*
*
* @param object $params The parameters for form initialization
* @return object Form data based on parameters
*/
@ -34,23 +34,23 @@ abstract class formbase extends \moodleform {
/**
* Generate form data from parameters
* Also validate parameters and access permissions here
*
*
* @param object $customdata The parameters for form initialization
* @return array Form data based on parameters
*/
abstract public function init_formdata(object $customdata);
/**
* Validate security access for this form based on the provided parameters
* Validate security access for this form based on the provided parameters
* Return true if validation passes, false or throw an exception if it does not.
*
*
* @param object $params The parameters for form initialization
* @return bool True if security validation passes.
* @return bool True if security validation passes.
* @throws \moodle_exception if access denied for a specific reason.
*/
abstract public static function check_security(object $customdata);
/**
/**
* Process the submission and perform necessary actions
* @param object $entry The processed form data
* @return object|array Data to pass to receiver if submission successful
@ -58,7 +58,7 @@ abstract class formbase extends \moodleform {
*/
abstract protected function process_submitted_data(object $entry);
/**
/**
* Process the submission and perform necessary actions
* @return object|array Data to pass to receiver if submission successful
* @throws \moodle_exception if an error must be given for a specific reason.
@ -66,13 +66,11 @@ abstract class formbase extends \moodleform {
public function process_submission() {
$data = $this->get_data();
if($data) {
if ($data) {
return $this->process_submitted_data($data);
} else {
throw new \moodle_exception('no_form_data','local_treestudyplan','',null,$data);
throw new \moodle_exception('no_form_data', 'local_treestudyplan', '', null, $data);
}
}
}

View File

@ -14,10 +14,9 @@ use local_treestudyplan\form\text_integer;
use moodle_exception;
use stdClass;
/**
* Moodleform class for the studyplan editor. A Moodleform is used here to facilitate a rich editor
* in the studyplan description
* Moodleform class for the studyplan editor. A Moodleform is used here to facilitate a rich editor
* in the studyplan description
*/
class studyplan_editform extends formbase {
/**
@ -27,18 +26,18 @@ class studyplan_editform extends formbase {
const CAP_EDIT = "local/treestudyplan:editstudyplan";
/**
* Translate parameters into customdata.
*
* Translate parameters into customdata.
*
* @param object $params The parameters for form initialization
* @return array Form data based on parameters
*/
*/
public static function init_customdata(object $params) {
$customdata = new stdClass;
$customdata->create = $params->mode=='create'?true:false;
if($customdata->create){
$customdata->create = $params->mode=='create' ? true : false;
if ($customdata->create) {
$customdata->context = \context::instance_by_id($params->contextid);
} else {
$customdata->plan = studyplan::find_by_id($params->studyplan_id);
$customdata->context = $customdata->plan->context();
$customdata->simplemodel = $customdata->plan->simple_model();
@ -59,43 +58,43 @@ class studyplan_editform extends formbase {
'accepted_types' => ['.jpg', '.png', '.jpeg', '.svg', '.svgz'],
'return_types' => \FILE_INTERNAL | \FILE_EXTERNAL,
];
return $customdata;
return $customdata;
}
/**
* Validate security access for this form based on the customdata generated by init_customdata
* Return true if validation passes, false or throw an exception if it does not.
*
*
* @param object $customdata The customdata for this form
* @return bool True if security validation passes.
* @return bool True if security validation passes.
* @throws \moodle_exception if access denied for a specific reason.
*/
public static function check_security(object $customdata) {
/*webservicehelper::require_capabilities(self::CAP_EDIT,$customdata->context); */
/*webservicehelper::require_capabilities(self::CAP_EDIT, $customdata->context); */
}
/**
* Generate form data from parameters
* Also validate parameters and access permissions here
*
*
* @param object $customdata The parameters for form initialization
* @return array Form data based on parameters
*/
*/
public function init_formdata(object $customdata) {
global $DB;
/* Use direct database retrieval to avoid our abstractions causing trouble
with existing moodle code assumptions.
with existing moodle code assumptions.
The form API does seem needlessly convoluted in it's use, but we need the editor...
*/
if($customdata->create) {
if ($customdata->create) {
$entry = new stdClass;
$entry->context_id = $customdata->context->id;
$entry->aggregation = get_config("local_treestudyplan","aggregation_mode");
$ag_cfg = json_decode(aggregator::create($entry->aggregation, "")->config_string(),true);
$entry->aggregation = get_config("local_treestudyplan", "aggregation_mode");
$agcfg = json_decode(aggregator::create($entry->aggregation, "")->config_string(), true);
// Determine the next august 1st for default value purposes.
$august = strtotime("first day of august this year");
if($august < time()) {
if ($august < time()) {
$august = strtotime("first day of august next year");
}
$entry->startdate = $august;
@ -107,7 +106,7 @@ class studyplan_editform extends formbase {
$entry->startdate = strtotime($customdata->simplemodel['pages'][0]['startdate']);
$entry->enddate = strtotime($customdata->simplemodel['pages'][0]['enddate']);
$entry->periods = $customdata->simplemodel['pages'][0]['periods'];
$ag_cfg = json_decode($customdata->plan->aggregator()->config_string(),true);
$agcfg = json_decode($customdata->plan->aggregator()->config_string(), true);
}
// Prepare the editor
@ -117,7 +116,7 @@ class studyplan_editform extends formbase {
\context_system::instance(),
'local_treestudyplan',
'studyplan',
($customdata->create)?null:$customdata->plan->id()
($customdata->create) ? null : $customdata->plan->id()
);
// Prepare file area for the icon
@ -132,14 +131,14 @@ class studyplan_editform extends formbase {
\context_system::instance()->id,
'local_treestudyplan',
'icon',
($customdata->create)?null:$customdata->plan->id(),
($customdata->create) ? null : $customdata->plan->id(),
$customdata->fileoptions
);
$entry->icon = $draftitemid;
// Add aggregation configs to entry.
foreach ($ag_cfg as $key => $val) {
foreach ($agcfg as $key => $val) {
$entrykey = $entry->aggregation."_".$key;
$entry->$entrykey = $val;
}
@ -160,29 +159,29 @@ class studyplan_editform extends formbase {
// Define the form
$field = 'name';
$mform->addElement('text',$field,
get_string('studyplan_name','local_treestudyplan'),
$mform->addElement('text', $field,
get_string('studyplan_name', 'local_treestudyplan'),
[]);
$mform->addRule($field, null, 'required', null, 'client');
$field = 'shortname';
$mform->addElement('text',$field,
get_string('studyplan_shortname','local_treestudyplan'),
$mform->addElement('text', $field,
get_string('studyplan_shortname', 'local_treestudyplan'),
[]);
$mform->addRule($field, null, 'required', null, 'client');
$field = 'idnumber';
$mform->addElement('text',$field,
get_string('studyplan_idnumber','local_treestudyplan'),
$mform->addElement('text', $field,
get_string('studyplan_idnumber', 'local_treestudyplan'),
[]);
$contextlist = [];
foreach(courseservice::list_available_categories('edit') as $c){
$contextlist[$c['context_id']] = implode(" / ",$c['category']['path']);
foreach(courseservice::list_available_categories('edit') as $c) {
$contextlist[$c['context_id']] = implode(" / ", $c['category']['path']);
}
$mform->addElement('autocomplete', 'context_id',
get_string('studyplan_context','local_treestudyplan'),
$mform->addElement('autocomplete', 'context_id',
get_string('studyplan_context', 'local_treestudyplan'),
$contextlist);
$mform->addRule('context_id', null, 'required', null, 'client');
@ -196,25 +195,25 @@ class studyplan_editform extends formbase {
);
if ($customdata->create) {
$timeless = \get_config("local_treestudyplan","timelessperiods");
$timeless = \get_config("local_treestudyplan", "timelessperiods");
if ( !$timeless) {
// Only add these fields if a new studyplan is created, to easily initialize the first page
$field = 'startdate';
$mform->addElement('date_selector',$field,
get_string('studyplan_startdate','local_treestudyplan'),
$mform->addElement('date_selector', $field,
get_string('studyplan_startdate', 'local_treestudyplan'),
[]);
$mform->addRule($field, null, 'required', null, 'client');
$field = 'enddate';
$mform->addElement('date_selector',$field,
get_string('studyplan_enddate','local_treestudyplan'),
$mform->addElement('date_selector', $field,
get_string('studyplan_enddate', 'local_treestudyplan'),
[]);
$mform->addRule($field, null, 'required', null, 'client');
}
$field = 'periods';
$mform->addElement('text_integer',$field,
get_string('studyplan_slots','local_treestudyplan'),
$mform->addElement('text_integer', $field,
get_string('studyplan_slots', 'local_treestudyplan'),
["unsigned" => true]);
$mform->setType($field, PARAM_INT);
$mform->addRule($field, null, 'required', null, 'client');
@ -222,83 +221,83 @@ class studyplan_editform extends formbase {
} else {
// These fields are only relevant if the studyplan is edited
$field = 'suspended';
$mform->addElement('advcheckbox',$field,
get_string('studyplan_suspend','local_treestudyplan'),
get_string('studyplan_suspend_details','local_treestudyplan'),
$mform->addElement('advcheckbox', $field,
get_string('studyplan_suspend', 'local_treestudyplan'),
get_string('studyplan_suspend_details', 'local_treestudyplan'),
[],
);
if (premium::enabled()) {
$field = 'template';
$mform->addElement('advcheckbox',$field,
get_string('studyplan_template','local_treestudyplan'),
get_string('studyplan_template_details','local_treestudyplan'),
$mform->addElement('advcheckbox', $field,
get_string('studyplan_template', 'local_treestudyplan'),
get_string('studyplan_template_details', 'local_treestudyplan'),
[],
);
}
}
$aggregators = [];
foreach(aggregator::list_model() as $a){
foreach(aggregator::list_model() as $a) {
// Add method only if not deprecated or currently used
if ( $customdata->simplemodel['aggregation'] == $a['id'] || !($a['deprecated']) ) {
$aggregators[$a['id']] = $a['name'];
}
}
$field = 'aggregation';
$mform->addElement('select',$field,
get_string('choose_aggregation_style','local_treestudyplan'),
$mform->addElement('select', $field,
get_string('choose_aggregation_style', 'local_treestudyplan'),
$aggregators);
/* Start Bistate aggregation specific items */
$field = 'bistate_thresh_excellent';
$mform->addElement('text_integer',$field,
get_string('setting_bistate_thresh_excellent','local_treestudyplan'),
$mform->addElement('text_integer', $field,
get_string('setting_bistate_thresh_excellent', 'local_treestudyplan'),
["unsigned" => false],
);
$mform->setType($field, PARAM_INT);
$mform->hideIf($field, "aggregation", "neq", "bistate");
$mform->hideif ($field, "aggregation", "neq", "bistate");
$field = 'bistate_thresh_good';
$mform->addElement('text_integer',$field,
get_string('setting_bistate_thresh_good','local_treestudyplan'),
$mform->addElement('text_integer', $field,
get_string('setting_bistate_thresh_good', 'local_treestudyplan'),
["unsigned" => true],
);
$mform->setType($field, PARAM_INT);
$mform->hideIf($field, "aggregation", "neq", "bistate");
$mform->hideif ($field, "aggregation", "neq", "bistate");
$field = 'bistate_thresh_completed';
$mform->addElement('text_integer',$field,
get_string('setting_bistate_thresh_completed','local_treestudyplan'),
$mform->addElement('text_integer', $field,
get_string('setting_bistate_thresh_completed', 'local_treestudyplan'),
["unsigned" => true],
);
$mform->setType($field, PARAM_INT);
$mform->hideIf($field, "aggregation", "neq", "bistate");
$mform->hideif ($field, "aggregation", "neq", "bistate");
$field = 'bistate_use_failed';
$mform->addElement('checkbox',$field,
get_string('setting_bistate_support_failed','local_treestudyplan'),
$mform->addElement('checkbox', $field,
get_string('setting_bistate_support_failed', 'local_treestudyplan'),
[],
);
$mform->hideIf($field, "aggregation", "neq", "bistate");
$mform->hideif ($field, "aggregation", "neq", "bistate");
$field = 'bistate_accept_pending_as_submitted';
$mform->addElement('checkbox',$field,
get_string('setting_bistate_accept_pending_submitted','local_treestudyplan'),
$mform->addElement('checkbox', $field,
get_string('setting_bistate_accept_pending_submitted', 'local_treestudyplan'),
[],
);
$mform->hideIf($field, "aggregation", "neq", "bistate");
$mform->hideif ($field, "aggregation", "neq", "bistate");
/* End Bistate aggregation specific items */
$mform->addElement('editor', 'description_editor',
get_string('studyplan_description', 'local_treestudyplan'),
null,
get_string('studyplan_description', 'local_treestudyplan'),
null,
$customdata->editoroptions);
$mform->setType('description_editor', PARAM_RAW);
}
/**
/**
* Process the submitted data and perform necessary actions
* @param object $entry The processed form data;
* @return bool false if submission not successful
@ -308,12 +307,12 @@ class studyplan_editform extends formbase {
$customdata = (object)$this->_customdata;
// Add aggregation configs to entry.
$ag_cfg = json_decode(aggregator::create($entry->aggregation, "")->config_string(),true); // Retrieve default config string from selected aggregation method
foreach ($ag_cfg as $key => $val) {
$agcfg = json_decode(aggregator::create($entry->aggregation, "")->config_string(), true); // Retrieve default config string from selected aggregation method
foreach ($agcfg as $key => $val) {
$entrykey = $entry->aggregation."_".$key;
$ag_cfg[$key] = $entry->$entrykey;
$agcfg[$key] = $entry->$entrykey;
}
$aggregation_config = json_encode($ag_cfg);
$aggregationconfig = json_encode($agcfg);
if ($customdata->create) {
@ -323,9 +322,9 @@ class studyplan_editform extends formbase {
'idnumber' => $entry->idnumber,
'context_id' => $entry->context_id,
'aggregation' => $entry->aggregation,
'aggregation_config' => $aggregation_config,
'startdate' => date("Y-m-d",$entry->startdate),
'enddate' => date("Y-m-d",$entry->enddate),
'aggregation_config' => $aggregationconfig,
'startdate' => date("Y-m-d", $entry->startdate),
'enddate' => date("Y-m-d", $entry->enddate),
'periods' => $entry->periods,
]);
// Process the provided files in the description editor
@ -335,7 +334,7 @@ class studyplan_editform extends formbase {
\context_system::instance(),
'local_treestudyplan',
'studyplan',
$plan->id());
$plan->id());
// Update the description
$plan->edit([
'description' => $entry->description,
@ -343,7 +342,7 @@ class studyplan_editform extends formbase {
]);
} else {
$plan = $customdata->plan;
// Process the provided files in the description editor
$entry = file_postupdate_standard_editor($entry,
'description',
@ -361,7 +360,7 @@ class studyplan_editform extends formbase {
'description' => $entry->description,
'descriptionformat' => $entry->descriptionformat,
'aggregation' => $entry->aggregation,
'aggregation_config' => $aggregation_config,
'aggregation_config' => $aggregationconfig,
'suspended' => $entry->suspended,
'template' => $entry->template,
]);
@ -382,12 +381,11 @@ class studyplan_editform extends formbase {
/* Return the simple model of the plan to make sure we can update stuff.
Parse it through the clean_returnvalue function of exernal api (of which studyplanservice is a subclass)
so we return it in a consistent way
so we return it in a consistent way
*/
$response = studyplanservice::clean_returnvalue(studyplan::simple_structure(),$plan->simple_model());
$response = studyplanservice::clean_returnvalue(studyplan::simple_structure(), $plan->simple_model());
debug::dump($response);
return $response;
}
}

View File

@ -14,10 +14,9 @@ use local_treestudyplan\form\text_integer;
use moodle_exception;
use stdClass;
/**
* Moodleform class for the studyplan editor. A Moodleform is used here to facilitate a rich editor
* in the studyplan description
* Moodleform class for the studyplan editor. A Moodleform is used here to facilitate a rich editor
* in the studyplan description
*/
class studyplan_fromtemplateform extends formbase {
/**
@ -27,42 +26,41 @@ class studyplan_fromtemplateform extends formbase {
const CAP_EDIT = "local/treestudyplan:editstudyplan";
/**
* Translate parameters into customdata.
*
* Translate parameters into customdata.
*
* @param object $params The parameters for form initialization
* @return array Form data based on parameters
*/
*/
public static function init_customdata(object $params) {
$customdata = new stdClass;
$customdata->context = \context::instance_by_id($params->contextid);
return $customdata;
return $customdata;
}
/**
* Validate security access for this form based on the customdata generated by init_customdata
* Return true if validation passes, false or throw an exception if it does not.
*
*
* @param object $customdata The customdata for this form
* @return bool True if security validation passes.
* @return bool True if security validation passes.
* @throws \moodle_exception if access denied for a specific reason.
*/
public static function check_security(object $customdata) {
/*webservicehelper::require_capabilities(self::CAP_EDIT,$customdata->context); */
/*webservicehelper::require_capabilities(self::CAP_EDIT, $customdata->context); */
}
/**
* Generate form data from parameters
* Also validate parameters and access permissions here
*
*
* @param object $customdata The parameters for form initialization
* @return array Form data based on parameters
*/
*/
public function init_formdata(object $customdata) {
global $DB;
/* Use direct database retrieval to avoid our abstractions causing trouble
with existing moodle code assumptions.
with existing moodle code assumptions.
The form API does seem needlessly convoluted in it's use, but we need the editor...
*/
$entry = new stdClass;
@ -70,7 +68,7 @@ class studyplan_fromtemplateform extends formbase {
// Determine the next august 1st for default value purposes.
$august = strtotime("first day of august this year");
if($august < time()) {
if ($august < time()) {
$august = strtotime("first day of august next year");
}
$entry->startdate = $august;
@ -95,70 +93,70 @@ class studyplan_fromtemplateform extends formbase {
// Define the form
$templatelist = [];
foreach(studyplan::find_template() as $s){
foreach(studyplan::find_template() as $s) {
$c = (new contextinfo($s->context()))->model();
$templatelist[$s->id()] = implode(" / ",$c['path']) . " / " . $s->name();
$templatelist[$s->id()] = implode(" / ", $c['path']) . " / " . $s->name();
}
if (count($templatelist) > 0) {
$mform->addElement('hidden','hastemplates','yes');
$mform->addElement('hidden', 'hastemplates', 'yes');
$field = 'template_id';
$mform->addElement('autocomplete', $field,
get_string('studyplan_fromtemplate','local_treestudyplan'),
$mform->addElement('autocomplete', $field,
get_string('studyplan_fromtemplate', 'local_treestudyplan'),
$templatelist);
$mform->addRule($field, null, 'required', null, 'client');
$field = 'name';
$mform->addElement('text',$field,
get_string('studyplan_name','local_treestudyplan'),
$mform->addElement('text', $field,
get_string('studyplan_name', 'local_treestudyplan'),
[]);
$mform->addRule($field, null, 'required', null, 'client');
$field = 'shortname';
$mform->addElement('text',$field,
get_string('studyplan_shortname','local_treestudyplan'),
$mform->addElement('text', $field,
get_string('studyplan_shortname', 'local_treestudyplan'),
[]);
$mform->addRule($field, null, 'required', null, 'client');
$field = 'idnumber';
$mform->addElement('text',$field,
get_string('studyplan_idnumber','local_treestudyplan'),
$mform->addElement('text', $field,
get_string('studyplan_idnumber', 'local_treestudyplan'),
[]);
$contextlist = [];
foreach(courseservice::list_available_categories('edit') as $c){
$contextlist[$c['context_id']] = implode(" / ",$c['category']['path']);
foreach(courseservice::list_available_categories('edit') as $c) {
$contextlist[$c['context_id']] = implode(" / ", $c['category']['path']);
}
$field = 'context_id';
$mform->addElement('autocomplete', $field,
get_string('studyplan_context','local_treestudyplan'),
$mform->addElement('autocomplete', $field,
get_string('studyplan_context', 'local_treestudyplan'),
$contextlist);
$mform->addRule($field, null, 'required', null, 'client');
$timeless = \get_config("local_treestudyplan","timelessperiods");
$timeless = \get_config("local_treestudyplan", "timelessperiods");
if ( !$timeless) {
// Only add these fields if the studyplans are timed
$field = 'startdate';
$mform->addElement('date_selector',$field,
get_string('studyplan_startdate','local_treestudyplan'),
$mform->addElement('date_selector', $field,
get_string('studyplan_startdate', 'local_treestudyplan'),
[]);
$mform->addRule($field, null, 'required', null, 'client');
}
} else {
$mform->addElement('hidden','hastemplates','no');
$mform->addElement('hidden', 'hastemplates', 'no');
$field = 'warning';
$mform->addElement('static', $field,
get_string('warning','core'),
get_string('no_templates','local_treestudyplan')
$mform->addElement('static', $field,
get_string('warning', 'core'),
get_string('no_templates', 'local_treestudyplan')
);
}
}
/**
/**
* Process the submitted data and perform necessary actions
* @param object $entry The processed form data;
* @return bool false if submission not successful
@ -167,21 +165,20 @@ class studyplan_fromtemplateform extends formbase {
protected function process_submitted_data($entry) {
$customdata = (object)$this->_customdata;
if($entry->hastemplates == "yes") {
if ($entry->hastemplates == "yes") {
// Find template study plan.
$template = studyplan::find_by_id($entry->template_id);
// Copy template plan.
$plan = $template->duplicate($entry->name,$entry->shortname,$entry->context_id,$entry->idnumber,$entry->startdate);
$plan = $template->duplicate($entry->name, $entry->shortname, $entry->context_id, $entry->idnumber, $entry->startdate);
/* Return the simple model of the plan to make sure we can update stuff.
Parse it through the clean_returnvalue function of exernal api (of which studyplanservice is a subclass)
so we return it in a consistent way
so we return it in a consistent way
*/
return studyplanservice::clean_returnvalue(studyplan::simple_structure(),$plan->simple_model());
return studyplanservice::clean_returnvalue(studyplan::simple_structure(), $plan->simple_model());
} else {
return null;
}
}
}

View File

@ -15,8 +15,8 @@ use moodle_exception;
use stdClass;
/**
* Moodleform class for the studyplan editor. A Moodleform is used here to facilitate a rich editor
* in the studyplan description
* Moodleform class for the studyplan editor. A Moodleform is used here to facilitate a rich editor
* in the studyplan description
*/
class studyplanpage_editform extends formbase {
/**
@ -26,15 +26,15 @@ class studyplanpage_editform extends formbase {
const CAP_EDIT = "local/treestudyplan:editstudyplan";
/**
* Translate parameters into customdata.
*
* Translate parameters into customdata.
*
* @param object $params The parameters for form initialization
* @return array Form data based on parameters
*/
*/
public static function init_customdata(object $params) {
$customdata = new stdClass;
$customdata->create = $params->mode=='create'?true:false;
if($customdata->create){
$customdata->create = $params->mode=='create' ? true : false;
if ($customdata->create) {
$customdata->plan = studyplan::find_by_id($params->studyplan_id);
} else {
$customdata->page = studyplanpage::find_by_id($params->page_id);
@ -58,42 +58,42 @@ class studyplanpage_editform extends formbase {
'accepted_types' => ['.jpg', '.png'],
'return_types' => \FILE_INTERNAL | \FILE_EXTERNAL,
];
return $customdata;
return $customdata;
}
/**
* Validate security access for this form based on the customdata generated by init_customdata
* Return true if validation passes, false or throw an exception if it does not.
*
*
* @param object $customdata The customdata for this form
* @return bool True if security validation passes.
* @return bool True if security validation passes.
* @throws \moodle_exception if access denied for a specific reason.
*/
public static function check_security(object $customdata) {
/*webservicehelper::require_capabilities(self::CAP_EDIT,$customdata->context); */
/*webservicehelper::require_capabilities(self::CAP_EDIT, $customdata->context); */
}
/**
* Generate form data from parameters
* Also validate parameters and access permissions here
*
*
* @param object $customdata The parameters for form initialization
* @return array Form data based on parameters
*/
*/
public function init_formdata(object $customdata) {
global $DB;
/* Use direct database retrieval to avoid our abstractions causing trouble
with existing moodle code assumptions.
with existing moodle code assumptions.
The form API does seem needlessly convoluted in it's use, but we need the editor...
*/
if($customdata->create) {
if ($customdata->create) {
$plan = $customdata->plan;
$entry = new stdClass;
$entry->studyplan_id = $plan->id();
// By default, make the start date of a new page, continue 1 day after the last page's start date;
$otherpages = $plan->pages();
if(count($otherpages) > 0){
if (count($otherpages) > 0) {
$lastpage = $otherpages[count($otherpages) -1];
// Propose 1 year after the last page's start date, if no end date is set.
@ -107,10 +107,10 @@ class studyplanpage_editform extends formbase {
} else {
// Determine the next august 1st for default value purposes. Only if no other page is available
$august = strtotime("first day of august this year");
if($august < time()) {
if ($august < time()) {
$august = strtotime("first day of august next year");
}
$entry->startdate = $august;
}
@ -129,7 +129,7 @@ class studyplanpage_editform extends formbase {
\context_system::instance(),
'local_treestudyplan',
'studyplanpage',
($customdata->create)?null:$customdata->page->id()
($customdata->create) ? null : $customdata->page->id()
);
return $entry;
@ -148,49 +148,49 @@ class studyplanpage_editform extends formbase {
// Define the form
$field = 'fullname';
$mform->addElement('text',$field,
get_string('studyplan_name','local_treestudyplan'),
$mform->addElement('text', $field,
get_string('studyplan_name', 'local_treestudyplan'),
[]);
$mform->addRule($field, null, 'required', null, 'client');
$field = 'shortname';
$mform->addElement('text',$field,
get_string('studyplan_shortname','local_treestudyplan'),
$mform->addElement('text', $field,
get_string('studyplan_shortname', 'local_treestudyplan'),
[]);
$mform->addRule($field, null, 'required', null, 'client');
$timeless = \get_config("local_treestudyplan","timelessperiods");
$timeless = \get_config("local_treestudyplan", "timelessperiods");
if ( !$timeless) {
$field = 'startdate';
$mform->addElement('date_selector',$field,
get_string('studyplan_startdate','local_treestudyplan'),
$mform->addElement('date_selector', $field,
get_string('studyplan_startdate', 'local_treestudyplan'),
[]);
$mform->addRule($field, null, 'required', null, 'client');
$field = 'enddate';
$mform->addElement('date_selector',$field,
get_string('studyplan_startdate','local_treestudyplan'),
$mform->addElement('date_selector', $field,
get_string('studyplan_startdate', 'local_treestudyplan'),
[]);
$mform->addRule($field, null, 'required', null, 'client');
}
$field = 'periods';
$mform->addElement('text_integer',$field,
get_string( ($timeless)?'studyplan_slots':'studyplan_periods','local_treestudyplan'),
$mform->addElement('text_integer', $field,
get_string( ($timeless) ? 'studyplan_slots' : 'studyplan_periods', 'local_treestudyplan'),
["unsigned" => true, "nonzero" => true]);
$mform->setType($field, PARAM_INT);
$mform->addRule($field, null, 'required', null, 'client');
$field = 'description_editor';
$mform->addElement('editor', $field,
get_string('studyplan_description', 'local_treestudyplan'),
null,
get_string('studyplan_description', 'local_treestudyplan'),
null,
$customdata->editoroptions);
$mform->setType($field, PARAM_RAW);
}
/**
/**
* Process the submitted data and perform necessary actions
* @param object $entry The processed form data;
* @return bool false if submission not successful
@ -199,13 +199,13 @@ class studyplanpage_editform extends formbase {
protected function process_submitted_data($entry) {
$customdata = (object)$this->_customdata;
if($customdata->create) {
if ($customdata->create) {
// Use our own abstraction to update the record, so caches are maintained
$page = studyplanpage::add(['fullname' => $entry->fullname,
'shortname' => $entry->shortname,
'startdate' => date("Y-m-d",$entry->startdate),
'enddate' => date("Y-m-d",$entry->enddate),
'startdate' => date("Y-m-d", $entry->startdate),
'enddate' => date("Y-m-d", $entry->enddate),
'periods' => $entry->periods,
'studyplan_id' => $customdata->plan->id(),
]);
@ -216,7 +216,7 @@ class studyplanpage_editform extends formbase {
\context_system::instance(),
'local_treestudyplan',
'studyplanpage',
$page->id());
$page->id());
// Update the description
$page->edit([
'description' => $entry->description,
@ -224,7 +224,7 @@ class studyplanpage_editform extends formbase {
]);
} else {
$page = $customdata->page;
// Process the provided files in the description editor
$entry = file_postupdate_standard_editor($entry,
'description',
@ -239,18 +239,17 @@ class studyplanpage_editform extends formbase {
'shortname' => $entry->shortname,
'description' => $entry->description,
'descriptionformat' => $entry->descriptionformat,
'startdate' => date("Y-m-d",$entry->startdate),
'enddate' => date("Y-m-d",$entry->enddate),
'startdate' => date("Y-m-d", $entry->startdate),
'enddate' => date("Y-m-d", $entry->enddate),
'periods' => $entry->periods,
]);
}
/* Return the editor structure of the new / edited page
Parse it through the clean_returnvalue function of exernal api (of which studyplanservice is a subclass)
so we return it in a consistent way
so we return it in a consistent way
*/
return studyplanservice::clean_returnvalue(studyplanpage::editor_structure(),$page->editor_model());
return studyplanservice::clean_returnvalue(studyplanpage::editor_structure(), $page->editor_model());
}
}

View File

@ -3,12 +3,10 @@ namespace local_treestudyplan\form;
use MoodleQuickForm_text;
use MoodleQuickForm;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . "/form/text.php");
class text_integer extends MoodleQuickForm_text {
/**
* Accepts a renderer
@ -32,14 +30,13 @@ class text_integer extends MoodleQuickForm_text {
}
$label = $this->getLabel();
$unsigned = (isset($this->_attributes['unsigned']) && $this->_attributes['unsigned']);
$nonzero = (isset($this->_attributes['nonzero']) && $this->_attributes['nonzero']);
$context = array(
'element' => $elementcontext,
'label' => $label,
'unsigned' => ($unsigned)?true:false ,
'nonzero' => ($nonzero)?true:false ,
'unsigned' => ($unsigned) ? true : false ,
'nonzero' => ($nonzero) ? true : false ,
'required' => $required,
'advanced' => $advanced,
'helpbutton' => $helpbutton,

View File

@ -95,14 +95,14 @@ class gradeinfo {
* Get the grade_item
* @return grade_item
*/
public function get_gradeitem() : grade_item {
public function get_gradeitem(): grade_item {
return $this->gradeitem;
}
/**
* Get the gradingscanner
* @return gradingscanner
*/
public function get_gradingscanner() : gradingscanner {
public function get_gradingscanner(): gradingscanner {
return $this->gradingscanner;
}
@ -110,7 +110,7 @@ class gradeinfo {
* Get the grade's scale if applicable
* @return grade_scale|null
*/
public function get_scale() : ?grade_scale {
public function get_scale(): ?grade_scale {
return $this->scale;
}
@ -118,7 +118,7 @@ class gradeinfo {
* Get content items (activity icons) from the repository
* @return content_item[]
*/
protected static function get_contentitems() : array {
protected static function get_contentitems(): array {
global $PAGE;
if (empty(static::$contentitems)) {
$PAGE->set_context(\context_system::instance());
@ -132,7 +132,7 @@ class gradeinfo {
* @param mixed $name Name of content item
* @return content_item|null
*/
public static function get_contentitem($name) : ?content_item {
public static function get_contentitem($name): ?content_item {
$contentitems = static::get_contentitems();
for ($i = 0; $i < count($contentitems); $i++) {
if ($contentitems[$i]->get_name() == $name) {
@ -148,7 +148,7 @@ class gradeinfo {
* @return \context_course
* @throws InvalidArgumentException if grade id is not found
*/
public static function get_coursecontext_by_id($id) : \context_course {
public static function get_coursecontext_by_id($id): \context_course {
$gi = grade_item::fetch(["id" => $id]);
if (!$gi || course_module_instance_pending_deletion($gi->courseid, $gi->itemmodule, $gi->iteminstance)) {
throw new \InvalidArgumentException ("Grade {$id} not found in database");
@ -174,7 +174,7 @@ class gradeinfo {
// Determine the icon for the associated activity.
$contentitem = static::get_contentitem($gi->itemmodule);
$this->icon = empty($contentitem) ? "" : $contentitem->get_icon();
$this->icon = empty($contentitem) ? "" : $contentitem->get_icon();
$this->scale = $gi->load_scale();
$this->outcome = $gi->load_outcome();
@ -210,7 +210,6 @@ class gradeinfo {
}
}
$this->typename = empty($contentitem) ? $gi->itemmodule : $contentitem->get_title()->get_value();
$this->gradingscanner = new gradingscanner($gi);
@ -222,7 +221,7 @@ class gradeinfo {
* Check if this gradable item is selected in the studyitem
* @return bool
*/
public function is_selected() : bool {
public function is_selected(): bool {
global $DB;
if ($this->studyitem) {
// Check if selected for this studyitem.
@ -260,7 +259,7 @@ class gradeinfo {
* Webservice structure for editor info
* @param int $value Webservice requirement constant
*/
public static function editor_structure($value = VALUE_REQUIRED) : \external_description {
public static function editor_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'grade_item id'),
"cmid" => new \external_value(PARAM_INT, 'course module id'),
@ -312,7 +311,7 @@ class gradeinfo {
* Webservice structure for userinfo
* @param int $value Webservice requirement constant
*/
public static function user_structure($value = VALUE_REQUIRED) : \external_description {
public static function user_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'grade_item id'),
"cmid" => new \external_value(PARAM_INT, 'course module id'),
@ -339,10 +338,10 @@ class gradeinfo {
global $DB;
$grade = $this->gradeitem->get_final($userid);
// Format grade for proper display
if(is_object($grade)) {
$finalgrade = \grade_format_gradevalue($grade->finalgrade,$this->gradeitem,true,null,1);
if (is_object($grade)) {
$finalgrade = \grade_format_gradevalue($grade->finalgrade, $this->gradeitem, true, null, 1);
} else {
$finalgrade = \grade_format_gradevalue(0,$this->gradeitem,true,null,1);
$finalgrade = \grade_format_gradevalue(0, $this->gradeitem, true, null, 1);
}
// Retrieve the aggregator and determine completion.
@ -358,8 +357,8 @@ class gradeinfo {
"name" => $this->name,
"typename" => $this->typename,
"grade" => $finalgrade,
"gradetype" => isset($this->scale) ? "completion" : "grade",
"feedback" => empty($grade) ? null : $grade->feedback,
"gradetype" => isset($this->scale) ? "completion" : "grade",
"feedback" => empty($grade) ? null : $grade->feedback,
"completion" => completion::label($completion),
"icon" => $this->icon,
"link" => $this->link,
@ -375,7 +374,7 @@ class gradeinfo {
* Export essential information for export
* @return array information model
*/
public function export_model() : array {
public function export_model(): array {
return [
"name" => $this->name,
"type" => $this->gradeitem->itemmodule,
@ -419,7 +418,7 @@ class gradeinfo {
* @param studyitem|null $studyitem Studyitem linked to the course which can be linked to created gradeinfo objects
* @return gradeinfo[] Array of gradeinfo
*/
public static function list_course_gradables($course, studyitem $studyitem = null) : array {
public static function list_course_gradables($course, studyitem $studyitem = null): array {
$list = [];
if (method_exists("\course_modinfo", "get_array_of_activities")) {
@ -462,7 +461,7 @@ class gradeinfo {
* @param studyitem $studyitem The studyitem to search for
* @return gradeinfo[] Array of gradeinfo
*/
public static function list_studyitem_gradables(studyitem $studyitem) : array {
public static function list_studyitem_gradables(studyitem $studyitem): array {
global $DB;
$table = 'local_treestudyplan_gradeinc';
$list = [];
@ -488,7 +487,6 @@ class gradeinfo {
return $list;
}
/**
* Webservice executor to include grade with studyitem or not.
* if both $inclue and $required are false, any existing DB record will be removed
@ -506,14 +504,14 @@ class gradeinfo {
$r = $DB->get_record($table, ['studyitem_id' => $itemid, 'grade_item_id' => $gradeid]);
if ($r) {
$r->include = 1;
$r->required = boolval($required) ? 1 : 0;
$r->required = boolval($required) ? 1 : 0;
$id = $DB->update_record($table, $r);
} else {
$DB->insert_record($table, [
'studyitem_id' => $itemid,
'grade_item_id' => $gradeid,
'include' => 1,
'required' => boolval($required) ? 1 : 0 ]
'required' => boolval($required) ? 1 : 0 ]
);
}
} else {

View File

@ -57,7 +57,7 @@ class gradingscanner {
* Check if a certain activity type is supported for scanning pending results
* @param string $mod name of activity module
*/
public static function supported($mod) : bool {
public static function supported($mod): bool {
if (!array_key_exists($mod, self::$modsupported)) {
self::$modsupported[$mod] = class_exists("\local_treestudyplan\\local\\ungradedscanners\\{$mod}_scanner");
}
@ -69,7 +69,7 @@ class gradingscanner {
* @param int $courseid Course id of the course to check
* @return int[] Array if user ids
*/
public static function get_course_students($courseid) : array {
public static function get_course_students($courseid): array {
global $CFG;
if (!array_key_exists($courseid, self::$coursestudents)) {
$students = [];
@ -99,7 +99,7 @@ class gradingscanner {
/**
* Check if this scanner is usable (has an internal activity specific scanner)
*/
public function is_available() : bool {
public function is_available(): bool {
return $this->scanner !== null;
}
@ -107,7 +107,7 @@ class gradingscanner {
* Check if the gradable item this scanner scans has pending submissions for a specific user
* @param int $userid ID of the user to check for
*/
public function pending($userid) : bool {
public function pending($userid): bool {
if (!array_key_exists($userid, $this->pendingcache)) {
if ($this->scanner === null) {
$this->pendingcache[$userid] = false;
@ -122,7 +122,7 @@ class gradingscanner {
* Webservice structure for basic info
* @param int $value Webservice requirement constant
*/
public static function structure($value = VALUE_OPTIONAL) : \external_description {
public static function structure($value = VALUE_OPTIONAL): \external_description {
return new \external_single_structure([
"ungraded" => new \external_value(PARAM_INT, 'number of ungraded submissions'),
"completed" => new \external_value(PARAM_INT, 'number of completed students'),
@ -135,7 +135,7 @@ class gradingscanner {
/**
* Webservice model for basic info
*/
public function model() : array {
public function model(): array {
// Upda.
$students = self::get_course_students($this->courseid);
$completed = 0;
@ -173,7 +173,7 @@ class gradingscanner {
* Check if a grade is considered passed according to the rules
* @param grade_grade $grade
*/
private function grade_passed($grade) : bool {
private function grade_passed($grade): bool {
// Function copied from bistate aggregator to avoid reference mazes.
global $DB;
$table = "local_treestudyplan_gradecfg";

View File

@ -69,7 +69,7 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
*/
protected function initialize($configstr) {
// First initialize with the defaults.
foreach (["thresh_excellent", "thresh_good", "thresh_completed", "thresh_progress", ] as $key) {
foreach (["thresh_excellent", "thresh_good", "thresh_completed", "thresh_progress" ] as $key) {
$val = intval(get_config('local_treestudyplan', "bistate_{$key}"));
if ($val >= 0 && $val <= 100) {
$this->cfg()->$key = floatval($val) / 100;
@ -84,7 +84,7 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
if (is_array($config)) {
// Copy all valid config settings to this item.
foreach (["thresh_excellent", "thresh_good", "thresh_completed", "thresh_progress", ] as $key) {
foreach (["thresh_excellent", "thresh_good", "thresh_completed", "thresh_progress" ] as $key) {
if (array_key_exists($key, $config)) {
$val = $config[$key];
if ($val >= 0 && $val <= 100) {
@ -142,7 +142,7 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
* 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.
*/
public function use_required_grades(){
public function use_required_grades() {
return true;
}
@ -173,7 +173,7 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
$totalrequired = 0;
$requiredmet = 0;
$minprogress = ($this->cfg()->accept_pending_as_submitted) ? completion::PENDING : completion::PROGRESS;
$minprogress = ($this->cfg()->accept_pending_as_submitted) ? completion : :PENDING : completion::PROGRESS;
foreach ($completions as $index => $c) {
@ -181,7 +181,7 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
$progress += ($c >= $minprogress) ? 1 : 0;
$failed += ($c <= completion::FAILED) ? 1 : 0;
if (in_array($index,$required)) {
if (in_array($index, $required)) {
// Not using count($required) to prevent nonexistant indices in the required list from messing things up.
$totalrequired += 1;
if ($c >= completion::COMPLETED) {
@ -193,10 +193,10 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
$started = $progress + $failed;
$allrequiredmet = ($requiredmet >= $totalrequired);
$fractioncompleted = ($total > 0) ? (floatval($completed) / floatval($total)) : 0.0;
$fractionprogress = ($total > 0) ? (floatval($progress) / floatval($total)) : 0.0;
$fractionfailed = ($total > 0) ? (floatval($failed) / floatval($total)) : 0.0;
$fractionstarted = ($total > 0) ? (floatval($started) / floatval($total)) : 0.0;
$fractioncompleted = ($total > 0) ? (floatval($completed) / floatval($total)): 0.0;
$fractionprogress = ($total > 0) ? (floatval($progress) / floatval($total)): 0.0;
$fractionfailed = ($total > 0) ? (floatval($failed) / floatval($total)): 0.0;
$fractionstarted = ($total > 0) ? (floatval($started) / floatval($total)): 0.0;
if ($total == 0) {
return completion::INCOMPLETE;
@ -230,7 +230,7 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
*/
public function aggregate_course(courseinfo $courseinfo, studyitem $studyitem, $userid) {
$course = $courseinfo->course();
$coursefinished = ($course->enddate) ? ($course->enddate < time()) : false;
$coursefinished = ($course->enddate) ? ($course->enddate < time()): false;
// Note: studyitem condition config is not used in this aggregator.
// Loop through all associated gradables and count the totals, completed, etc..
$completions = [];
@ -323,12 +323,12 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
$gradeitem = $gradeinfo->get_gradeitem();
$grade = $gradeitem->get_final($userid);
$course = \get_course($gradeitem->courseid); // Fetch course from cache.
$coursefinished = ($course->enddate) ? ($course->enddate < time()) : false;
$coursefinished = ($course->enddate) ? ($course->enddate < time()): false;
if (empty($grade)) {
return completion::INCOMPLETE;
} else if ($grade->finalgrade === null) {
// On assignments, grade NULL means a submission has not yet been graded,.
// On assignments, grade NULL means a submission has not yet been graded, .
// But on quizes this can also mean a quiz might have been started.
// Therefor, we treat a NULL result as a reason to check the relevant gradingscanner for presence of pending items.

View File

@ -68,13 +68,13 @@ class competency_aggregator extends \local_treestudyplan\aggregator {
*/
protected function initialize($configstr) {
// First initialize with the defaults.
foreach (["thresh_completed", ] as $key) {
foreach (["thresh_completed" ] as $key) {
$val = intval(get_config('local_treestudyplan', "competency_{$key}"));
if ($val >= 0 && $val <= 100) {
$this->cfg()->$key = floatval($val) / 100;
}
}
foreach (["use_failed", ] as $key) {
foreach (["use_failed" ] as $key) {
$this->cfg()->$key = boolval(get_config('local_treestudyplan', "competency_{$key}"));
}
@ -83,7 +83,7 @@ class competency_aggregator extends \local_treestudyplan\aggregator {
if (is_array($config)) {
// Copy all valid config settings to this item.
foreach (["thresh_completed", ] as $key) {
foreach (["thresh_completed" ] as $key) {
if (array_key_exists($key, $config)) {
$val = $config[$key];
if ($val >= 0 && $val <= 100) {
@ -91,7 +91,7 @@ class competency_aggregator extends \local_treestudyplan\aggregator {
}
}
}
foreach (["use_failed",] as $key) {
foreach (["use_failed" ] as $key) {
if (array_key_exists($key, $config)) {
$this->cfg()->$key = boolval($config[$key]);
}
@ -167,7 +167,7 @@ class competency_aggregator extends \local_treestudyplan\aggregator {
public function aggregate_course(courseinfo $courseinfo, studyitem $studyitem, $userid) {
// Retrieve the course competencies
$course = $courseinfo->course();
$cci = new coursecompetencyinfo($course,$studyitem);
$cci = new coursecompetencyinfo($course, $studyitem);
$competencies = $cci->course_competencies();
if (count($competencies) == 0) {
@ -180,14 +180,14 @@ class competency_aggregator extends \local_treestudyplan\aggregator {
$requiredcount = 0;
foreach ($competencies as $c) {
$count += 1;
$p = $cci->proficiency($c,$userid);
$p = $cci->proficiency($c, $userid);
if ($p->proficient) {
$proficient += 1;
}
if ($p->courseproficient) {
$courseproficient += 1;
}
if ($cci->is_required(($c))){
if ($cci->is_required(($c))) {
$requiredcount += 1;
if ($p->proficient) {
$requiredmet += 1;
@ -196,9 +196,9 @@ class competency_aggregator extends \local_treestudyplan\aggregator {
}
// Determine minimum for
// Determine minimum for
$limit = $this->cfg()->thresh_completed * $count;
$coursefinished = ($course->enddate) ? ($course->enddate < time()) : false;
$coursefinished = ($course->enddate) ? ($course->enddate < time()): false;
if ($proficient >= $count && $requiredmet >= $requiredcount) {
if ($limit < $count) {
@ -280,7 +280,6 @@ class competency_aggregator extends \local_treestudyplan\aggregator {
}
}
/**
* Determine completion for a single grade and user
* @param gradeinfo $gradeinfo Gradeinfo object for grade to check
@ -291,5 +290,4 @@ class competency_aggregator extends \local_treestudyplan\aggregator {
// COURSE COMPETENCIES DOESN'T REALLY USE THIS FUNCTION.
}
}

View File

@ -35,7 +35,6 @@ class core_aggregator extends \local_treestudyplan\aggregator {
/** @var bool */
public const DEPRECATED = false;
/**
* Create new instance of aggregation method
* @param string $configstr Aggregation configuration string
@ -50,7 +49,7 @@ class core_aggregator extends \local_treestudyplan\aggregator {
* @param string $configstr Aggregation configuration string
*/
protected function initialize($configstr) {
}
/**
@ -208,7 +207,6 @@ class core_aggregator extends \local_treestudyplan\aggregator {
}
}
/**
* Determine completion for a single grade and user
* @param gradeinfo $gradeinfo Gradeinfo object for grade to check

View File

@ -133,7 +133,7 @@ class tristate_aggregator extends \local_treestudyplan\aggregator {
*/
public function aggregate_course(courseinfo $courseinfo, studyitem $studyitem, $userid) {
$condition = self::DEFAULT_CONDITION;
$list = [];
foreach (gradeinfo::list_studyitem_gradables($studyitem) as $gi) {
$list[] = $this->grade_completion($gi, $userid);
@ -152,7 +152,7 @@ class tristate_aggregator extends \local_treestudyplan\aggregator {
public function aggregate_junction(array $completion, studyitem $studyitem, $userid) {
$completed = self::aggregate_completion($completion, $studyitem->conditions());
// If null result (conditions are unknown/null) - default to ALL.
return isset($completed) ? $completed : (self::aggregate_completion($completion, 'ALL'));
return isset($completed) ? $completed : (self::aggregate_completion($completion, 'ALL'));
}
/**
@ -169,7 +169,7 @@ class tristate_aggregator extends \local_treestudyplan\aggregator {
if (empty($grade)) {
return completion::INCOMPLETE;
} else if ($grade->finalgrade === null) {
// On assignments, grade NULL means a submission has not yet been graded,.
// On assignments, grade NULL means a submission has not yet been graded, .
// But on quizes this can also mean a quiz might have been started.
// Therefor, we treat a NULL result as a reason to check the relevant gradingscanner for presence of pending items.

View File

@ -68,13 +68,13 @@ class webservicehelper {
* @param string $capability The capability to scan for in the categories
* @return boolean
*/
public static function has_capability_in_any_category($capability,$userid=null ) {
public static function has_capability_in_any_category($capability, $userid=null ) {
global $USER;
if ($userid == null) {
$userid = $USER->id;
}
$list = courseservice::user_tops($userid,$capability);
$list = courseservice::user_tops($userid, $capability);
return boolval(count($list) > 0);
}

View File

@ -70,15 +70,15 @@ class randomimage {
];
/**
* Create a random polygon with number of points between 0 & $max_pts
* Create a random polygon with number of points between 0 & $maxpts
* @param \GdImage $im The image reource
* @param integer $max_pts Max number of point to use
* @param integer $maxpts Max number of point to use
* @return void
*/
private function random_polygon($im, Int $max_pts = 20)
private function random_polygon($im, Int $maxpts = 20)
{
$color = imagecolorallocatealpha($im, ...$this->random_color_alpha());
$pts = $this->random_pts(\random_int(3, $max_pts));
$pts = $this->random_pts(\random_int(3, $maxpts));
imagefilledpolygon($im, $pts, $color);
}
@ -100,7 +100,6 @@ class randomimage {
imagefilledarc($im, $cx, $cy, $w, $h, $s, $e, $col, $style);
}
/**
* Generates an array of random alpha color values.
* @return Array [r, g, b, a]
@ -116,7 +115,7 @@ class randomimage {
}
/**
* Generates a set of random points for a polygon [x1,y1, x2,y2,...]
* Generates a set of random points for a polygon [x1, y1, x2, y2, ...]
* @param integer $length Number of sets of points to generate
* @return Array The resulting array of points
*/
@ -130,7 +129,7 @@ class randomimage {
return $pts;
}
public function __construct($shapes=3,$width=256,$height=256) {
public function __construct($shapes=3, $width=256, $height=256) {
$this->shapes = $shapes;
$this->width = $width;
$this->height = $height;
@ -143,7 +142,7 @@ class randomimage {
}
$this->name = $string.".png";
$im = imagecreatetruecolor($this->width, $this->height);
for ($i = 0; $i < $this->shapes; $i++) {
switch(\random_int(1, 2)) {
@ -155,8 +154,8 @@ class randomimage {
break;
}
}
$this->tempfile = \tempnam("/tmp","tsp");
imagepng($im,$this->tempfile);
$this->tempfile = \tempnam("/tmp", "tsp");
imagepng($im, $this->tempfile);
imagedestroy($im);
}

View File

@ -56,7 +56,7 @@ class period {
/**
* Shortcut to studyplan (page)'s aggregator
*/
public function aggregator() : aggregator {
public function aggregator(): aggregator {
return $this->page->aggregator();
}
@ -88,7 +88,7 @@ class period {
$period = self::find_by_id($id);
} catch (\dml_missing_record_exception $x) {
// Period does not exist - create one ...
// Make a best guess estimate of the start and end date, based on surrounding periods,.
// Make a best guess estimate of the start and end date, based on surrounding periods, .
// Or specified duration of the page and the sequence of the periods .
$pcount = $page->periods();
$ystart = $page->startdate()->getTimestamp();
@ -118,7 +118,7 @@ class period {
}
// Continue period numbers if so configured
if (get_config("local_treestudyplan","continueperiodnumberingnewpage")) {
if (get_config("local_treestudyplan", "continueperiodnumberingnewpage")) {
$offset = 0;
foreach (studyplanpage::find_studyplan_children($page->studyplan()) as $p) {
if ($p->id() != $page->id()) {
@ -142,7 +142,6 @@ class period {
return $period;
}
/**
* Find all periods registered to a studyplan in sequence
* @param studyplanpage $page Studyplan page to find periods for
@ -181,7 +180,7 @@ class period {
* Return associated studyplan
* @return studyplan
*/
public function studyplan() : studyplan {
public function studyplan(): studyplan {
return $this->page->studyplan();
}
@ -242,7 +241,7 @@ class period {
* Webservice structure for basic info
* @param int $value Webservice requirement constant
*/
public static function structure($value = VALUE_REQUIRED) : \external_description {
public static function structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of period'),
"fullname" => new \external_value(PARAM_TEXT, 'Full name of period'),
@ -259,14 +258,14 @@ class period {
* @return array Webservice data model
*/
public function model() {
$timeless = get_config("local_treestudyplan","timelessperiods");
$timeless = get_config("local_treestudyplan", "timelessperiods");
return [
'id' => $this->r->id,
'fullname' => $this->r->fullname,
'shortname' => $this->r->shortname,
'period' => $this->r->period,
'startdate' => ($timeless)?0:$this->r->startdate,
'enddate' => ($timeless)?0:$this->r->enddate,
'startdate' => ($timeless) ? 0 : $this->r->startdate,
'enddate' => ($timeless) ? 0 : $this->r->enddate,
'timeless' => $timeless,
];
}
@ -276,7 +275,7 @@ class period {
* Use only when performing import! The static find() and find_for_page() functions create the period during normal operation
* @param array $fields Properties for ['page_id', 'fullname', 'shortname', 'period', 'startdate', 'enddate']
*/
public static function add($fields) : self {
public static function add($fields): self {
global $DB;
if (!isset($fields['page_id'])) {
@ -305,7 +304,7 @@ class period {
* Edit period properties
* @param array $fields Properties for ['fullname', 'shortname', 'startdate', 'enddate']
*/
public function edit($fields) : self {
public function edit($fields): self {
global $DB;
$pages = self::find_for_page($this->page());
@ -313,7 +312,7 @@ class period {
$next = (count($pages) > $this->period()) ? $pages[$this->period() + 1] : null;
$editable = ['fullname', 'shortname', 'startdate', 'enddate'];
$info = ['id' => $this->id, ];
$info = ['id' => $this->id ];
foreach ($editable as $f) {
if (array_key_exists($f, $fields)) {
$info[$f] = $fields[$f];
@ -347,7 +346,7 @@ class period {
/**
* Delete period
*/
public function delete() : success {
public function delete(): success {
global $DB;
$DB->delete_records(self::TABLE, ['id' => $this->id]);
return success::success();
@ -357,7 +356,7 @@ class period {
* Webservice structure for list of periods in page
* @param int $value Webservice requirement constant
*/
public static function page_structure($value = VALUE_REQUIRED) : \external_description {
public static function page_structure($value = VALUE_REQUIRED): \external_description {
return new \external_multiple_structure(self::structure(), "The periods in the page", $value);
}
@ -366,9 +365,9 @@ class period {
* @param studyplanpage $page The page to create the model for
* @return array Webservice data model
*/
public static function page_model(studyplanpage $page) : array {
public static function page_model(studyplanpage $page): array {
$model = [];
foreach (self::find_for_page($page,true) as $p) {
foreach (self::find_for_page($page, true) as $p) {
$model[] = $p->model();
}
return $model;

View File

@ -20,7 +20,6 @@
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace local_treestudyplan;
defined('MOODLE_INTERNAL') || die();
@ -30,7 +29,6 @@ use DateTime;
use moodle_url;
use stdClass;
/**
* Handle badge information in the same style as the other classes
*/
@ -38,7 +36,7 @@ class premium extends \external_api {
// Toggle the variable below to enable support for premium stuff.
// If set to false, all premium features will be enabled and no premium settings panel will be visible.
private static $premium_supported = false;
private static $premiumsupported = false;
private static $premiumcrt = "-----BEGIN CERTIFICATE-----
MIIDSzCCAjMCFFlyhmKf1fN7U5lQL/dtlsyP24AQMA0GCSqGSIb3DQEBCwUAMGEx
@ -64,31 +62,31 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
private static $cachedpremiumstatus = null;
public static function supported() {
return self::$premium_supported;
return self::$premiumsupported;
}
private static function decrypt($encrypted) {
// Get the public key.
$key = \openssl_get_publickey(self::$premiumcrt);
if ($key === false ){
if ($key === false ) {
throw new \ValueError("Error parsing public key data)");
}
// Determine the key size.
$keysize = \openssl_pkey_get_details($key)["bits"];
//
//
$blocksize = ($keysize / 8); // Bits / 8. Whether padded or not.
// Decode data in
// Decode data in
$b64 = \base64_decode($encrypted);
if ($b64 === false) {
throw new \ValueError("Error in base64 decoding");
}
$data = \str_split($b64,$blocksize);
$data = \str_split($b64, $blocksize);
$decrypted = "";
$i = 0;
foreach($data as $chunk) {
if (\openssl_public_decrypt($chunk,$dchunk,$key, \OPENSSL_PKCS1_PADDING)) {
if (\openssl_public_decrypt($chunk, $dchunk, $key, \OPENSSL_PKCS1_PADDING)) {
$decrypted .= $dchunk;
} else {
throw new \ValueError("Error decrypting chunk $i ({$blocksize} bytes)");
@ -104,23 +102,23 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
return $decrypted;
}
private static function trim_headers($data) {
// Headers are repeated in this function for easier testing and copy-pasting into other projects.
$START_HEADER = "----- BEGIN ACTIVATION KEY -----";
$END_HEADER = "----- END ACTIVATION KEY -----";
$parts = preg_split("/\r?\n/",\trim($data));
$STARTHEADER = "----- BEGIN ACTIVATION KEY -----";
$ENDHEADER = "----- END ACTIVATION KEY -----";
$parts = preg_split("/\r?\n/", \trim($data));
if (count($parts) > 2) {
$start = -1;
$end = -1;
for($i = 0; $i < count($parts); $i++) {
$p = trim(preg_replace('/\s+/u', ' ', $parts[$i])); // Make sure all unicode spaces are converted to normal spaces before comparing...
if ( $p == $START_HEADER ) {
if ( $p == $STARTHEADER ) {
$start = $i+1;
}
if ($start > 0 && $p == $END_HEADER) {
if ($start > 0 && $p == $ENDHEADER) {
$end = $i;
}
}
@ -129,7 +127,7 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
throw new \ValueError("Invalid activation key wrappers");
} else {
$keyslice = array_slice($parts, $start, $end - $start);
return implode("\n",$keyslice);
return implode("\n", $keyslice);
}
} else {
throw new \ValueError("Invalid activation key");
@ -141,7 +139,7 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
* @return bool
*/
public static function enabled() {
if (self::$premium_supported) {
if (self::$premiumsupported) {
$status = self::premiumStatus();
return $status->enabled;
} else {
@ -154,10 +152,10 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
* @param string $intent The intent to search for
* @return bool
*/
public static function has_intent($intent){
public static function has_intent($intent) {
$status = self::premiumStatus();
if ($status->enabled) {
return \in_array(\strtolower($intent),$status->intents);
return \in_array(\strtolower($intent), $status->intents);
} else {
return false;
}
@ -166,25 +164,25 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
public static function debuginfo() {
$s = "<pre>";
try {
$activationkey = \get_config("local_treestudyplan","premium_key");
$activationkey = \get_config("local_treestudyplan", "premium_key");
if (strlen($activationkey) > 0) {
$keydata = self::trim_headers($activationkey);
$json = self::decrypt($keydata);
$s .= "Decoded key data:\n----\n";
$s .= $json . "\n----\n";
$decoded = \json_decode($json,false);
$decoded = \json_decode($json, false);
$s .= "Read as object:\n----\n";
$s .= print_r($decoded,true) ."\n----\n";
$s .= print_r($decoded, true) ."\n----\n";
$status = self::premiumStatus();
$s .= "Parsed premium status block:\n----\n";
$s .= print_r($status,true) ."\n----\n";
$s .= print_r($status, true) ."\n----\n";
$s .= "Message: " . self::statusdescription() . "\n";
} else {
$s .= "Premium key empty";
}
} catch (\Throwable $x) {
$s .= "!!! " . get_class($x) . ": " . $x->getCode() . " | " . $x->getMessage(). "\n";
$stack = explode("\n",$x->getTraceAsString());
$stack = explode("\n", $x->getTraceAsString());
foreach ($stack as $l) {
$s .= " " . trim($l) ."\n";
}
@ -193,13 +191,13 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
$s.="</pre>";
return $s;
}
/**
/**
* Determine, cache and retrieve premium status
* @return object
*/
protected static function premiumStatus() {
if (!isset(self::$cachedpremiumstatus)) {
// Initialize default object.
$o = new \stdClass;
$o->enabled = false;
@ -210,28 +208,28 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
$o->expired = false;
$o->issued = "";
try {
$activationkey = \get_config("local_treestudyplan","premium_key");
$activationkey = \get_config("local_treestudyplan", "premium_key");
if (strlen($activationkey) > 0) {
$keydata = self::trim_headers($activationkey);
$json = self::decrypt($keydata);
$decoded = \json_decode($json,false);
$decoded = \json_decode($json, false);
if (is_object($decoded)) {
// Copy basic data/
$keys = ["name","website","expires","issued"];
$keys = ["name", "website", "expires", "issued"];
foreach ( $keys as $k) {
if (isset($decoded->$k)) {
$o->$k = $decoded->$k;
}
}
if(!empty($decoded->intent)) {
$o->intents = explode(",",$decoded->intent);
if (!empty($decoded->intent)) {
$o->intents = explode(", ", $decoded->intent);
}
// Convert dates to DateTime for
// Convert dates to DateTime for
$now = new \DateTime();
$issuedate = new \DateTime($o->issued);
$expirydate = new \DateTime(); // Default to now
@ -244,7 +242,7 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
} catch (\Exception $x) {}
}
if ( \in_array('treestudyplan',$o->intents)
if ( \in_array('treestudyplan', $o->intents)
&& !empty($o->issued)
&& self::website_match($o->website)
) {
@ -256,17 +254,17 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
$o->enabled = false;
}
// Format dates localized.
$o->issued = \userdate($issuedate->getTimestamp(),\get_string('strftimedate','langconfig'));
$o->issued = \userdate($issuedate->getTimestamp(), \get_string('strftimedate', 'langconfig'));
if ($o->expires == "never") {
$o->expires = \get_string("premium:never",'local_treestudyplan');
$o->expires = \get_string("premium:never", 'local_treestudyplan');
} else {
$o->expires = \userdate($expirydate->getTimestamp(),\get_string('strftimedate','langconfig'));
$o->expires = \userdate($expirydate->getTimestamp(), \get_string('strftimedate', 'langconfig'));
}
}
}
}
}
} catch (\ValueError $x) {
$o->status = \get_string("premium:invalidactivationcontent","local_treestudyplan");
$o->status = \get_string("premium:invalidactivationcontent", "local_treestudyplan");
}
self::$cachedpremiumstatus = $o;
@ -280,13 +278,13 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
private static function website_match($key) {
global $CFG;
$site = $CFG->wwwroot;
// Add double slashes to key and site if no scheme is set.
// Basically: if no double slashes present before any dots,slashes or @s.
if(!\preg_match_all('#^[^./@]*?//#',$key )) {
// Basically: if no double slashes present before any dots, slashes or @s.
if (!\preg_match_all('#^[^./@]*?//#', $key )) {
$key = "//".$key;
}
if(!\preg_match_all('#^[^./@]*?//#',$site)) {
if (!\preg_match_all('#^[^./@]*?//#', $site)) {
$site = "//".$site;
}
// Use parse_url() to split path and host.
@ -304,17 +302,17 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
}
// First match the host part.
$keyparts = \array_reverse(\explode(".",$keyurl->host));
$siteparts = \array_reverse(\explode(".",$siteurl->host));
$keyparts = \array_reverse(\explode(".", $keyurl->host));
$siteparts = \array_reverse(\explode(".", $siteurl->host));
// Trim starting www from both parts, since site.domain and www.site.domain should be treated as the same.
if (($x = \array_pop($keyparts)) != "www") {\array_push($keyparts,$x);}
if (($x = \array_pop($siteparts)) != "www") {\array_push($siteparts,$x);}
if (($x = \array_pop($keyparts)) != "www") {\array_push($keyparts, $x);}
if (($x = \array_pop($siteparts)) != "www") {\array_push($siteparts, $x);}
for ($i = 0; $i < count($keyparts); $i++) {
// No match if the site does not have a part, but the key does. Unless the key part is *
if (!isset($siteparts[$i]) ) {
if($keyparts[$i] != "*") {
if ($keyparts[$i] != "*") {
return false;
} else {
$i++; //increment $i by one before break, to make sure the comparison following this loop holds.
@ -324,7 +322,7 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
// Now do a proper case insensitive check for matching.
// Uses fnmatch to easily handle shell type wildcards.
if ( ! \fnmatch($keyparts[$i],$siteparts[$i],\FNM_CASEFOLD)) {
if ( ! \fnmatch($keyparts[$i], $siteparts[$i], \FNM_CASEFOLD)) {
return false;
}
}
@ -335,39 +333,39 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
// If we made it here then the host part matches. Now check the path.
// If path is /*, matches all subpaths including /
$keypath = empty($keyurl->path)?"/":$keyurl->path;
$sitepath = empty($siteurl->path)?"/":$siteurl->path;
$keypath = empty($keyurl->path) ? "/" : $keyurl->path;
$sitepath = empty($siteurl->path) ? "/" : $siteurl->path;
// Trim trailing / from both paths before comparison
if (\strlen($sitepath) > 1) {
$sitepath = \rtrim($sitepath,"/");
$sitepath = \rtrim($sitepath, "/");
}
if (\strlen($keypath) > 1) {
$keypath = \rtrim($keypath,"/");
$keypath = \rtrim($keypath, "/");
}
// Do a case insensitive fnmatch on the site so wildcards are matched too.
return \fnmatch($keypath,$sitepath,\FNM_CASEFOLD);
return \fnmatch($keypath, $sitepath, \FNM_CASEFOLD);
}
/**
* Parameter description for webservice function get_premiumstatus
*/
public static function get_premiumstatus_parameters() : \external_function_parameters {
public static function get_premiumstatus_parameters(): \external_function_parameters {
return new \external_function_parameters([]);
}
/**
* Return value description for webservice function get_premiumstatus
*/
public static function get_premiumstatus_returns() : \external_description {
public static function get_premiumstatus_returns(): \external_description {
return new \external_single_structure([
"enabled" => new \external_value(PARAM_BOOL, 'premium status enabled'),
"website" => new \external_value(PARAM_TEXT, 'premium registration website'),
"name" => new \external_value(PARAM_TEXT, 'premium registration name'),
"expires" => new \external_value(PARAM_TEXT, 'premium registration expiry date'),
"expired" => new \external_value(PARAM_BOOL, 'premium status expired'),
"intents" => new \external_multiple_structure(new \external_value(PARAM_TEXT),'additional intents included in the license '),
"intents" => new \external_multiple_structure(new \external_value(PARAM_TEXT), 'additional intents included in the license '),
]);
}
@ -376,7 +374,7 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
* @return object
*/
public static function get_premiumstatus() {
if (self::$premium_supported) {
if (self::$premiumsupported) {
$status = self::premiumStatus();
$keys = [
"enabled",
@ -386,7 +384,7 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
"expired",
"intents",
];
$result = [];
foreach ( $keys as $param) {
$result[$param] = $status->$param;
@ -416,19 +414,19 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
$msg->issued = $status->issued;
$msg->expires = $status->expires;
if ($status->website != "*") {
$msg->sitestatus = \get_string("premium:onsite",'local_treestudyplan',$status);
$msg->sitestatus = \get_string("premium:onsite", 'local_treestudyplan', $status);
} else {
$msg->sitestatus = \get_string("premium:anywhere",'local_treestudyplan');
$msg->sitestatus = \get_string("premium:anywhere", 'local_treestudyplan');
}
if($status->enabled) {
return \get_string("premium:active",'local_treestudyplan',$msg);
if ($status->enabled) {
return \get_string("premium:active", 'local_treestudyplan', $msg);
} else if ($status->expired) {
return \get_string("premium:expired",'local_treestudyplan',$msg);
return \get_string("premium:expired", 'local_treestudyplan', $msg);
} else if (!self::website_match($status->website)) {
return \get_string("premium:siteinvalid",'local_treestudyplan',$status->website);
return \get_string("premium:siteinvalid", 'local_treestudyplan', $status->website);
} else {
return \get_string("premium:notregistered",'local_treestudyplan',$msg);
return \get_string("premium:notregistered", 'local_treestudyplan', $msg);
}
}
@ -437,7 +435,7 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
*/
public static function require_premium($message="premiumfeature:warning") {
if (! self::enabled()) {
throw new \moodle_exception($message,"local_treestudyplan");
throw new \moodle_exception($message, "local_treestudyplan");
}
}

View File

@ -83,7 +83,7 @@ class provider implements \core_privacy\local\metadata\provider,
* @param int $userid The user to search.
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
*/
public static function get_contexts_for_userid(int $userid) : contextlist {
public static function get_contexts_for_userid(int $userid): contextlist {
$contextlist = new \core_privacy\local\request\contextlist();
$contextlist->add_system_context(); // For invitations.
@ -260,7 +260,7 @@ class provider implements \core_privacy\local\metadata\provider,
// Determine the relevant plan_ids for this context.
$sql = "SELECT s.id FROM {local_treestudyplan}
WHERE ( s.context_id IS NULL OR s.context_id == 0 OR s.context_id = :contextid)) ";
$planids = $DB->get_fieldset_sql($sql, ["contextid" => $context->id, ]);
$planids = $DB->get_fieldset_sql($sql, ["contextid" => $context->id ]);
// If plan ids not empty, they will be processed later.
// Also delete all invitations for these users.
@ -270,7 +270,7 @@ class provider implements \core_privacy\local\metadata\provider,
} else if ($context->contextlevel == CONTEXT_COURSECAT) {
$sql = "SELECT s.id FROM {local_treestudyplan}
WHERE (s.context_id = :contextid)";
$planids = $DB->get_fieldset_sql($sql, ["contextid" => $context->id, ]);
$planids = $DB->get_fieldset_sql($sql, ["contextid" => $context->id ]);
// If plan ids not empty, they will be processed later.
}

View File

@ -45,12 +45,12 @@ class reportinvite_form extends moodleform {
$mform->addElement('hidden', 'update', 0);
$mform->setType('update', PARAM_INT);
$mform->addElement('text', 'name', get_string('invite_name', 'local_treestudyplan'), array('size' => 50));
$mform->addElement('text', 'name', get_string('invite_name', 'local_treestudyplan'), ['size' => 50]);
$mform->setType('name', PARAM_NOTAGS); // Set type of element.
$mform->setDefault('name', ''); // Default value.
$mform->addRule('name', get_string('required'), 'required', null, 'client');
$mform->addElement('text', 'email', get_string('invite_email', 'local_treestudyplan'), array('size' => 20));
$mform->addElement('text', 'email', get_string('invite_email', 'local_treestudyplan'), ['size' => 20]);
$mform->setType('email', PARAM_NOTAGS); // Set type of element.
$mform->setDefault('email', ''); // Default value.
$mform->addRule('email', get_string('required'), 'required', null, 'client');
@ -68,7 +68,7 @@ class reportinvite_form extends moodleform {
* @return array validation data
*/
public function validation($data, $files) {
return array();
return [];
}
/**

View File

@ -40,19 +40,18 @@ class reportservice extends \external_api {
*/
const CAP_VIEW = "local/treestudyplan:viewuserreports";
public static function get_report_structure_parameters() : \external_function_parameters {
public static function get_report_structure_parameters(): \external_function_parameters {
return new \external_function_parameters([
"pageid" => new \external_value(PARAM_INT, 'id of studyplan page'),
"firstperiod" => new \external_value(PARAM_INT, 'first period to include in report',VALUE_DEFAULT),
"lastperiod" => new \external_value(PARAM_INT, 'last period to include in report',VALUE_DEFAULT),
"firstperiod" => new \external_value(PARAM_INT, 'first period to include in report', VALUE_DEFAULT),
"lastperiod" => new \external_value(PARAM_INT, 'last period to include in report', VALUE_DEFAULT),
]);
}
/**
* Return value description for webservice function list_user_studyplans
*/
public static function get_report_structure_returns() : \external_description {
public static function get_report_structure_returns(): \external_description {
return new \external_single_structure([
"periods" => new \external_multiple_structure(new \external_single_structure([
"period" => period::structure(),
@ -75,14 +74,14 @@ class reportservice extends \external_api {
* @param int|null $lastperiod Last period to include in report
* @return object
*/
public static function get_report_structure($pageid,$firstperiod=null,$lastperiod=null) {
public static function get_report_structure($pageid, $firstperiod=null, $lastperiod=null) {
$page = studyplanpage::find_by_id($pageid);
webservicehelper::require_capabilities(self::CAP_VIEW,$page->studyplan()->context());
webservicehelper::require_capabilities(self::CAP_VIEW, $page->studyplan()->context());
$plan = $page->studyplan();
if (empty($firstperiod)) {
$firstperiod = 1;
}
}
if (empty($lastperiod)) {
// Index for periods starts at 1, so the period count is same as length
$lastperiod = $page->periods();
@ -111,30 +110,29 @@ class reportservice extends \external_api {
"line" => $line->simple_model(),
"items" => [],
];
$items = studyitem::search_studyline_children($line,$i,studyitem::COURSE);
$items = studyitem::search_studyline_children($line, $i, studyitem::COURSE);
if (count($items) > 0) {
foreach ($items as $item) {
$lmodel["items"][] = $item->editor_model();
}
// Only include the line if it has actual children - saves us from muddying up the report.
$pmodel['lines'][] = $lmodel;
}
}
$model["periods"][] = $pmodel;
}
return $model;
}
public static function get_report_data_parameters() : \external_function_parameters {
public static function get_report_data_parameters(): \external_function_parameters {
return new \external_function_parameters([
"pageid" => new \external_value(PARAM_INT, 'id of studyplan page'),
"userid" => new \external_value(PARAM_INT, 'id of user'),
"firstperiod" => new \external_value(PARAM_INT, 'first period to include in report',VALUE_DEFAULT),
"lastperiod" => new \external_value(PARAM_INT, 'last period to include in report',VALUE_DEFAULT),
"firstperiod" => new \external_value(PARAM_INT, 'first period to include in report', VALUE_DEFAULT),
"lastperiod" => new \external_value(PARAM_INT, 'last period to include in report', VALUE_DEFAULT),
]);
}
@ -142,22 +140,21 @@ class reportservice extends \external_api {
/**
* Return value description for webservice function list_user_studyplans
*/
public static function get_report_data_returns() : \external_description {
public static function get_report_data_returns(): \external_description {
return new \external_multiple_structure(studyitem::user_structure(), "Information per studyitem");
}
public static function get_report_data($pageid,$userid,$firstperiod=null,$lastperiod=null) {
public static function get_report_data($pageid, $userid, $firstperiod=null, $lastperiod=null) {
$page = studyplanpage::find_by_id($pageid);
webservicehelper::require_capabilities(self::CAP_VIEW,$page->studyplan()->context());
webservicehelper::require_capabilities(self::CAP_VIEW, $page->studyplan()->context());
$plan = $page->studyplan();
if (!$plan->has_linked_user($userid)) {
throw new \moodle_exception("error:usernotassociated","local_treestudyplan");
throw new \moodle_exception("error:usernotassociated", "local_treestudyplan");
}
if (empty($firstperiod)) {
$firstperiod = 1;
}
}
if (empty($lastperiod)) {
// Index for periods starts at 1, so the period count is same as length
$lastperiod = $page->periods();
@ -170,7 +167,7 @@ class reportservice extends \external_api {
for($i = $firstperiod; $i <= $lastperiod; $i++) {
$lines = studyline::find_page_children($page);
foreach ($lines as $line) {
$items = studyitem::search_studyline_children($line,$i,studyitem::COURSE);
$items = studyitem::search_studyline_children($line, $i, studyitem::COURSE);
if (count($items) > 0) {
foreach ($items as $item) {
$model[] = $item->user_model($userid);
@ -183,9 +180,7 @@ class reportservice extends \external_api {
}
public static function get_report_details_parameters() : \external_function_parameters {
public static function get_report_details_parameters(): \external_function_parameters {
return new \external_function_parameters([
"itemid" => new \external_value(PARAM_INT, 'id of studyitem'),
"userid" => new \external_value(PARAM_INT, 'id of user'),
@ -195,7 +190,7 @@ class reportservice extends \external_api {
/**
* Return value description for webservice function list_user_studyplans
*/
public static function get_report_details_returns() : \external_description {
public static function get_report_details_returns(): \external_description {
return studyitem::user_structure();
}
@ -205,16 +200,15 @@ class reportservice extends \external_api {
* @param int $userid ID of user to check specific info for
* @return array
*/
public static function get_report_details($itemid,$userid) {
public static function get_report_details($itemid, $userid) {
$item = studyitem::find_by_id($itemid);
$plan = $item->studyline()->studyplan();
webservicehelper::require_capabilities(self::CAP_VIEW,$plan->context());
webservicehelper::require_capabilities(self::CAP_VIEW, $plan->context());
if (!$plan->has_linked_user($userid)) {
throw new \moodle_exception("error:usernotassociated","local_treestudyplan");
throw new \moodle_exception("error:usernotassociated", "local_treestudyplan");
}
return $item->user_model($userid);
}
}

View File

@ -48,11 +48,11 @@ class studentstudyplanservice extends \external_api {
* list_user_studyplans *
* *
************************/
/**
* Parameter description for webservice function list_user_studyplans
*/
public static function list_user_studyplans_parameters() : \external_function_parameters {
public static function list_user_studyplans_parameters(): \external_function_parameters {
return new \external_function_parameters([
"userid" => new \external_value(PARAM_INT, 'id of student', VALUE_DEFAULT),
]);
@ -61,7 +61,7 @@ class studentstudyplanservice extends \external_api {
/**
* Return value description for webservice function list_user_studyplans
*/
public static function list_user_studyplans_returns() : \external_description {
public static function list_user_studyplans_returns(): \external_description {
return new \external_multiple_structure(
studyplan::simple_structure()
);
@ -95,7 +95,7 @@ class studentstudyplanservice extends \external_api {
/**
* Parameter description for webservice function get_user_studyplan
*/
public static function get_user_studyplan_parameters() : \external_function_parameters {
public static function get_user_studyplan_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"userid" => new \external_value(PARAM_INT, 'id of user'),
"studyplanid" => new \external_value(PARAM_INT, 'id of specific studyplan to provide'),
@ -105,7 +105,7 @@ class studentstudyplanservice extends \external_api {
/**
* Return value description for webservice function get_user_studyplan
*/
public static function get_user_studyplan_returns() : \external_description {
public static function get_user_studyplan_returns(): \external_description {
return studyplan::user_structure();
}
@ -126,7 +126,7 @@ class studentstudyplanservice extends \external_api {
}
if ($studyplan->exist_for_user($userid)) {
$model = $studyplan->user_model($userid);
return $model;
} else {
@ -143,7 +143,7 @@ class studentstudyplanservice extends \external_api {
/**
* Parameter description for webservice function get_user_page
*/
public static function get_user_page_parameters() : \external_function_parameters {
public static function get_user_page_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"userid" => new \external_value(PARAM_INT, 'id of user'),
"pageid" => new \external_value(PARAM_INT, 'id of specific studyplan to provide'),
@ -153,7 +153,7 @@ class studentstudyplanservice extends \external_api {
/**
* Return value description for webservice function get_user_page
*/
public static function get_user_page_returns() : \external_description {
public static function get_user_page_returns(): \external_description {
return studyplan::user_structure();
}
@ -185,7 +185,7 @@ class studentstudyplanservice extends \external_api {
/**
* Parameter description for webservice function list_invited_studyplan
*/
public static function list_invited_studyplans_parameters() : \external_function_parameters {
public static function list_invited_studyplans_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"invitekey" => new \external_value(PARAM_RAW, 'invite key'),
] );
@ -194,7 +194,7 @@ class studentstudyplanservice extends \external_api {
/**
* Return value description for webservice function list_invited_studyplan
*/
public static function list_invited_studyplans_returns() : \external_description {
public static function list_invited_studyplans_returns(): \external_description {
return new \external_multiple_structure(
studyplan::simple_structure()
);
@ -208,7 +208,7 @@ class studentstudyplanservice extends \external_api {
public static function list_invited_studyplans($invitekey) {
global $DB;
// First check if studyplan sharing is enabled.
if (!get_config("local_treestudyplan","enableplansharing")) {
if (!get_config("local_treestudyplan", "enableplansharing")) {
return [];
}
@ -243,7 +243,7 @@ class studentstudyplanservice extends \external_api {
/**
* Parameter description for webservice function get_invited_studyplan
*/
public static function get_invited_studyplan_parameters() : \external_function_parameters {
public static function get_invited_studyplan_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"invitekey" => new \external_value(PARAM_RAW, 'invite key'),
"studyplanid" => new \external_value(PARAM_INT, 'studyplan_id'),
@ -253,7 +253,7 @@ class studentstudyplanservice extends \external_api {
/**
* Return value description for webservice function get_invited_studyplan
*/
public static function get_invited_studyplan_returns() : \external_description {
public static function get_invited_studyplan_returns(): \external_description {
return studyplan::user_structure();
}
@ -263,10 +263,10 @@ class studentstudyplanservice extends \external_api {
* @param int $studyplanid ID of the studyplan to retrieve
* @return array
*/
public static function get_invited_studyplan($invitekey,$studyplanid) {
public static function get_invited_studyplan($invitekey, $studyplanid) {
global $DB;
// First check if studyplan sharing is enabled.
if (!get_config("local_treestudyplan","enableplansharing")) {
if (!get_config("local_treestudyplan", "enableplansharing")) {
return [];
}
$invite = $DB->get_record_select(
@ -280,7 +280,7 @@ class studentstudyplanservice extends \external_api {
}
// Do not validate the context in this instance to avoid requiring logins when this is not wanted
$studyplan = studyplan::find_by_id($studyplanid);
$userid = $invite->user_id;
@ -290,7 +290,7 @@ class studentstudyplanservice extends \external_api {
} else {
throw new \moodle_exception("The selected studyplan is suspended");
}
} else {
throw new \moodle_exception("Invitation's user is not linked to this studyplan");
}
@ -305,7 +305,7 @@ class studentstudyplanservice extends \external_api {
/**
* Parameter description for webservice function get_invited_studyplan
*/
public static function get_invited_page_parameters() : \external_function_parameters {
public static function get_invited_page_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"invitekey" => new \external_value(PARAM_RAW, 'invite key'),
"pageid" => new \external_value(PARAM_INT, 'studyplan page id'),
@ -315,7 +315,7 @@ class studentstudyplanservice extends \external_api {
/**
* Return value description for webservice function get_invited_studyplan
*/
public static function get_invited_page_returns() : \external_description {
public static function get_invited_page_returns(): \external_description {
return studyplanpage::user_structure();
}
@ -325,10 +325,10 @@ class studentstudyplanservice extends \external_api {
* @param int $pageid ID of the studyplan to retrieve
* @return array
*/
public static function get_invited_page($invitekey,$pageid) {
public static function get_invited_page($invitekey, $pageid) {
global $DB;
// First check if studyplan sharing is enabled.
if (!get_config("local_treestudyplan","enableplansharing")) {
if (!get_config("local_treestudyplan", "enableplansharing")) {
return [];
}
$invite = $DB->get_record_select(
@ -342,7 +342,7 @@ class studentstudyplanservice extends \external_api {
}
// Do not validate the context in this instance to avoid requiring logins when this is not wanted
$page = studyplanpage::find_by_id($pageid);
$studyplan = $page->studyplan();
$userid = $invite->user_id;
@ -363,14 +363,14 @@ class studentstudyplanservice extends \external_api {
/**
* Parameter description for webservice function list_own_studyplans
*/
public static function list_own_studyplans_parameters() : \external_function_parameters {
public static function list_own_studyplans_parameters(): \external_function_parameters {
return new \external_function_parameters([]);
}
/**
* Return value description for webservice function list_own_studyplans
*/
public static function list_own_studyplans_returns() : \external_description {
public static function list_own_studyplans_returns(): \external_description {
return new \external_multiple_structure(
studyplan::simple_structure()
);
@ -401,7 +401,7 @@ class studentstudyplanservice extends \external_api {
/**
* Parameter description for webservice function get_own_studyplan
*/
public static function get_own_studyplan_parameters() : \external_function_parameters {
public static function get_own_studyplan_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"studyplanid" => new \external_value(PARAM_INT, 'id of studyplan to retrieve'),
] );
@ -410,7 +410,7 @@ class studentstudyplanservice extends \external_api {
/**
* Return value description for webservice function get_own_studyplan
*/
public static function get_own_studyplan_returns() : \external_description {
public static function get_own_studyplan_returns(): \external_description {
return studyplan::user_structure();
}
@ -446,7 +446,7 @@ class studentstudyplanservice extends \external_api {
/**
* Parameter description for webservice function get_own_page
*/
public static function get_own_page_parameters() : \external_function_parameters {
public static function get_own_page_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"pageid" => new \external_value(PARAM_INT, 'id of studyplan to retrieve'),
] );
@ -455,12 +455,12 @@ class studentstudyplanservice extends \external_api {
/**
* Return value description for webservice function get_own_page
*/
public static function get_own_page_returns() : \external_description {
public static function get_own_page_returns(): \external_description {
return studyplan::user_structure();
}
/**
* Get studyplanpage for current user
* Get studyplanpage for current user
* @param int $pagid ID of specific studyplan page
* @return array
*/
@ -491,14 +491,14 @@ class studentstudyplanservice extends \external_api {
/**
* Parameter description for webservice function list_teaching_studyplans
*/
public static function list_teaching_studyplans_parameters() : \external_function_parameters {
public static function list_teaching_studyplans_parameters(): \external_function_parameters {
return new \external_function_parameters( [] );
}
/**
* Return value description for webservice function list_teaching_studyplans
*/
public static function list_teaching_studyplans_returns() : \external_description {
public static function list_teaching_studyplans_returns(): \external_description {
return new \external_multiple_structure(
studyplan::simple_structure()
);
@ -532,14 +532,14 @@ class studentstudyplanservice extends \external_api {
/**
* Parameter description for webservice function list_teaching_studyplans
*/
public static function list_coaching_studyplans_parameters() : \external_function_parameters {
public static function list_coaching_studyplans_parameters(): \external_function_parameters {
return new \external_function_parameters( [] );
}
/**
* Return value description for webservice function list_teaching_studyplans
*/
public static function list_coaching_studyplans_returns() : \external_description {
public static function list_coaching_studyplans_returns(): \external_description {
return new \external_multiple_structure(
studyplan::simple_structure()
);
@ -557,17 +557,17 @@ class studentstudyplanservice extends \external_api {
\external_api::validate_context(\context_system::instance());
// Return empty list if coach role not enabled
if ( ! (premium::enabled() && \get_config("local_treestudyplan","enablecoach")) ) {
if ( ! (premium::enabled() && \get_config("local_treestudyplan", "enablecoach")) ) {
return [];
}
$records = $DB->get_records("local_treestudyplan_coach",["user_id" => $userid]);
$records = $DB->get_records("local_treestudyplan_coach", ["user_id" => $userid]);
$list = [];
foreach ($records as $r) {
try {
$studyplan = studyplan::find_by_id($r->studyplan_id);
if (has_capability(self::CAP_COACH,$studyplan->context(),$USER)) {
if (has_capability(self::CAP_COACH, $studyplan->context(), $USER)) {
$list[] = $studyplan->simple_model_coach();
}
} catch(\Exception $x) {}
@ -584,7 +584,7 @@ class studentstudyplanservice extends \external_api {
/**
* Parameter description for webservice function get_teaching_studyplan
*/
public static function get_teaching_studyplan_parameters() : \external_function_parameters {
public static function get_teaching_studyplan_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"studyplanid" => new \external_value(PARAM_INT, 'id of specific studyplan to provide', VALUE_DEFAULT),
] );
@ -593,7 +593,7 @@ class studentstudyplanservice extends \external_api {
/**
* Return value description for webservice function get_teaching_studyplan
*/
public static function get_teaching_studyplan_returns() : \external_description {
public static function get_teaching_studyplan_returns(): \external_description {
return studyplan::editor_structure();
}
@ -625,7 +625,7 @@ class studentstudyplanservice extends \external_api {
/**
* Parameter description for webservice function get_teaching_page
*/
public static function get_teaching_page_parameters() : \external_function_parameters {
public static function get_teaching_page_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"pageid" => new \external_value(PARAM_INT, 'id of specific studyplan page to provide', VALUE_DEFAULT),
] );
@ -634,7 +634,7 @@ class studentstudyplanservice extends \external_api {
/**
* Return value description for webservice function get_teaching_page
*/
public static function get_teaching_page_returns() : \external_description {
public static function get_teaching_page_returns(): \external_description {
return studyplanpage::editor_structure();
}
@ -667,7 +667,7 @@ class studentstudyplanservice extends \external_api {
/**
* Parameter description for webservice function get_teaching_page
*/
public static function line_enrol_self_parameters() : \external_function_parameters {
public static function line_enrol_self_parameters(): \external_function_parameters {
return new \external_function_parameters( [
"id" => new \external_value(PARAM_INT, 'id of specific studyline to enrol into'),
] );
@ -676,7 +676,7 @@ class studentstudyplanservice extends \external_api {
/**
* Return value description for webservice function get_teaching_page
*/
public static function line_enrol_self_returns() : \external_description {
public static function line_enrol_self_returns(): \external_description {
return studyline::enrol_info_structure();
}

View File

@ -65,7 +65,6 @@ class studyitem {
/** @var aggregator */
private $aggregator;
/**
* Return the context the studyplan is associated to
*/
@ -83,8 +82,8 @@ class studyitem {
/**
* Return the condition string for this item
*/
public function conditions() : string {
if($this->r->type == self::COURSE) {
public function conditions(): string {
if ($this->r->type == self::COURSE) {
return (!empty($this->r->conditions)) ? $this->r->conditions : "";
} else {
return (!empty($this->r->conditions)) ? $this->r->conditions : "ALL";
@ -118,42 +117,42 @@ class studyitem {
/**
* Return database identifier
*/
public function id() : int {
public function id(): int {
return $this->id;
}
/**
* Return period slot for this item
*/
public function slot() : int {
public function slot(): int {
return $this->r->slot;
}
/**
* Return layer (order within a line and slot) for this item
*/
public function layer() : int {
public function layer(): int {
return $this->r->layer;
}
/**
* Return study item type (see constants above)
*/
public function type() : string {
public function type(): string {
return $this->r->type;
}
/**
* Return period span
*/
public function span() : string {
public function span(): string {
return $this->r->span;
}
/**
* Return id of linked course (only relevant on COURSE types) or 0 if none
*/
public function courseid() : int {
public function courseid(): int {
return $this->r->course_id;
}
@ -161,16 +160,16 @@ class studyitem {
* Check if a studyitem with the given id exists
* @param int $id Id of studyplan
*/
public static function exists($id) : bool {
public static function exists($id): bool {
global $DB;
return is_numeric($id) && $DB->record_exists(self::TABLE, array('id' => $id));
return is_numeric($id) && $DB->record_exists(self::TABLE, ['id' => $id]);
}
/**
* Webservice structure for simple info
* @param int $value Webservice requirement constant
*/
public static function simple_structure($value = VALUE_REQUIRED) : \external_description {
public static function simple_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of study item'),
"type" => new \external_value(PARAM_TEXT, 'shortname of study item'),
@ -179,7 +178,7 @@ class studyitem {
"span" => new \external_value(PARAM_INT, 'how many periods the item spans'),
"course" => courseinfo::simple_structure(VALUE_OPTIONAL),
"badge" => badgeinfo::simple_structure(VALUE_OPTIONAL),
],"",$value);
], "", $value);
}
/**
@ -199,7 +198,7 @@ class studyitem {
if (isset($ci)) {
$model['course'] = $ci->simple_model();
}
if (is_numeric($this->r->badge_id) && $DB->record_exists('badge', array('id' => $this->r->badge_id))) {
if (is_numeric($this->r->badge_id) && $DB->record_exists('badge', ['id' => $this->r->badge_id])) {
$badge = new \core_badges\badge($this->r->badge_id);
$badgeinfo = new badgeinfo($badge);
$model['badge'] = $badgeinfo->simple_model();
@ -211,7 +210,7 @@ class studyitem {
* Webservice structure for editor info
* @param int $value Webservice requirement constant
*/
public static function editor_structure($value = VALUE_REQUIRED) : \external_description {
public static function editor_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of study item'),
"type" => new \external_value(PARAM_TEXT, 'shortname of study item'),
@ -226,7 +225,7 @@ class studyitem {
'in' => new \external_multiple_structure(studyitemconnection::structure()),
'out' => new \external_multiple_structure(studyitemconnection::structure()),
]),
],"",$value);
], "", $value);
}
/**
@ -257,7 +256,7 @@ class studyitem {
'connections' => [
"in" => [],
"out" => [],
]
],
];
if ($mode == "export") {
// Remove slot and layer.
@ -278,7 +277,7 @@ class studyitem {
}
// Add badge info if available.
if (is_numeric($this->r->badge_id) && $DB->record_exists('badge', array('id' => $this->r->badge_id))) {
if (is_numeric($this->r->badge_id) && $DB->record_exists('badge', ['id' => $this->r->badge_id])) {
$badge = new \core_badges\badge($this->r->badge_id);
$badgeinfo = new badgeinfo($badge);
if ($mode == "export") {
@ -329,11 +328,11 @@ class studyitem {
* 'competency_id', 'course_id', 'badge_id', 'continuation_id', 'span']
* @param bool $import Set tot true if calling on import
*/
public static function add($fields, $import = false) : self {
public static function add($fields, $import = false): self {
global $DB;
$addable = ['line_id', 'type', 'layer', 'conditions', 'slot',
'competency_id', 'course_id', 'badge_id', 'continuation_id', 'span'];
$info = [ 'layer' => 0, ];
$info = [ 'layer' => 0 ];
foreach ($addable as $f) {
if (array_key_exists($f, $fields)) {
$info[$f] = $fields[$f];
@ -352,11 +351,11 @@ class studyitem {
* Edit study item properties
* @param array $fields Changed roperties for study line ['conditions', 'course_id', 'continuation_id', 'span']
*/
public function edit($fields) : self {
public function edit($fields): self {
global $DB;
$editable = ['conditions', 'course_id', 'continuation_id', 'span'];
$info = ['id' => $this->id, ];
$info = ['id' => $this->id ];
foreach ($editable as $f) {
if (array_key_exists($f, $fields) && isset($fields[$f])) {
$info[$f] = $fields[$f];
@ -372,7 +371,7 @@ class studyitem {
/**
* Check if references course and badges are still available
*/
public function valid() : bool {
public function valid(): bool {
// Check if referenced courses and/or badges still exist.
if ($this->r->type == static::COURSE) {
return courseinfo::exists($this->r->course_id);
@ -418,7 +417,7 @@ class studyitem {
* Reposition study items in line, layer and/or slot
* @param mixed $resequence Array of item info [id, line_id, slot, layer]
*/
public static function reorder($resequence) : success {
public static function reorder($resequence): success {
global $DB;
foreach ($resequence as $sq) {
@ -442,7 +441,7 @@ class studyitem {
* @param studyline $line The studyline to search for
* @return studyitem[]
*/
public static function find_studyline_children(studyline $line) : array {
public static function find_studyline_children(studyline $line): array {
global $DB;
$list = [];
$ids = $DB->get_fieldset_select(self::TABLE, "id", "line_id = :line_id ORDER BY layer", ['line_id' => $line->id()]);
@ -460,13 +459,13 @@ class studyitem {
* @param int $type The type of items to include
* @return studyitem[]
*/
public static function search_studyline_children(studyline $line,$slot,$type) : array {
public static function search_studyline_children(studyline $line, $slot, $type): array {
global $DB;
$list = [];
$ids = $DB->get_fieldset_select(
self::TABLE, "id",
self::TABLE, "id",
"line_id = :line_id AND type = :type AND ( slot <= :slota AND ( slot + (span-1) >= :slotb ) ) ORDER BY layer",
['line_id' => $line->id(), 'slota' => $slot, 'slotb' => $slot,'type' => $type]
['line_id' => $line->id(), 'slota' => $slot, 'slotb' => $slot, 'type' => $type]
);
foreach ($ids as $id) {
$item = self::find_by_id($id, $line);
@ -475,13 +474,11 @@ class studyitem {
return $list;
}
/**
* Webservice structure for linking between plans
* @param int $value Webservice requirement constant
*/
private static function link_structure($value = VALUE_REQUIRED) : \external_description {
private static function link_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of study item'),
"type" => new \external_value(PARAM_TEXT, 'type of study item'),
@ -495,7 +492,7 @@ class studyitem {
* Webservice model for linking between plans
* @param int $userid ID for user to links completion from
*/
private function link_model($userid) : array {
private function link_model($userid): array {
global $DB;
$line = $DB->get_record(studyline::TABLE, ['id' => $this->r->line_id]);
$plan = $DB->get_record(studyplan::TABLE, ['id' => $line->studyplan_id]);
@ -513,7 +510,7 @@ class studyitem {
* Webservice structure for userinfo
* @param int $value Webservice requirement constant
*/
public static function user_structure($value = VALUE_REQUIRED) : \external_description {
public static function user_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of study item'),
"type" => new \external_value(PARAM_TEXT, 'type of study item'),
@ -591,7 +588,7 @@ class studyitem {
/**
* Get courseinfo for studyitem if it references a course
*/
public function getcourseinfo() : ?courseinfo {
public function getcourseinfo(): ?courseinfo {
if (empty($this->courseinfo) && courseinfo::exists($this->r->course_id)) {
$this->courseinfo = new courseinfo($this->r->course_id, $this);
}
@ -603,7 +600,7 @@ class studyitem {
* @param int $userid User id
* @return int completion:: constant
*/
public function completion($userid) : int {
public function completion($userid): int {
global $DB;
if ($this->valid()) {
@ -649,7 +646,7 @@ class studyitem {
break;
}
}
return ($notexpired) ? completion::COMPLETED : completion::INCOMPLETE;
return ($notexpired) ? completion : :COMPLETED : completion::INCOMPLETE;
} else {
return completion::COMPLETED;
}
@ -673,7 +670,7 @@ class studyitem {
* Duplicate this studyitem
* @param studyline $newline Study line to add duplicate to
*/
public function duplicate($newline) : self {
public function duplicate($newline): self {
global $DB;
// Clone the database fields.
$fields = clone $this->r;
@ -700,12 +697,11 @@ class studyitem {
return $this->generate_model("export");
}
/**
* Import studyitems from model
* @param array $model Decoded array
*/
public static function import_item($model) : self {
public static function import_item($model): self {
unset($model["course_id"]);
unset($model["competency_id"]);
unset($model["badge_id"]);

View File

@ -56,7 +56,7 @@ class studyitemconnection {
* Webservice structure for basic info
* @param int $value Webservice requirement constant
*/
public static function structure($value = VALUE_REQUIRED) : \external_description {
public static function structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
'id' => new \external_value(PARAM_INT, 'id of connection'),
'from_id' => new \external_value(PARAM_INT, 'id of start item'),
@ -72,25 +72,24 @@ class studyitemconnection {
return ['id' => $this->r->id, 'from_id' => $this->r->from_id, 'to_id' => $this->r->to_id];
}
/**
* Get originating studyitem for this connection
*/
public function from_item() : studyitem {
public function from_item(): studyitem {
return studyitem::find_by_id($this->r->from_id);
}
/**
* Get target studyitem for this connection
*/
public function to_item() : studyitem {
public function to_item(): studyitem {
return studyitem::find_by_id($this->r->to_id);
}
/**
* Get originating studyitem id for this connection
*/
public function from_id() : int {
public function from_id(): int {
return $this->r->from_id;
}
@ -106,7 +105,7 @@ class studyitemconnection {
* @param int $itemid Id of the studyitem
* @return studyitemconnection[]
*/
public static function find_outgoing($itemid) : array {
public static function find_outgoing($itemid): array {
global $DB;
$list = [];
$connout = $DB->get_records(self::TABLE, ['from_id' => $itemid]);

View File

@ -39,7 +39,7 @@ class studyline {
* @var int
*/
public const ENROLLABLE_SELF = 1;
/**
* Studyline can be enrolled into by specific role(s)
* @var int
@ -110,7 +110,6 @@ class studyline {
/** @var studyplan*/
private $studyplan;
/**
* Return the context the studyplan is associated to
*/
@ -121,14 +120,14 @@ class studyline {
/**
* Return the studyplan for this line
*/
public function studyplan() : studyplan {
public function studyplan(): studyplan {
return $this->studyplan;
}
/**
* Return the studyplan page for this line
*/
public function page() : studyplanpage {
public function page(): studyplanpage {
return $this->page;
}
@ -158,35 +157,35 @@ class studyline {
/**
* Return database identifier
*/
public function id() : int {
public function id(): int {
return $this->id;
}
/**
* Return full name
*/
public function name() : string {
public function name(): string {
return $this->r->name;
}
/**
* Return short name
*/
public function shortname() : string {
public function shortname(): string {
return $this->r->shortname;
}
/**
* Whether this line is enrollable by the student
*/
public function self_enrollable() : bool {
public function self_enrollable(): bool {
return ($this->r->enrollable == self::ENROLLABLE_SELF || $this->r->enrollable == self::ENROLLABLE_SELF_ROLE);
}
/**
* Whether this line is enrollable by a role
*/
public function role_enrollable() : bool {
public function role_enrollable(): bool {
return ($this->r->enrollable == self::ENROLLABLE_ROLE || $this->r->enrollable == self::ENROLLABLE_SELF_ROLE);
}
@ -194,11 +193,11 @@ class studyline {
* Whether the current user can enrol a specific user in this line
* @param int|null $user ID or user object for user or null
*/
public function can_enrol($userid=null) : bool {
public function can_enrol($userid=null): bool {
global $USER;
$plan = $this->studyplan();
if (!empty($userid)){
if (!empty($userid)) {
if ( $plan->has_linked_user(intval($userid))) {
if ( $this->self_enrollable() && $userid == $USER->id ) {
return true;
@ -206,7 +205,7 @@ class studyline {
if ( $this->role_enrollable()) {
$context = $plan->context();
foreach ( $this->enrol_roleids() as $rid) {
if (\user_has_role_assignment($USER->id,$rid,$context->id)){
if (\user_has_role_assignment($USER->id, $rid, $context->id)) {
return true;
}
}
@ -216,73 +215,73 @@ class studyline {
if ( $this->role_enrollable()) {
$context = $plan->context();
foreach ( $this->enrol_roleids() as $rid) {
if (\user_has_role_assignment($USER->id,$rid,$context->id)){
if (\user_has_role_assignment($USER->id, $rid, $context->id)) {
return true;
}
}
}
}
return false;
}
/**
* Whether this line is enrollable at all
*/
public function enrollable() : bool {
public function enrollable(): bool {
return $this->r->enrollable != self::ENROLLABLE_NONE;
}
/**
* List the available roles that can enrol the student
*/
public function enrol_roles() : array {
public function enrol_roles(): array {
global $DB;
$list = [];
$roles = explode(",",$this->r->enrolrole);
$roles = explode(", ", $this->r->enrolrole);
foreach($roles as $r) {
$roleid = intval($r);
if ($roleid > 0) {
try {
$role = $DB->get_record('role',["id" => $roleid],"*", MUST_EXIST);
$role = $DB->get_record('role', ["id" => $roleid], "*", MUST_EXIST);
$list[] = $role;
} catch(\Exception $x) {}
}
}
return $list;
}
/**
* List the available roles that can enrol the student
*/
public function enrol_roleids() : array {
public function enrol_roleids(): array {
global $DB;
$list = [];
$roles = explode(",",$this->r->enrolrole);
$roles = explode(", ", $this->r->enrolrole);
foreach($roles as $r) {
$roleid = intval($r);
if ($roleid > 0) {
$list[] = $roleid;
}
}
return $list;
}
/**
* List the available roles that can enrol the student in a proper model
*/
public function enrol_roles_model() : array {
public function enrol_roles_model(): array {
$list = [];
foreach($this->enrol_roles() as $role) {
$name = role_get_name($role,$this->context()); // Get localized role name.
$name = role_get_name($role, $this->context()); // Get localized role name.
$list[] = [
"id" => $role->id,
"name" => $name,
];
}
return $list;
}
@ -290,7 +289,7 @@ class studyline {
* Webservice structure for editor info
* @param int $value Webservice requirement constant
*/
public static function editor_structure($value = VALUE_REQUIRED) : \external_description {
public static function editor_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of studyline'),
"name" => new \external_value(PARAM_TEXT, 'shortname of studyline'),
@ -306,7 +305,7 @@ class studyline {
studyitem::editor_structure(), 'filter items'),
])
)
],"Study line editor structure",$value);
], "Study line editor structure", $value);
}
/**
@ -321,19 +320,19 @@ class studyline {
"id" => new \external_value(PARAM_INT, 'id of role'),
"name" => new \external_value(PARAM_TEXT, 'name of role'),
])),
"can_enrol" => new \external_value(PARAM_BOOL, 'enrollable by current user',VALUE_OPTIONAL),
"enrolled" => new \external_value(PARAM_BOOL, 'student is enrolled',VALUE_OPTIONAL),
"enrolled_time" => new \external_value(PARAM_INT, 'moment of enrollment',VALUE_OPTIONAL),
"enrolled_by" => new \external_value(PARAM_TEXT, 'Name of enrolling user',VALUE_OPTIONAL),
"selfview" => new \external_value(PARAM_BOOL, 'viewing user is the student',VALUE_OPTIONAL),
],"Enrollment info",$value);
"can_enrol" => new \external_value(PARAM_BOOL, 'enrollable by current user', VALUE_OPTIONAL),
"enrolled" => new \external_value(PARAM_BOOL, 'student is enrolled', VALUE_OPTIONAL),
"enrolled_time" => new \external_value(PARAM_INT, 'moment of enrollment', VALUE_OPTIONAL),
"enrolled_by" => new \external_value(PARAM_TEXT, 'Name of enrolling user', VALUE_OPTIONAL),
"selfview" => new \external_value(PARAM_BOOL, 'viewing user is the student', VALUE_OPTIONAL),
], "Enrollment info", $value);
}
/**
* Webservice structure for simple info
* @param int $value Webservice requirement constant
*/
public static function simple_structure($value = VALUE_REQUIRED) : \external_description {
public static function simple_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of studyline'),
"name" => new \external_value(PARAM_TEXT, 'shortname of studyline'),
@ -341,14 +340,14 @@ class studyline {
"color" => new \external_value(PARAM_TEXT, 'description of studyline'),
"sequence" => new \external_value(PARAM_INT, 'order of studyline'),
"enrol" => self::enrol_info_structure(),
],"Study line simple structure",$value);
], "Study line simple structure", $value);
}
/**
* Webservice model for simple info
* @return array Webservice data model
*/
public function simple_model() : array {
public function simple_model(): array {
return [
'id' => $this->r->id,
'name' => $this->r->name,
@ -363,7 +362,7 @@ class studyline {
* Webservice model for editor info
* @return array Webservice data model
*/
public function editor_model() : array {
public function editor_model(): array {
return $this->generate_model("editor");
}
@ -371,7 +370,7 @@ class studyline {
* Create a model for the given type of operation
* @param string $mode One of [ 'editor', 'export']
*/
protected function generate_model($mode) : array {
protected function generate_model($mode): array {
// Mode parameter is used to geep this function for both editor model and export model.
// (Export model results in fewer parameters on children, but is otherwise basically the same as this function).
global $DB;
@ -436,12 +435,11 @@ class studyline {
return $model;
}
/**
* Add a new study line
* @param array $fields Properties for study line ['page_id', 'name', 'shortname', 'color']
*/
public static function add($fields) : self {
public static function add($fields): self {
global $DB;
if (!isset($fields['page_id'])) {
@ -450,7 +448,7 @@ class studyline {
$pageid = $fields['page_id'];
$sqmax = $DB->get_field_select(self::TABLE, "MAX(sequence)", "page_id = :page_id", ['page_id' => $pageid]);
$addable = ['page_id', 'name', 'shortname', 'color','enrollable','enrolrole'];
$addable = ['page_id', 'name', 'shortname', 'color', 'enrollable', 'enrolrole'];
$info = ['sequence' => $sqmax + 1];
foreach ($addable as $f) {
if (array_key_exists($f, $fields)) {
@ -465,10 +463,10 @@ class studyline {
* Edit study line properties
* @param array $fields Changed roperties for study line ['name', 'shortname', 'color']
*/
public function edit($fields) : self {
public function edit($fields): self {
global $DB;
$editable = ['name', 'shortname', 'color','enrollable','enrolrole'];
$info = ['id' => $this->id, ];
$editable = ['name', 'shortname', 'color', 'enrollable', 'enrolrole'];
$info = ['id' => $this->id ];
foreach ($editable as $f) {
if (array_key_exists($f, $fields)) {
$info[$f] = $fields[$f];
@ -484,7 +482,7 @@ class studyline {
* Delete studyline
* @param bool $force Force deletion even if study line contains items
*/
public function delete($force = false) : success {
public function delete($force = false): success {
global $DB;
if ($force) {
@ -506,7 +504,7 @@ class studyline {
* Reorder study lines
* @param int[] $resequence New order of study lines by id
*/
public static function reorder($resequence) : success {
public static function reorder($resequence): success {
global $DB;
foreach ($resequence as $sq) {
@ -524,7 +522,7 @@ class studyline {
* @param studyplanpage $page The studyplanpage to search for
* @return studyline[]
*/
public static function find_page_children(studyplanpage $page) : array {
public static function find_page_children(studyplanpage $page): array {
global $DB;
$list = [];
$ids = $DB->get_fieldset_select(self::TABLE, "id", "page_id = :page_id ORDER BY sequence",
@ -539,7 +537,7 @@ class studyline {
* Webservice structure for userinfo
* @param int $value Webservice requirement constant
*/
public static function user_structure($value = VALUE_REQUIRED) : \external_description {
public static function user_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of studyline'),
"name" => new \external_value(PARAM_TEXT, 'shortname of studyline'),
@ -564,7 +562,7 @@ class studyline {
* @return array Webservice data model
*/
public function enrol_info_model($userid=null) {
global $DB,$USER;
global $DB, $USER;
$model = [
'enrolroles' => $this->enrol_roleids(),
@ -573,34 +571,34 @@ class studyline {
];
if (!empty($userid)) {
$r = $DB->get_record('local_treestudyplan_lineuser',[
$r = $DB->get_record('local_treestudyplan_lineuser', [
'line_id' => $this->id(),
'user_id' => $userid,
]);
if (empty($r)) {
$enrolled = false;
$enrolled_time = 0;
$enrolled_by = "";
$enrolledtime = 0;
$enrolledby = "";
} else {
$enrolled = boolval($r->enrolled);
$enrolled_time = $r->timeenrolled;
$by = $DB->get_record('user',["id" => $r->enrolledby]);
$enrolledtime = $r->timeenrolled;
$by = $DB->get_record('user', ["id" => $r->enrolledby]);
if (empty($by)) {
$enrolled_by = \get_string("unknownuser","core");
$enrolledby = \get_string("unknownuser", "core");
} else {
$enrolled_by = "{$by->firstname} {$by->lastname}";
$enrolledby = "{$by->firstname} {$by->lastname}";
}
}
$usermodel = [
'can_enrol' => $this->can_enrol($userid),
"enrolled" => $enrolled,
"enrolled_time" => $enrolled_time,
"enrolled_by" => $enrolled_by,
"enrolled_time" => $enrolledtime,
"enrolled_by" => $enrolledby,
"selfview" => boolval($userid == $USER->id),
];
$model = array_merge($model,$usermodel);
$model = array_merge($model, $usermodel);
} else {
$model["can_enrol"] = $this->can_enrol();
}
@ -613,7 +611,7 @@ class studyline {
*/
public function get_enrolled_userids() {
$userids = $this->studyplan()->find_linked_userids();
if($this->enrollable()) {
if ($this->enrollable()) {
$list = [];
foreach($userids as $uid) {
if ( $this->isenrolled($uid)) {
@ -626,7 +624,6 @@ class studyline {
}
}
/**
* Check if student is enrolled in the line.
* @param int $userid ID of user to check specific info for
@ -637,7 +634,7 @@ class studyline {
if ($this->r->enrollable == self::ENROLLABLE_NONE) {
return true; // If student cannot enrol, the student always is enrolled
} else {
$r = $DB->get_record('local_treestudyplan_lineuser',[
$r = $DB->get_record('local_treestudyplan_lineuser', [
'line_id' => $this->id(),
'user_id' => $userid,
]);
@ -649,13 +646,13 @@ class studyline {
}
}
}
/**
* List the course id is linked in this studyplan
* Used for cohort enrolment cascading
* @return int[]
*/
public function get_linked_course_ids() : array {
public function get_linked_course_ids(): array {
global $DB;
$sql = "SELECT i.course_id
@ -674,7 +671,7 @@ class studyline {
* @param int $userid of user to enrol
*/
public function enrol($userid) {
global $DB,$USER;
global $DB, $USER;
if ($this->r->enrollable > self::ENROLLABLE_NONE) {
$r = $DB->get_record("local_treestudyplan_lineuser",
@ -686,7 +683,7 @@ class studyline {
$r->enrolled = 1;
$r->timeenrolled = time();
$r->enrolledby = $USER->id;
$DB->update_record("local_treestudyplan_lineuser",$r);
$DB->update_record("local_treestudyplan_lineuser", $r);
}
// Otherwise, ignore the request.
@ -698,7 +695,7 @@ class studyline {
$r->user_id = $userid;
$r->timeenrolled = time();
$r->enrolledby = $USER->id;
$DB->insert_record("local_treestudyplan_lineuser",$r);
$DB->insert_record("local_treestudyplan_lineuser", $r);
}
$this->studyplan()->mark_csync_changed();
@ -713,8 +710,8 @@ class studyline {
* @param int $userid of user to unenrol
*/
public function unenrol($userid) {
global $DB,$USER;
global $DB, $USER;
if ($this->r->enrollable > self::ENROLLABLE_NONE) {
// Check if an enrollment line exist.
$r = $DB->get_record("local_treestudyplan_lineuser",
@ -726,18 +723,17 @@ class studyline {
$r->enrolled = 0;
$r->timeenrolled = time(); // Regi
$r->enrolledby = $USER->id;
$DB->update_record("local_treestudyplan_lineuser",$r);
$DB->update_record("local_treestudyplan_lineuser", $r);
$this->studyplan()->mark_csync_changed();
}
// Otherwise, ignore the request.
}
}
// Otherwise, no action is needed.
}
}
/**
* Webservice model for user info
* @param int $userid ID of user to check specific info for
@ -803,7 +799,7 @@ class studyline {
* @param array $translation Mapping array of old item ids to new item ids for connection matching
* @param bool $bare Set to true to skip copying contents
*/
public function duplicate($newpage, &$translation,$bare = false) : self {
public function duplicate($newpage, &$translation, $bare = false): self {
global $DB;
// Clone the database fields.

View File

@ -38,7 +38,6 @@ class studyplan {
/** @var string */
const TABLE_COACH = "local_treestudyplan_coach";
/**
* Cache retrieved studyitems in this session
* @var array */
@ -73,7 +72,7 @@ class studyplan {
/**
* Return configured aggregator for this studyplan
*/
public function aggregator() : aggregator {
public function aggregator(): aggregator {
return $this->aggregator;
}
@ -96,7 +95,7 @@ class studyplan {
private function __construct($id) {
global $DB;
$this->id = $id;
$this->r = $DB->get_record(self::TABLE, ['id' => $id],"*",MUST_EXIST);
$this->r = $DB->get_record(self::TABLE, ['id' => $id], "*", MUST_EXIST);
$this->aggregator = aggregator::create_or_default($this->r->aggregation, $this->r->aggregation_config);
}
@ -155,14 +154,13 @@ class studyplan {
return $date;
}
private function icon() {
global $CFG;
$fs = \get_file_storage();
// Returns an array of `stored_file` instances.
$files = $fs->get_area_files(\context_system::instance()->id, 'local_treestudyplan', 'icon', $this->id);
if (count($files) > 0 ){
if (count($files) > 0 ) {
$file = array_shift($files);
if ($file->get_filename() == ".") {
// Get next file if the first is the directory itself.
@ -188,12 +186,12 @@ class studyplan {
$url = \moodle_url::make_pluginfile_url(\context_system::instance()->id, 'local_treestudyplan', 'defaulticon', 0, "/",
$defaulticon);
}
}
return $url->out();
}
/**
/**
* Return description with all file references resolved
*/
public function description() {
@ -202,7 +200,7 @@ class studyplan {
$this->r->description,
// The pluginfile URL which will serve the request.
'pluginfile.php',
// The combination of contextid / component / filearea / itemid
// form the virtual bucket that file are stored in.
\context_system::instance()->id, // System instance is always used for this
@ -217,7 +215,7 @@ class studyplan {
* @param bool $refresh Set to true to force a refresh of the pages
* @return studyplanpage[]
*/
public function pages($refresh=false) : array {
public function pages($refresh=false): array {
if ( ((bool)$refresh) || empty($this->pagecache)) {
$this->pagecache = studyplanpage::find_studyplan_children($this);
}
@ -252,24 +250,24 @@ class studyplan {
* Webservice structure for basic info
* @param int $value Webservice requirement constant
*/
public static function simple_structure($value = VALUE_REQUIRED) : \external_description {
public static function simple_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of studyplan'),
"userid" => new \external_value(PARAM_INT, 'id of user the plan is shown for',VALUE_OPTIONAL),
"userid" => new \external_value(PARAM_INT, 'id of user the plan is shown for', VALUE_OPTIONAL),
"name" => new \external_value(PARAM_TEXT, 'name of studyplan'),
"shortname" => new \external_value(PARAM_TEXT, 'shortname of studyplan'),
"idnumber" => new \external_value(PARAM_TEXT, 'idnumber of curriculum'),
"context_id" => new \external_value(PARAM_INT, 'context_id of studyplan'),
"description" => new \external_value(PARAM_RAW, 'description of studyplan'),
"descriptionformat" => new \external_value(PARAM_INT, 'description format'),
"icon" => new \external_value(PARAM_RAW,'icon for this plan'),
"icon" => new \external_value(PARAM_RAW, 'icon for this plan'),
"aggregation" => new \external_value(PARAM_TEXT, 'selected aggregator'),
"aggregation_config" => new \external_value(PARAM_TEXT, 'config string for aggregator'),
"aggregation_info" => aggregator::basic_structure(),
"pages" => new \external_multiple_structure(studyplanpage::simple_structure(), 'pages'),
"progress" => new \external_value(PARAM_FLOAT,"fraction of completed modules",VALUE_OPTIONAL),
"amteaching" => new \external_value(PARAM_BOOL,"Current user is teaching one or more courses in this studyplan",VALUE_OPTIONAL),
"suspended" => new \external_value(PARAM_BOOL, 'if studyplan is suspended',VALUE_OPTIONAL),
"progress" => new \external_value(PARAM_FLOAT, "fraction of completed modules", VALUE_OPTIONAL),
"amteaching" => new \external_value(PARAM_BOOL, "Current user is teaching one or more courses in this studyplan", VALUE_OPTIONAL),
"suspended" => new \external_value(PARAM_BOOL, 'if studyplan is suspended', VALUE_OPTIONAL),
], 'Basic studyplan info', $value);
}
@ -299,10 +297,10 @@ class studyplan {
'pages' => $pages,
'suspended' => boolval($this->r->suspended),
];
if(isset($userid)) {
if (isset($userid)) {
$model["userid"] = $userid;
$model["progress"] = $this->scanuserprogress($userid);
$model['amteaching'] = teachingfinder::is_teaching_studyplan($this,$userid);
$model['amteaching'] = teachingfinder::is_teaching_studyplan($this, $userid);
}
return $model;
}
@ -317,7 +315,7 @@ class studyplan {
$sum = 0;
foreach ( $users as $uid ) {
$sum += $this->scanuserprogress($uid);
}
}
$model["progress"] = $sum / count($users);
@ -328,7 +326,7 @@ class studyplan {
* Webservice structure for editor info
* @param int $value Webservice requirement constant
*/
public static function editor_structure($value = VALUE_REQUIRED) : \external_description {
public static function editor_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of studyplan'),
"name" => new \external_value(PARAM_TEXT, 'name of studyplan'),
@ -336,7 +334,7 @@ class studyplan {
"idnumber" => new \external_value(PARAM_TEXT, 'idnumber of curriculum'),
"description" => new \external_value(PARAM_RAW, 'description of studyplan'),
"descriptionformat" => new \external_value(PARAM_INT, 'description format'),
"icon" => new \external_value(PARAM_RAW,'icon for this plan'),
"icon" => new \external_value(PARAM_RAW, 'icon for this plan'),
"context_id" => new \external_value(PARAM_INT, 'context_id of studyplan'),
"aggregation" => new \external_value(PARAM_TEXT, 'selected aggregator'),
"aggregation_config" => new \external_value(PARAM_TEXT, 'config string for aggregator'),
@ -350,7 +348,7 @@ class studyplan {
])),
], "Scale forcing on stuff", VALUE_OPTIONAL),
], "Advanced features available", VALUE_OPTIONAL),
"suspended" => new \external_value(PARAM_BOOL, 'if studyplan is suspended',VALUE_OPTIONAL),
"suspended" => new \external_value(PARAM_BOOL, 'if studyplan is suspended', VALUE_OPTIONAL),
], 'Studyplan full structure', $value);
}
@ -390,7 +388,7 @@ class studyplan {
// Get a list of available scales.
$scales = array_map( function($scale) {
return [ "id" => $scale->id, "name" => $scale->name, ];
return [ "id" => $scale->id, "name" => $scale->name ];
}, \grade_scale::fetch_all(['courseid' => 0]) );
$model['advanced']['force_scales'] = [
@ -407,7 +405,7 @@ class studyplan {
* 'aggregation_config', 'periods', 'startdate', 'enddate'];
* @param bool $bare If true, do not create a first page with copy of studyplan names
*/
public static function add($fields, $bare = false) : self {
public static function add($fields, $bare = false): self {
global $CFG, $DB;
$addable = ['name', 'shortname', 'description', 'descriptionformat', 'idnumber', 'context_id', 'aggregation', 'aggregation_config'];
@ -420,7 +418,7 @@ class studyplan {
$id = $DB->insert_record(self::TABLE, $info);
$plan = self::find_by_id($id); // Make sure the new studyplan is immediately cached.
// Add a single page and initialize it with placeholder data
// Add a single page and initialize it with placeholder data
// This makes it easier to create a new study plan
// On import, adding an empty page messes things up , so we have an option to skip this....
if (!$bare) {
@ -437,7 +435,7 @@ class studyplan {
}
}
$page = studyplanpage::add($pageinfo,$bare);
$page = studyplanpage::add($pageinfo, $bare);
$plan->page_cache = [$page];
}
@ -449,7 +447,7 @@ class studyplan {
* @param array $fields Changed properties for study line ['name', 'shortname', 'description', 'idnumber',
* 'context_id', 'aggregation', 'aggregation_config', 'suspended']
*/
public function edit($fields) : self {
public function edit($fields): self {
global $DB;
$editable = [
'name',
@ -463,7 +461,7 @@ class studyplan {
'suspended',
'template'
];
$info = ['id' => $this->id, ];
$info = ['id' => $this->id ];
foreach ($editable as $f) {
if (array_key_exists($f, $fields)) {
$info[$f] = $fields[$f];
@ -486,7 +484,7 @@ class studyplan {
* Delete studyline
* @param bool $force Force deletion even if study line contains items
*/
public function delete($force = false) : success {
public function delete($force = false): success {
global $DB;
if ($force) {
@ -503,7 +501,7 @@ class studyplan {
$DB->delete_records("local_treestudyplan_coach", ["studyplan_id" => $this->id]);
$DB->delete_records("local_treestudyplan_cohort", ["studyplan_id" => $this->id]);
$DB->delete_records("local_treestudyplan_user", ["studyplan_id" => $this->id]);
//
//
$DB->delete_records('local_treestudyplan', ['id' => $this->id]);
return success::success();
}
@ -514,7 +512,7 @@ class studyplan {
* @param int $contextid Optional contextid to search in. ANY context used if left empty
* @return studyplan[]
*/
public static function find_all($contextid = -1) : array {
public static function find_all($contextid = -1): array {
global $DB, $USER;
$list = [];
@ -541,7 +539,7 @@ class studyplan {
* @param int $contextid Optional contextid to search in. ANY context used if left empty
* @return studyplan[]
*/
public static function find_template($contextid = -1) : array {
public static function find_template($contextid = -1): array {
global $DB, $USER;
$list = [];
@ -569,7 +567,7 @@ class studyplan {
* @param int $contextid Optional contextid to search in. ANY context used if left empty
* @return int
*/
public static function count_template($contextid = -1) : int {
public static function count_template($contextid = -1): int {
global $DB, $USER;
$list = [];
@ -604,7 +602,7 @@ class studyplan {
} else if ($contextid > 1) {
$where .= " AND context_id = :contextid";
}
$ids = $DB->get_fieldset_select(self::TABLE, "id", $where, ["shortname" => $shortname, "contextid" => $contextid]);
foreach ($ids as $id) {
$list[] = self::find_by_id($id);
@ -665,7 +663,7 @@ class studyplan {
* @param int $userid Id of the user to search for
* @return studyplan[]
*/
public static function find_for_user($userid) : array {
public static function find_for_user($userid): array {
global $DB;
$sql = "SELECT s.id FROM {local_treestudyplan} s
@ -699,7 +697,7 @@ class studyplan {
* Check if a given user has associated studyplans
* @param int $userid Id of the user to search for
*/
public static function exist_for_user($userid) : bool {
public static function exist_for_user($userid): bool {
global $DB;
$count = 0;
$sql = "SELECT COUNT(s.id) FROM {local_treestudyplan} s
@ -722,7 +720,7 @@ class studyplan {
* Retrieve the users linked to this studyplan.
* @return stdClass[] User objects
*/
public function find_linked_users() : array {
public function find_linked_users(): array {
global $DB;
$users = [];
@ -793,11 +791,11 @@ class studyplan {
public function is_coach($user=null) {
global $DB, $USER
;
if ( ! (premium::enabled() && \get_config("local_treestudyplan","enablecoach")) ) {
if ( ! (premium::enabled() && \get_config("local_treestudyplan", "enablecoach")) ) {
// If coach role is not available, return false immediately.
return false;
}
if($user == null) {
if ($user == null) {
$user = $USER;
$userid = $USER->id;
} else if (is_numeric($user)) {
@ -805,9 +803,9 @@ class studyplan {
} else {
$userid = $user->id;
}
$r = $DB->get_record(self::TABLE_COACH,["studyplan_id" => $this->id, "user_id"=> $userid]);
$r = $DB->get_record(self::TABLE_COACH, ["studyplan_id" => $this->id, "user_id"=> $userid]);
if ($r && has_capability(associationservice::CAP_COACH,$this->context(),$userid)) {
if ($r && has_capability(associationservice::CAP_COACH, $this->context(), $userid)) {
return true;
} else {
return false;
@ -818,7 +816,7 @@ class studyplan {
* Webservice structure for userinfo
* @param int $value Webservice requirement constant
*/
public static function user_structure($value = VALUE_REQUIRED) : \external_description {
public static function user_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of studyplan'),
"userid" => new \external_value(PARAM_INT, 'id of user the plan is shown for'),
@ -826,8 +824,8 @@ class studyplan {
"shortname" => new \external_value(PARAM_TEXT, 'shortname of studyplan'),
"description" => new \external_value(PARAM_RAW, 'description of studyplan'),
"descriptionformat" => new \external_value(PARAM_INT, 'description format'),
"icon" => new \external_value(PARAM_RAW,'icon for this plan'),
"progress" => new \external_value(PARAM_FLOAT,"fraction of completed modules"),
"icon" => new \external_value(PARAM_RAW, 'icon for this plan'),
"progress" => new \external_value(PARAM_FLOAT, "fraction of completed modules"),
"idnumber" => new \external_value(PARAM_TEXT, 'idnumber of curriculum'),
"pages" => new \external_multiple_structure(studyplanpage::user_structure()),
"aggregation_info" => aggregator::basic_structure(),
@ -893,9 +891,9 @@ class studyplan {
* @param string $shortname New shortname of studyplan
* @return array Simple webservices model of plan
*/
public static function duplicate_plan($planid, $name, $shortname) : array {
public static function duplicate_plan($planid, $name, $shortname): array {
$ori = self::find_by_id($planid);
$new = $ori->duplicate($name, $shortname,$ori->context()->id);
$new = $ori->duplicate($name, $shortname, $ori->context()->id);
return $new->simple_model();
}
@ -904,21 +902,21 @@ class studyplan {
* @param string $name New fullname of studyplan
* @param string $shortname New shortname of studyplan
*/
public function duplicate($name, $shortname, $contextid, $idnumber=null, $newstartdate = null) : self {
public function duplicate($name, $shortname, $contextid, $idnumber=null, $newstartdate = null): self {
// First duplicate the studyplan structure.
$newplan = self::add([
'name' => $name,
'shortname' => $shortname,
'idnumber' => ($idnumber?$idnumber:$this->r->idnumber),
'idnumber' => ($idnumber ? $idnumber : $this->r->idnumber),
'context_id' => $contextid,
'description' => $this->r->description,
'descriptionformat' => $this->r->descriptionformat,
'aggregation' => $this->r->aggregation,
'aggregation_config' => $this->r->aggregation_config
],true);
], true);
// Copy any files related to this studyplan.
$areas = ["icon","studyplan"];
$areas = ["icon", "studyplan"];
$fs = \get_file_storage();
foreach ($areas as $area) {
$files = $fs->get_area_files(
@ -948,9 +946,9 @@ class studyplan {
}
// Next, copy the studylines.
$timeless = \get_config("local_treestudyplan","timelessperiods");
$timeless = \get_config("local_treestudyplan", "timelessperiods");
if (!$timeless && $newstartdate) {
$newstart = new \DateTime(date("Y-m-d",$newstartdate));
$newstart = new \DateTime(date("Y-m-d", $newstartdate));
$oldstart = $this->startdate();
$timeoffset = $oldstart->diff($newstart);
} else {
@ -958,7 +956,7 @@ class studyplan {
}
foreach ($this->pages() as $page) {
$newchild = $page->duplicate($newplan,$timeoffset);
$newchild = $page->duplicate($newplan, $timeoffset);
}
return $newplan;
@ -967,7 +965,7 @@ class studyplan {
/**
* Description of export structure for webservices
*/
public static function export_structure() : \external_description {
public static function export_structure(): \external_description {
return new \external_single_structure([
"format" => new \external_value(PARAM_TEXT, 'format of studyplan export'),
"content" => new \external_value(PARAM_RAW, 'exported studyplan content'),
@ -1010,7 +1008,6 @@ class studyplan {
return $model;
}
/**
* Export files from file storage
* @param string $area Name of the file area to export
@ -1041,9 +1038,9 @@ class studyplan {
* Import previously exported files into the file storage
* @param string $area Name of the file area to import
* @param mixed $importfiles List of files to import from string in the format exported in export_model()
*
*
*/
public function import_files($importfiles,$area) {
public function import_files($importfiles, $area) {
$fs = get_file_storage();
foreach($importfiles as $file) {
if ($file['name'] != ".") {
@ -1055,7 +1052,7 @@ class studyplan {
'filepath' => $file["path"], // Path of the file.
'filename' => $file["name"], // Name of the file..
];
$fs->create_file_from_string($fileinfo, convert_uudecode($file["content"]));
}
}
@ -1099,11 +1096,11 @@ class studyplan {
// Import the files
if (isset( $planmodel['files']) && is_array( $planmodel['files'])) {
$plan->import_files( $planmodel['files'],"studyplan");
$plan->import_files( $planmodel['files'], "studyplan");
}
// Import the icon
if (isset( $planmodel['iconfiles']) && is_array( $planmodel['iconfiles'])) {
$plan->import_files( $planmodel['iconfiles'],"icon");
$plan->import_files( $planmodel['iconfiles'], "icon");
}
// Now import each page.
@ -1138,12 +1135,11 @@ class studyplan {
}
}
/**
* Import pages from decoded array model
* @param array $model Decoded array
*/
protected function import_pages_model($model) : bool {
protected function import_pages_model($model): bool {
$this->pages(); // Make sure the page cache is initialized, since we will be adding to it.
foreach ($model as $p) {
$p["studyplan_id"] = $this->id();
@ -1152,7 +1148,7 @@ class studyplan {
$page->import_periods_model($p["perioddesc"]);
$page->import_studylines_model($p["studylines"]);
if ($p['files']) {
$page->import_files($p["files"],'studyplanpage');
$page->import_files($p["files"], 'studyplanpage');
}
}
return true;
@ -1181,7 +1177,7 @@ class studyplan {
/**
* Check if the studyplan as changed regarding courses and associated cohorts
*/
public function has_csync_changed() : bool {
public function has_csync_changed(): bool {
return ($this->r->csync_flag > 0) ? true : false;
}
@ -1189,7 +1185,7 @@ class studyplan {
* See if the specified course id is linked in this studyplan
* @param int $courseid Id of course to check
*/
public function course_linked($courseid) : bool {
public function course_linked($courseid): bool {
global $DB;
$sql = "SELECT COUNT(i.id)
@ -1203,13 +1199,12 @@ class studyplan {
return ($count > 0) ? true : false;
}
/**
* Get all study lines linked to this plan (quickly)
* Used for cohort enrolment cascading
* @return studyline[]
*/
public function get_all_studylines() : array {
public function get_all_studylines(): array {
global $DB;
$sql = "SELECT l.id
@ -1242,7 +1237,7 @@ class studyplan {
* List the user id's explicitly associated with this studyplan
* @return int[]
*/
public function get_linked_user_ids() : array {
public function get_linked_user_ids(): array {
global $CFG, $DB;
$sql = "SELECT DISTINCT j.user_id FROM {local_treestudyplan_user} j
@ -1254,7 +1249,7 @@ class studyplan {
* See if the specified badge is linked in this studyplan
* @param int $badgeid Badge id
*/
public function badge_linked($badgeid) : bool {
public function badge_linked($badgeid): bool {
global $DB;
$sql = "SELECT COUNT(i.id)

View File

@ -53,7 +53,7 @@ class studyplanpage {
* Get aggregator for the studyplan (page)
* @return aggregator
*/
public function aggregator() : aggregator {
public function aggregator(): aggregator {
return $this->studyplan->aggregator();
}
@ -90,7 +90,7 @@ class studyplanpage {
/**
* Find studyplan for this page
*/
public function studyplan() : studyplan {
public function studyplan(): studyplan {
return $this->studyplan;
}
@ -143,9 +143,9 @@ class studyplanpage {
}
/**
/**
* Return description with all file references resolved
* @return string
* @return string
*/
public function description() {
$text = \file_rewrite_pluginfile_urls(
@ -153,7 +153,7 @@ class studyplanpage {
$this->r->description,
// The pluginfile URL which will serve the request.
'pluginfile.php',
// The combination of contextid / component / filearea / itemid
// form the virtual bucket that file are stored in.
\context_system::instance()->id, // System instance is always used for this
@ -181,7 +181,7 @@ class studyplanpage {
* Webservice structure for basic info
* @param int $value Webservice requirement constant
*/
public static function simple_structure($value = VALUE_REQUIRED) : \external_description {
public static function simple_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of studyplan page'),
"fullname" => new \external_value(PARAM_TEXT, 'name of studyplan page'),
@ -211,7 +211,7 @@ class studyplanpage {
'enddate' => $this->r->enddate,
'timing' => $this->timing(),
"perioddesc" => period::page_model($this),
'timeless' => \get_config("local_treestudyplan","timelessperiods"),
'timeless' => \get_config("local_treestudyplan", "timelessperiods"),
];
}
@ -219,7 +219,7 @@ class studyplanpage {
* Webservice structure for editor info
* @param int $value Webservice requirement constant
*/
public static function editor_structure($value = VALUE_REQUIRED) : \external_description {
public static function editor_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of studyplan'),
"fullname" => new \external_value(PARAM_TEXT, 'name of studyplan page'),
@ -253,7 +253,7 @@ class studyplanpage {
'timing' => $this->timing(),
'studylines' => [],
"perioddesc" => period::page_model($this),
'timeless' => \get_config("local_treestudyplan","timelessperiods"),
'timeless' => \get_config("local_treestudyplan", "timelessperiods"),
];
$children = studyline::find_page_children($this);
@ -268,7 +268,7 @@ class studyplanpage {
* @param mixed $fields Parameter for new study plan page
* @param bool $bare If true, do not create a first page with copy of studyplan names
*/
public static function add($fields, $bare = false) : self {
public static function add($fields, $bare = false): self {
global $DB;
if (!isset($fields['studyplan_id'])) {
@ -297,8 +297,8 @@ class studyplanpage {
$page = self::find_by_id($id); // Make sure the new page is immediately cached.
if (!$bare) {
if(get_config("local_treestudyplan","copystudylinesnewpage")) {
if (get_config("local_treestudyplan", "copystudylinesnewpage")) {
$templatepage = null;
$templatelines = [];
// find the latest a page with lines in the plan
@ -316,16 +316,16 @@ class studyplanpage {
if (isset($templatepage)) {
foreach ($templatelines as $l) {
$map = []; // Bare copy still requires passing an empty array.
$l->duplicate($page,$map,true); // Do bare copy, which does not include line content.
$l->duplicate($page, $map, true); // Do bare copy, which does not include line content.
}
}
}
if(count(studyline::find_page_children($page)) == 0) {
if (count(studyline::find_page_children($page)) == 0) {
// Add an empty study line if there are currently no study lines
$lineinfo = ['page_id' => $id,
'name' => get_string("default_line_name","local_treestudyplan"),
'shortname' => get_string("default_line_shortname","local_treestudyplan"),
'name' => get_string("default_line_name", "local_treestudyplan"),
'shortname' => get_string("default_line_shortname", "local_treestudyplan"),
"color" => "#DDDDDD",
];
studyline::add($lineinfo);
@ -339,10 +339,10 @@ class studyplanpage {
* Edit studyplan page
* @param mixed $fields Parameters to change
*/
public function edit($fields) : self {
public function edit($fields): self {
global $DB;
$editable = ['fullname', 'shortname', 'description', 'descriptionformat', 'periods', 'startdate', 'enddate'];
$info = ['id' => $this->id, ];
$info = ['id' => $this->id ];
foreach ($editable as $f) {
if (array_key_exists($f, $fields)) {
$info[$f] = $fields[$f];
@ -386,7 +386,7 @@ class studyplanpage {
* Webservice structure for userinfo
* @param int $value Webservice requirement constant
*/
public static function user_structure($value = VALUE_REQUIRED) : \external_description {
public static function user_structure($value = VALUE_REQUIRED): \external_description {
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of studyplan page'),
"fullname" => new \external_value(PARAM_TEXT, 'name of studyplan page'),
@ -420,7 +420,7 @@ class studyplanpage {
'timing' => $this->timing(),
'studylines' => [],
"perioddesc" => period::page_model($this),
'timeless' => \get_config("local_treestudyplan","timelessperiods"),
'timeless' => \get_config("local_treestudyplan", "timelessperiods"),
];
$children = studyline::find_page_children($this);
@ -444,7 +444,7 @@ class studyplanpage {
foreach ($items as $c) {
if (in_array($c->type(), studyline::COURSE_TYPES)) {
$courses += 1;
if($c->completion($userid) >= completion::COMPLETED){
if ($c->completion($userid) >= completion::COMPLETED) {
$completed += 1;
}
}
@ -479,7 +479,7 @@ class studyplanpage {
* @param int $pageid Id of the page to copy
* @param studyplan $newstudyplan Studyplan to copy the page into
*/
public static function duplicate_page(int $pageid, studyplan $newstudyplan) : self {
public static function duplicate_page(int $pageid, studyplan $newstudyplan): self {
$ori = self::find_by_id($pageid);
$new = $ori->duplicate($newstudyplan);
return $new;
@ -489,11 +489,11 @@ class studyplanpage {
* Duplicate this studyplan page
* @param studyplan $newstudyplan Studyplan to copy the page into
*/
public function duplicate(studyplan $newstudyplan, $timeoffset = null) : self {
public function duplicate(studyplan $newstudyplan, $timeoffset = null): self {
if ($timeoffset == null) {
$timeoffset = new \DateInterval("P0D");
}
// First duplicate the studyplan structure.
$new = self::add([
'studyplan_id' => $newstudyplan->id(),
@ -502,7 +502,7 @@ class studyplanpage {
'description' => $this->r->description,
'pages' => $this->r->pages,
'startdate' => $this->startdate()->add($timeoffset)->format("Y-m-d"),
'enddate' => empty($this->r->enddate) ? null : ($this->enddate()->add($timeoffset)->format("Y-m-d")),
'enddate' => empty($this->r->enddate) ? null : ($this->enddate()->add($timeoffset)->format("Y-m-d")),
]);
// Copy any files related to this page.
@ -550,7 +550,7 @@ class studyplanpage {
$translation = [];
$newchild = $c->duplicate($new, $translation);
$itemtranslation += $translation; // Fixes behaviour where translation array is reset on each call.
$linetranslation[$c->id()] = $newchild->id();
$linetranslation[$c->id()] = $newchild->id();
}
// Now the itemtranslation array contains all of the old child id's as keys and all of the related new ids as values.
@ -569,7 +569,7 @@ class studyplanpage {
/**
* Description of export structure for webservices
*/
public static function export_structure() : \external_description {
public static function export_structure(): \external_description {
return new \external_single_structure([
"format" => new \external_value(PARAM_TEXT, 'format of studyplan export'),
"content" => new \external_value(PARAM_RAW, 'exported studyplan content'),
@ -748,9 +748,9 @@ class studyplanpage {
* Import previously exported files into the file storage
* @param string $area Name of the file area to export
* @param mixed $importfiles List of files to import from string in the format exported in export_model()
*
*
*/
public function import_files($importfiles,$area) {
public function import_files($importfiles, $area) {
$fs = get_file_storage();
foreach($importfiles as $file) {
if ($file['name'] != ".") {
@ -768,7 +768,6 @@ class studyplanpage {
}
}
/**
* Export this pages periods into an array before serialization
* @return array
@ -871,7 +870,7 @@ class studyplanpage {
$itemtranslation = [];
$itemconnections = [];
foreach ($model as $ix => $linemodel) {
$translation = [];
$translation = [];
$connections = [];
$linemap[$ix]->import_studyitems($linemodel["slots"], $translation, $connections);
$itemtranslation += $translation; // Fixes behaviour where translation array is reset on each call.

File diff suppressed because it is too large Load Diff

View File

@ -43,7 +43,7 @@ class success {
* @param string $msg Message to add to result
* @param array|object $data Custom data to pass to receiver
*/
public static function success($data=[]) : self {
public static function success($data=[]): self {
return new self(true, 'success', $data);
}
@ -52,7 +52,7 @@ class success {
* @param string $msg Message to add to result
* @param array|object $data Custom data to pass to receiver
*/
public static function fail($msg = "", $data=[]) : self {
public static function fail($msg = "", $data=[]): self {
return new self(false, $msg, $data);
}
@ -63,7 +63,7 @@ class success {
* @param array|object $data Custom data to pass to receiver
*/
public function __construct($success, $msg, $data=[]) {
$this->success = ($success) ? true : false;
$this->success = ($success) ? true : false;
$this->msg = $msg;
$this->data = json_encode($data);
}
@ -71,7 +71,7 @@ class success {
/**
* Describe the result for the webservice model
*/
public static function structure() : \external_description {
public static function structure(): \external_description {
return new \external_single_structure([
"success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'),
"msg" => new \external_value(PARAM_RAW, 'message'),
@ -79,7 +79,6 @@ class success {
]);
}
/**
* Make the webservice result model
* @return array Webservice value

View File

@ -72,7 +72,7 @@ class autocohortsync extends \core\task\scheduled_task {
}
}
/**
/**
* Perform immediate syncronization on a single studyplan.
*/
public static function syncplan(studyplan $studyplan) {
@ -86,7 +86,7 @@ class autocohortsync extends \core\task\scheduled_task {
$studyplan->clear_csync_changed(); // Clear the csync required flag.
}
/**
/**
* Perform immediate syncronization on a single studyline.
*/
public static function syncline(studyline $line) {

View File

@ -33,7 +33,6 @@ class teachingfinder {
/** @var string */
const TABLE = "local_treestudyplan_teachers";
/**
* List all studyplans the current user is teaching
* (Updates the cache if no results are found the first time)
@ -62,7 +61,7 @@ class teachingfinder {
* @param studyplan $plan Studyplan to check
* @return bool If teaching in this plan
*/
public static function is_teaching_studyplan(studyplan $plan,$userid) {
public static function is_teaching_studyplan(studyplan $plan, $userid) {
global $DB;
$count = $DB->count_records(self::TABLE, ['teacher_id' => $userid, "studyplan_id" => $plan->id()]);
return ($count > 0)?true:false;
@ -80,7 +79,6 @@ class teachingfinder {
return ($count > 0)?true:false;
}
/**
* Check if current user is teaching in a specific studyplan
* (Does not update the cache if results are 0)
@ -89,7 +87,7 @@ class teachingfinder {
*/
public static function am_teaching_studyplan(studyplan $plan) {
global $USER;
return self::is_teaching_studyplan($plan,$USER->id);
return self::is_teaching_studyplan($plan, $USER->id);
}
/**
@ -103,7 +101,7 @@ class teachingfinder {
return self::is_teaching($USER->id);
}
/**
/**
* Check if a user is teaching in a specific course
* @param int $courseid ID of the course
* @param int $userid ID of the user
@ -114,14 +112,14 @@ class teachingfinder {
return is_enrolled($coursecontext, $userid, 'mod/assign:grade');
}
/**
/**
* Check if current user is teaching in a specific course
* @param int $courseid ID of the course
* @return bool True if teaching in the course
*/
public static function am_teaching_course($courseid) {
global $USER;
return self::is_teaching_course($courseid,$USER->id);
return self::is_teaching_course($courseid, $USER->id);
}
/**

View File

@ -45,21 +45,20 @@ class utilityservice extends \external_api {
*/
const CAP_VIEW = "local/treestudyplan:viewuserreports";
protected static function load_mform($formname, $params, $ajaxformdata = null) {
global $CFG;
/* We don't need to load the form php file (class autoloading will handle that)
but we do need to check it's existence to give a nice developer warning
and protect against some forms of hacking
and protect against some forms of hacking
*/
$modmoodleform = "$CFG->dirroot/local/treestudyplan/classes/form/{$formname}.php";
if (!file_exists($modmoodleform)) {
throw new \moodle_exception('noformfile', 'local_treestudyplan','',$formname);
throw new \moodle_exception('noformfile', 'local_treestudyplan', '', $formname);
}
$mformclassname = "\\local_treestudyplan\\form\\{$formname}";
// Check if the form is a subclass of formbase.
if ( is_a($mformclassname,"\\local_treestudyplan\\form\\formbase",true)) {
if ( is_a($mformclassname, "\\local_treestudyplan\\form\\formbase", true)) {
$jsonparams = json_decode($params);
$mform = new $mformclassname( $jsonparams, $ajaxformdata);
return $mform;
@ -92,8 +91,7 @@ class utilityservice extends \external_api {
global $OUTPUT, $PAGE, $CFG;
\external_api::validate_context(\context_system::instance());
require_login(null,false,null);
require_login(null, false, null);
// Hack alert: Set a default URL to stop the annoying debug.
$PAGE->set_url('/');
@ -106,7 +104,7 @@ class utilityservice extends \external_api {
// Load the form before any output is started.
$mform = self::load_mform($formname, $params);
// Perform actual render.
$html = $mform->render();
$html = $mform->render();
$jsfooter = $PAGE->requires->get_end_code();
$output = ['html' => $html, 'javascript' => $jsfooter];
@ -130,7 +128,7 @@ class utilityservice extends \external_api {
/**
* Parameter description for webservice function submit_cm_editform
*/
public static function submit_mform_parameters() : \external_function_parameters {
public static function submit_mform_parameters(): \external_function_parameters {
return new \external_function_parameters( [
'formname' => new \external_value(PARAM_COMPONENT, 'name of the treestudyplan form to parse'),
'params' => new \external_value(PARAM_RAW, 'JSON encoded parameters for form initialization'),
@ -141,7 +139,7 @@ class utilityservice extends \external_api {
/**
* Return value description for webservice function submit_cm_editform
*/
public static function submit_mform_returns() : \external_description {
public static function submit_mform_returns(): \external_description {
return success::structure(); // Success structure includes data component which encodes date in json format.
}
@ -154,24 +152,23 @@ class utilityservice extends \external_api {
*/
public static function submit_mform($formname, $params, $formdata) {
\external_api::validate_context(\context_system::instance());
require_login(null,false,null);
require_login(null, false, null);
$ajaxformdata = [];
parse_str($formdata,$ajaxformdata);
parse_str($formdata, $ajaxformdata);
// Load the form, provide submitted form data and perform security checks
$mform = self::load_mform($formname, $params, $ajaxformdata);
$return = $mform->process_submission();
// Pass form processing result as success data component.
return success::success($return)->model();
}
/**
* Parameter description for webservice function submit_cm_editform
*/
public static function getsettings_parameters() : \external_function_parameters {
public static function getsettings_parameters(): \external_function_parameters {
return new \external_function_parameters( [
] );
}
@ -179,7 +176,7 @@ class utilityservice extends \external_api {
/**
* Return value description for webservice function submit_cm_editform
*/
public static function getsettings_returns() : \external_description {
public static function getsettings_returns(): \external_description {
return new \external_single_structure([
"hivizdropslots" => new \external_value(PARAM_BOOL, 'High visibility drop slots for items'),
"toolboxleft" => new \external_value(PARAM_BOOL, 'Start toolbox default on left side'),
@ -192,13 +189,12 @@ class utilityservice extends \external_api {
*/
public static function getsettings() {
\external_api::validate_context(\context_system::instance());
require_login(null,false,null);
require_login(null, false, null);
return [
"hivizdropslots" => get_config("local_treestudyplan","hivizdropslots"),
"toolboxleft" => get_config("local_treestudyplan","toolboxleft")
"hivizdropslots" => get_config("local_treestudyplan", "hivizdropslots"),
"toolboxleft" => get_config("local_treestudyplan", "toolboxleft")
];
}
}

View File

@ -66,8 +66,8 @@ cli_writeln("Creating {$amount} new badges");
$fortunepath = "/usr/games/fortune";
if (!is_executable($fortunepath)) {
// Get a fortune if it is available.
cli_error('/usr/bin/fortune not found, which is needed for this script. Please install fortune',2);
}
cli_error('/usr/bin/fortune not found, which is needed for this script. Please install fortune', 2);
}
// Get administrator role and log in as.
$user = get_admin();
@ -76,7 +76,7 @@ if (!$user) {
cli_error("Unable to find admin user in DB.");
}
$auth = empty($user->auth) ? 'manual' : $user->auth;
$auth = empty($user->auth) ? 'manual' : $user->auth;
if ($auth == 'nologin' || !is_enabled_auth($auth)) {
cli_error(sprintf("User authentication is either 'nologin' or disabled. Check Moodle authentication method for '%s'",
$user->username));
@ -87,7 +87,6 @@ $authplugin->sync_roles($user);
login_attempt_valid($user);
complete_user_login($user);
for ($i=0; $i<$amount; $i++) {
$fortune = shell_exec("{$fortunepath} -n 160 ");
$pieces = explode(" ", $fortune);
@ -95,11 +94,10 @@ for ($i=0; $i<$amount; $i++) {
$fordb = new \stdClass();
$fordb->id = null;
$now = time();
$randomicon = new randomimage(10,256,256);
$randomicon = new randomimage(10, 256, 256);
$fordb->name = $name;
$fordb->version = 1;
@ -134,7 +132,7 @@ for ($i=0; $i<$amount; $i++) {
$newid = $DB->insert_record('badge', $fordb, true);
// Trigger event, badge created.
$eventparams = array('objectid' => $newid, 'context' => $PAGE->context);
$eventparams = ['objectid' => $newid, 'context' => $PAGE->context];
$event = \core\event\badge_created::create($eventparams);
$event->trigger();
@ -143,4 +141,3 @@ for ($i=0; $i<$amount; $i++) {
cli_writeln("Created new badge '{$name}'");
}

View File

@ -73,7 +73,7 @@ if (!$user) {
cli_error("Unable to find admin user in DB.");
}
$auth = empty($user->auth) ? 'manual' : $user->auth;
$auth = empty($user->auth) ? 'manual' : $user->auth;
if ($auth == 'nologin' || !is_enabled_auth($auth)) {
cli_error(sprintf("User authentication is either 'nologin' or disabled. Check Moodle authentication method for '%s'",
$user->username));

View File

@ -28,21 +28,18 @@ require_once($CFG->libdir.'/weblib.php');
$systemcontext = context_system::instance();
$PAGE->set_url("/local/treestudyplan/coach.php", array());
$PAGE->set_url("/local/treestudyplan/coach.php", []);
require_login();
$PAGE->set_pagelayout('base');
$PAGE->set_context($systemcontext);
$PAGE->set_title(get_string('coaching_plans', 'local_treestudyplan'));
$PAGE->set_heading(get_string('coaching_plans', 'local_treestudyplan'));
premium::require_premium();
if ( ! (\get_config("local_treestudyplan","enablecoach")) ) {
throw new \moodle_exception("error:coachdisabled","local_treestudyplan");
if ( ! (\get_config("local_treestudyplan", "enablecoach")) ) {
throw new \moodle_exception("error:coachdisabled", "local_treestudyplan");
}
// Load javascripts and specific css.
$PAGE->requires->css(new moodle_url($CFG->wwwroot.'/local/treestudyplan/css/bootstrap-vue/bootstrap-vue.css'));
@ -77,11 +74,11 @@ print $OUTPUT->header();
<a href='#' @click.prevent='closeStudyplan'
><i style='font-size: 150%;' class='fa fa-chevron-left'></i> <?php t('back');?></a>
<span><?php t("studyplan_select"); ?></span>&nbsp;
<s-studyplan-details
v-model="displayedstudyplan"
<s-studyplan-details
v-model="displayedstudyplan"
v-if="displayedstudyplan.description"
></s-studyplan-details>
<div class="flex-grow-1"><!-- Spacer to align student selector right --></div>
<div class="flex-grow-1"><!-- Spacer to align student selector right --></div>
<span><?php t('selectstudent_btn') ?></span>
<s-prevnext-selector
:options="associatedstudents"

View File

@ -23,7 +23,7 @@
defined('MOODLE_INTERNAL') || die();
$services = [
];
$functions = [
@ -227,7 +227,7 @@ $functions = [
'ajax' => true,
'capabilities' => '',
'loginrequired' => true,
],
],
'local_treestudyplan_search_related_badges' => [ // Web service function name.
'classname' => '\local_treestudyplan\studyplanservice', // Class containing the external function.
'methodname' => 'search_related_badges', // External function name.
@ -236,7 +236,7 @@ $functions = [
'ajax' => true,
'capabilities' => '',
'loginrequired' => true,
],
],
/***************************
* Association functions

View File

@ -532,8 +532,6 @@ function xmldb_local_treestudyplan_upgrade($oldversion) {
$dbman->add_field($table, $field);
}
// Treestudyplan savepoint reached.
upgrade_plugin_savepoint(true, 2024022502, 'local', 'treestudyplan');
@ -564,13 +562,13 @@ function xmldb_local_treestudyplan_upgrade($oldversion) {
$table->add_field('timeenrolled', XMLDB_TYPE_INTEGER, '12', null, null, null, null);
$table->add_field('enrolled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
$table->add_field('enrolledby', XMLDB_TYPE_INTEGER, '18', null, null, null, null);
// Adding keys to table local_treestudyplan_lineuser.
$table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
$table->add_key('line_id-id', XMLDB_KEY_FOREIGN, ['line_id'], 'local_treestudyplan_line', ['id']);
$table->add_key('user_id-id', XMLDB_KEY_FOREIGN, ['user_id'], 'user', ['id']);
$table->add_key('enrolledby-id', XMLDB_KEY_FOREIGN, ['enrolledby'], 'user', ['id']);
// Conditionally launch create table for local_treestudyplan_lineuser.
if (!$dbman->table_exists($table)) {
$dbman->create_table($table);
@ -634,7 +632,7 @@ function xmldb_local_treestudyplan_upgrade($oldversion) {
}
if ($oldversion < 2024052400) {
// Changing the default of field template on table local_treestudyplan to 0.
$table = new xmldb_table('local_treestudyplan');
$field = new xmldb_field('template', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'suspended');
@ -649,12 +647,9 @@ function xmldb_local_treestudyplan_upgrade($oldversion) {
// Launch change of default for field suspended.
$dbman->change_field_default($table, $field);
// Treestudyplan savepoint reached.
upgrade_plugin_savepoint(true, 2024052400, 'local', 'treestudyplan');
}
return true;
}

View File

@ -26,7 +26,7 @@ require_once($CFG->libdir.'/weblib.php');
$systemcontext = context_system::instance();
$PAGE->set_url("/local/treestudyplan/doc.php", array());
$PAGE->set_url("/local/treestudyplan/doc.php", []);
if ($CFG->debugdeveloper) {
$PAGE->requires->css(new moodle_url($CFG->wwwroot.'/local/treestudyplan/css/devstyles.css'));
}

View File

@ -56,7 +56,7 @@ if (!empty($add)) {
);
} else if (!empty($update)) {
$data = $DB->get_record("local_treestudyplan_invit", array('id' => $update));
$data = $DB->get_record("local_treestudyplan_invit", ['id' => $update]);
$data->update = $update;
if (empty($data) || $data->user_id != $USER->id) {
throw new \moodle_exception('invalidaction', 'local_treestudyplan');;
@ -64,7 +64,7 @@ if (!empty($add)) {
}
} else if (!empty($resend)) {
$data = $DB->get_record("local_treestudyplan_invit", array('id' => $resend));
$data = $DB->get_record("local_treestudyplan_invit", ['id' => $resend]);
$data->resend = $resend;
if (empty($data) || $data->user_id != $USER->id) {
throw new \moodle_exception('invalidaction', 'local_treestudyplan');;
@ -77,7 +77,7 @@ if (!empty($add)) {
print $OUTPUT->footer();
exit;
} else if (!empty($delete)) {
$data = $DB->get_record("local_treestudyplan_invit", array('id' => $delete));
$data = $DB->get_record("local_treestudyplan_invit", ['id' => $delete]);
$data->delete = $delete;
if (empty($data) || $data->user_id != $USER->id) {
throw new \moodle_exception('invalidaction', 'local_treestudyplan');;

View File

@ -31,7 +31,7 @@ use local_treestudyplan\debug;
$systemcontext = context_system::instance();
$PAGE->set_url("/local/treestudyplan/edit-plan.php", array());
$PAGE->set_url("/local/treestudyplan/edit-plan.php", []);
require_login();
// Figure out the context (category or system, based on either category or context parameter).
@ -73,19 +73,19 @@ if ($studyplancontext->id > 1) {
$PAGE->navbar->add(get_string('cfg_plans', 'local_treestudyplan'));
// Coursecat context
$cat = \core_course_category::get($studyplancontext->instanceid,IGNORE_MISSING,true); // We checck visibility later
} else {
$cat = \core_course_category::get($studyplancontext->instanceid, IGNORE_MISSING, true); // We checck visibility later
} else {
// System context
$cat = \core_course_category::top();
}
if (!$cat->is_uservisible()) {
throw new \moodle_exception("error:cannotviewcategory","local_treestudyplan","/local/treestudyplan/edit_plan.php",$contextname);
throw new \moodle_exception("error:cannotviewcategory", "local_treestudyplan", "/local/treestudyplan/edit_plan.php", $contextname);
}
if (!has_capability('local/treestudyplan:editstudyplan', $studyplancontext)) {
throw new \moodle_exception("error:nostudyplaneditaccess","local_treestudyplan","/local/treestudyplan/edit_plan.php",$contextname);
throw new \moodle_exception("error:nostudyplaneditaccess", "local_treestudyplan", "/local/treestudyplan/edit_plan.php", $contextname);
}
// Load javascripts and specific css.
@ -94,7 +94,7 @@ if ($CFG->debugdeveloper) {
$PAGE->requires->css(new moodle_url($CFG->wwwroot.'/local/treestudyplan/css/devstyles.css'));
}
$PAGE->requires->js_call_amd('local_treestudyplan/page-edit-plan', 'init', [$studyplancontext->id, $categoryid, [
"defaultAggregation" => get_config("local_treestudyplan","aggregation_mode"),
"defaultAggregation" => get_config("local_treestudyplan", "aggregation_mode"),
]]);
/**
@ -121,17 +121,17 @@ print $OUTPUT->header();
<div v-cloak>
<div v-if='!activestudyplan && usedcontexts && !loadingstudyplan' class='ml-3 mb-3 s-context-selector'>
<b-form-select text='<?php print($contextname);?>' :value="contextid" @change='switchContext'
:class="(!(usedcontexts.length))?'text-primary':''">
:class="(!(usedcontexts.length)) ? 'text-primary' : ''">
<b-form-select-option v-if='!(usedcontexts.length)' :value="contextid"
:class="'text-primary'">
<span><?php t("loading",null,"core"); ?>...</span></b-form-select-option>
<span><?php t("loading", null, "core"); ?>...</span></b-form-select-option>
<b-form-select-option v-for='ctx in usedcontexts' :key='ctx.id' :value="ctx.context_id"
:class="(ctx.studyplancount > 0) ? 'font-weight-bold' : ''"
><span v-for="(p, i) in ctx.category.path"
><span v-if="i>0"> / </span>{{ p }}</span> <span>({{ ctx.studyplancount }})</span>
</b-form-select-option>
</b-form-select>
<div v-if="!(usedcontexts.length)" style="position: relative; top: 0.3rem; width: 1.2rem; height: 1.2rem; font-size: 0.7rem;"
<div v-if="!(usedcontexts.length)" style="position: relative; top: 0.3rem; width: 1.2rem; height: 1.2rem; font-size: 0.7rem;"
class="spinner-border text-primary" role="status"></div>
</div>
@ -154,15 +154,15 @@ print $OUTPUT->header();
v-model="create.studyplan"
type="button"
variant="primary"
default-aggregation="<?php print(get_config("local_treestudyplan","aggregation_mode")); ?>"
default-aggregation="<?php print(get_config("local_treestudyplan", "aggregation_mode")); ?>"
:contextid='contextid'
><i class='fa fa-plus'></i> {{ text.studyplan_add }}</t-studyplan-edit>
<b-button
variant='danger' href='#' role='presentation' @click="import_studyplan "
><i class='fa fa-upload'></i> {{ text.advanced_import_from_file }}</b-button
><mform v-if="premiumenabled && templatecount > 0"
name="studyplan_fromtemplateform"
:params="{contextid: contextid }"
name="studyplan_fromtemplateform"
:params="{contextid: contextid }"
@saved="onStudyPlanCreated"
variant="success"
type="button"

View File

@ -31,7 +31,7 @@ $invitedurl = "/local/treestudyplan/invited.php";
$systemcontext = context_system::instance();
$PAGE->set_url("/local/treestudyplan/invitations.php", array());
$PAGE->set_url("/local/treestudyplan/invitations.php", []);
require_login();
$PAGE->set_pagelayout('base');
@ -45,12 +45,12 @@ $PAGE->requires->js_call_amd('local_treestudyplan/page-invitemanager', 'init');
// Retrieve list of courses that the student is enrolled in.
$sent = optional_param('sent', '', PARAM_INT);
if (!empty($sent)) {
$invite = $DB->get_record('local_treestudyplan_invit', array('id' => $sent));
$invite = $DB->get_record('local_treestudyplan_invit', ['id' => $sent]);
\core\notification::success(get_string('invite_resent_msg', 'local_treestudyplan', $invite));
};
if (!get_config("local_treestudyplan","enableplansharing")) {
if (!get_config("local_treestudyplan", "enableplansharing")) {
$PAGE->set_title(get_string('accessdenied', 'admin'));
$PAGE->set_heading(get_string('accessdenied', 'admin'));
@ -59,7 +59,7 @@ if (!get_config("local_treestudyplan","enableplansharing")) {
// Render page for skill level 0 (global).
print "<div class='box errorbox alert alert-danger'>";
print get_string('accessdenied','admin');
print get_string('accessdenied', 'admin');
print "</div>";
print $OUTPUT->footer();
@ -71,7 +71,7 @@ if (!get_config("local_treestudyplan","enableplansharing")) {
print "<p>".get_string('invite_description', 'local_treestudyplan')."</p>";
$invites = $DB->get_records('local_treestudyplan_invit', array('user_id' => $USER->id));
$invites = $DB->get_records('local_treestudyplan_invit', ['user_id' => $USER->id]);
print "<h3>".get_string('invite_tablecaption', 'local_treestudyplan')."</h3>";
print "<table class='m-manage_invites'>";

View File

@ -41,13 +41,13 @@ $PAGE->set_context($systemcontext);
// See if we can get a valid user for this invited.
$invitekey = optional_param('key', '', PARAM_ALPHANUM); // Module name.
$PAGE->set_url("/local/treestudyplan/invited.php", array('key' => $invitekey));
$PAGE->set_url("/local/treestudyplan/invited.php", ['key' => $invitekey]);
$invite = $DB->get_record_select("local_treestudyplan_invit",
$DB->sql_compare_text("invitekey"). " = " . $DB->sql_compare_text(":invitekey"),
['invitekey' => $invitekey]);
if (!get_config("local_treestudyplan","enableplansharing")) {
if (!get_config("local_treestudyplan", "enableplansharing")) {
$PAGE->set_title(get_string('accessdenied', 'admin'));
$PAGE->set_heading(get_string('accessdenied', 'admin'));
@ -56,7 +56,7 @@ if (!get_config("local_treestudyplan","enableplansharing")) {
// Render page for skill level 0 (global).
print "<div class='box errorbox alert alert-danger'>";
print get_string('accessdenied','admin');
print get_string('accessdenied', 'admin');
print "</div>";
print $OUTPUT->footer();
@ -85,7 +85,7 @@ if (!get_config("local_treestudyplan","enableplansharing")) {
}
$PAGE->requires->js_call_amd('local_treestudyplan/page-myreport', 'init', ['invited', $invitekey]);
$student = $DB->get_record('user', array('id' => $invite->user_id));
$student = $DB->get_record('user', ['id' => $invite->user_id]);
$PAGE->set_title(get_string('report_invited', 'local_treestudyplan', "{$student->firstname} {$student->lastname}" ));
$PAGE->set_heading(get_string('report_invited', 'local_treestudyplan', "{$student->firstname} {$student->lastname}"));

View File

@ -67,12 +67,12 @@ $string["invite_date"] = "Date";
$string["invite_resent_msg"] = 'The invitation for {$a->name}<{$a->email}> has been sent';
$string["invite_mail_subject"] = 'Shared grade card of {$a->sender}';
$string["invite_mail_text"] = '
<p>Dear {$a->invitee},</p>
<p>Dear {$a->invitee}, </p>
<p>I\'d like to invite you to view my study plan and progess.</p>
<p>The link below gives you access at any time to view the most recent results. Feel free to bookmark this link in your browser.</p>
<p>Click the link below to view the study plan:<br>
<a href="{$a->link}">{$a->link}</a></p>
<p>Kind regards,<br>
<p>Kind regards, <br>
{$a->sender}</p>
';
@ -271,7 +271,6 @@ $string["studyplan_past"] = "Past study plans";
$string["studyplan_present"] = "Current study plans";
$string["studyplan_future"] = "Upcoming study plans";
$string["link_myreport"] = "My study plan";
$string["link_viewplan"] = "Study plans";
$string["link_editplan"] = "Manage study plans";
@ -416,7 +415,6 @@ $string["currentpage"] = "Currently active page:";
$string["advanced_bulk_course_timing"] = 'Sync course timing to periods';
$string["advanced_bulk_course_timing_desc"] = 'Synchronize the start and end date of all courses in the currently active studyplan page to periods in which they are placed.';
$string["advanced_cascade_cohortsync_title"] = "Cascade cohort sync";
$string["advanced_cascade_cohortsync_desc"] = "Add cohort sync enrolment to each course in this study plan for all cohorts linked to this study plan";
$string["advanced_cascade_cohortsync"] = "Cascade cohort sync";
@ -497,7 +495,6 @@ $string["setting_premium_key"] = 'Activation key';
$string["settingdesc_premium_key"] = 'Paste the premium key you received in the box above.<br> <b>Attention!</b> The lines <i>----- BEGIN ACTIVATION KEY -----</i> and <i>----- END ACTIVATION KEY -----</i> are part of the key.';
$string["setting_premium_debug"] = 'Debug info for premium key';
$string["premiumfeature:morestudyplans"] = 'Creating more than 5 studyplans in a single category is a premium feature.';
$string["premiumfeature:morecategories"] = 'Creating studyplans in more than 20 categories is a premium feature.';
$string["premiumfeature:warning"] = 'The features on this page are only accessible if your site has premium features enabled.';

View File

@ -41,7 +41,6 @@ $string["treestudyplan:selectowngradables"] = 'Docenten kunnen in hun eigen curs
$string["treestudyplan:lineunenrol"] = "Beheer inschrijvingen van studenten in leerlijnen";
$string["treestudyplan:coach"] = "Beschikbaar als coach";
$string["report"] = 'Voortgangsrapport';
$string["report_invited"] = 'Voortgang van {$a}';
$string["report_index"] = 'Studieplannen van studenten inzien';
@ -333,7 +332,6 @@ $string["core_aggregator_desc"] = 'Gebruik de ingesteld cursusvoltooiing';
$string["competency_aggregator_title"] = 'Cursuscompetenties';
$string["competency_aggregator_desc"] = 'Gebruik de bij de cursus ingestelde competenties';
$string["setting_bistate_heading"] = 'Standaardwaarden voor Behaald + Vereiste leerdoelen ';
$string["settingdesc_bistate_heading"] = 'Stel de standaardwaarden in voor deze verzamelmethode';
@ -369,7 +367,6 @@ $string["settingdesc_copystudylinesnewpage"] = 'Bij aanmaken van een nieuw tabbl
$string["setting_continueperiodnumberingnewpage"] = 'Perioden doornummeren op nieuw tabblad';
$string["settingdesc_continueperiodnumberingnewpage"] = 'Bij aanmaken van een nieuw tabblad, wordt de standaardnaam van perioden doorgenummerd (b.v. P5, P6, P7, P8) in plaats van herstart (P1, P2, P3, P4)';
$string["grade_include"] = 'Doel';
$string["grade_require"] = 'Verplicht';
$string["required_goal"] = 'Verplicht leerdoel';

40
lib.php
View File

@ -44,7 +44,6 @@ function local_treestudyplan_unit_get_editor_options(context $context) {
'trusttext' => 0];
}
/**
* Create primary navigation links for studyplan if needed
*/
@ -56,7 +55,7 @@ function local_treestudyplan_autofill_customusermenuitems() {
"/local/treestudyplan/view-plan.php" => ["included" => false, "strkey" => "link_viewplan"],
"/local/treestudyplan/edit-plan.php" => ["included" => false, "strkey" => "link_editplan"],
];
if ((premium::enabled() && \get_config("local_treestudyplan","enablecoach"))) {
if ((premium::enabled() && \get_config("local_treestudyplan", "enablecoach"))) {
// Also include the coach role if enabled
$navitems["/local/treestudyplan/coach.php"] = ["included" => false, "strkey" => "link_coach"];
}
@ -118,7 +117,7 @@ function local_treestudyplan_extend_navigation(global_navigation $navigation) {
Studieplannen beheren|/local/treestudyplan/edit-plan.php.
Using some javascript magic we'll hide the links that are not accessible.
(Since the Output API does not easily support inline style tags, adding one through Javascript is easier,.
(Since the Output API does not easily support inline style tags, adding one through Javascript is easier, .
and not much more complex than loading a separate stylesheet for each link we want to hide).
We will add all the hrefs that should be hidden to this variable below.
*/
@ -140,7 +139,7 @@ function local_treestudyplan_extend_navigation(global_navigation $navigation) {
// Create studyplan node.
$node = navigation_node::create(
get_string("link_myreport", "local_treestudyplan"),
new moodle_url($CFG->wwwroot . "/local/treestudyplan/myreport.php", array()),
new moodle_url($CFG->wwwroot . "/local/treestudyplan/myreport.php", []),
global_navigation::TYPE_SYSTEM,
null,
"local_treestudyplan_myreport",
@ -152,7 +151,7 @@ function local_treestudyplan_extend_navigation(global_navigation $navigation) {
// Create invitenode node.
$invitenode = navigation_node::create(
get_string("manage_invites", "local_treestudyplan"),
new moodle_url($CFG->wwwroot . "/local/treestudyplan/invitations.php", array()),
new moodle_url($CFG->wwwroot . "/local/treestudyplan/invitations.php", []),
global_navigation::TYPE_CUSTOM ,
null,
"local_treestudyplan_invitemgmt",
@ -169,7 +168,7 @@ function local_treestudyplan_extend_navigation(global_navigation $navigation) {
|| webservicehelper::has_capability_in_any_category('local/treestudyplan:viewuserreports')) {
$node = navigation_node::create(
get_string("link_viewplan", "local_treestudyplan"),
new moodle_url($CFG->wwwroot . "/local/treestudyplan/view-plan.php", array()),
new moodle_url($CFG->wwwroot . "/local/treestudyplan/view-plan.php", []),
global_navigation::TYPE_SYSTEM ,
null,
"local_treestudyplan_viewplan",
@ -186,7 +185,7 @@ function local_treestudyplan_extend_navigation(global_navigation $navigation) {
) {
$node = navigation_node::create(
get_string("link_editplan", "local_treestudyplan"),
new moodle_url($CFG->wwwroot . "/local/treestudyplan/edit-plan.php", array()),
new moodle_url($CFG->wwwroot . "/local/treestudyplan/edit-plan.php", []),
global_navigation::TYPE_SYSTEM ,
null,
"local_treestudyplan_editplan",
@ -198,19 +197,19 @@ function local_treestudyplan_extend_navigation(global_navigation $navigation) {
} else {
$hideprimaryhrefs[] = "/local/treestudyplan/edit-plan.php";
}
$coachsql = "SELECT COUNT('id') FROM {local_treestudyplan_coach} as c
$coachsql = "SELECT COUNT('id') FROM {local_treestudyplan_coach} as c
INNER JOIN {local_treestudyplan} AS t ON c.studyplan_id = t.id
WHERE c.user_id = :user_id";
if ( (premium::enabled() && \get_config("local_treestudyplan","enablecoach")) &&
if ( (premium::enabled() && \get_config("local_treestudyplan", "enablecoach")) &&
(has_capability('local/treestudyplan:coach', context_system::instance())
|| webservicehelper::has_capability_in_any_category('local/treestudyplan:coach')
) && $DB->count_records_sql($coachsql,["user_id" => $USER->id]) > 0
) && $DB->count_records_sql($coachsql, ["user_id" => $USER->id]) > 0
) {
$node = navigation_node::create(
get_string("link_coach", "local_treestudyplan"),
new moodle_url($CFG->wwwroot . "/local/treestudyplan/coach.php", array()),
new moodle_url($CFG->wwwroot . "/local/treestudyplan/coach.php", []),
global_navigation::TYPE_SYSTEM ,
null,
"local_treestudyplan_coach",
@ -231,7 +230,7 @@ function local_treestudyplan_extend_navigation(global_navigation $navigation) {
// Create invitenode node.
$invitenode = navigation_node::create(
get_string("nav_invited", "local_treestudyplan"),
new moodle_url($CFG->wwwroot . "/local/treestudyplan/invited.php", array()),
new moodle_url($CFG->wwwroot . "/local/treestudyplan/invited.php", []),
global_navigation::TYPE_USER ,
null,
"local_treestudyplan_invitemgmt",
@ -315,7 +314,7 @@ function local_treestudyplan_reset_fontawesome_icon_map() {
*/
function local_treestudyplan_send_invite($inviteid) {
global $DB, $USER, $CFG;
$invite = $DB->get_record("local_treestudyplan_invit", array('id' => $inviteid));
$invite = $DB->get_record("local_treestudyplan_invit", ['id' => $inviteid]);
$noreply = 'noreply@' . get_host_from_url($CFG->wwwroot);
$mailer = get_mailer();
@ -433,20 +432,18 @@ function local_treestudyplan_pluginfile(
bool $forcedownload,
array $options = []
): bool {
global $DB,$USER;
global $DB, $USER;
$studyplan_filecaps = ["local/treestudyplan:editstudyplan","local/treestudyplan:viewuserreports"];
$studyplanfilecaps = ["local/treestudyplan:editstudyplan", "local/treestudyplan:viewuserreports"];
// Check the contextlevel is as expected - the studyplan plugin only uses system context for storing files.
// This avoids headaches when moving studyplans between contexts, while the security impact is minimal...
// This avoids headaches when moving studyplans between contexts, while the security impact is minimal...
if ($context->contextlevel != CONTEXT_SYSTEM) {
return false;
}
// Make sure the filearea is one of those used by the plugin.
if (in_array($filearea,["studyplan","icon","studyplanpage"])) {
if (in_array($filearea, ["studyplan", "icon", "studyplanpage"])) {
// The args is an array containing [itemid, path].
// Fetch the itemid from the path.
$itemid = array_shift($args);
@ -476,7 +473,7 @@ function local_treestudyplan_pluginfile(
return false;
}
} else if (in_array($filearea,['defaulticon'])) {
} else if (in_array($filearea, ['defaulticon'])) {
// The args is an array containing [itemid, path].
// Fetch the itemid from the path.
$itemid = array_shift($args);
@ -506,4 +503,3 @@ function local_treestudyplan_pluginfile(
}

View File

@ -29,17 +29,17 @@ use local_treestudyplan\teachingfinder;
$systemcontext = context_system::instance();
$PAGE->set_url("/local/treestudyplan/myreport.php", array());
$PAGE->set_url("/local/treestudyplan/myreport.php", []);
require_login();
$PAGE->set_pagelayout('base');
$PAGE->set_context($systemcontext);
//$teachermode = has_capability("local/treestudyplan:viewuserreports", $systemcontext);
$am_teaching = teachingfinder::is_teaching($USER->id);
$have_plans = studyplan::exist_for_user($USER->id);
$amteaching = teachingfinder::is_teaching($USER->id);
$haveplans = studyplan::exist_for_user($USER->id);
if ($am_teaching) {
if ($amteaching) {
$PAGE->set_title(get_string('myreport_teachermode', 'local_treestudyplan'));
$PAGE->set_heading(get_string('myreport_teachermode', 'local_treestudyplan'));
} else {
@ -52,7 +52,7 @@ $PAGE->requires->css(new moodle_url($CFG->wwwroot.'/local/treestudyplan/css/boot
if ($CFG->debugdeveloper) {
$PAGE->requires->css(new moodle_url($CFG->wwwroot.'/local/treestudyplan/css/devstyles.css'));
}
$PAGE->requires->js_call_amd('local_treestudyplan/page-myreport', 'init', [$am_teaching ? 'teaching' : 'own']);
$PAGE->requires->js_call_amd('local_treestudyplan/page-myreport', 'init', [$amteaching ? 'teaching' : 'own']);
/**
* Shortcut function to provide translations
@ -70,7 +70,7 @@ print $OUTPUT->header();
print '<div class="m-buttonbar" style="margin-bottom: 1em; text-align: right;">';
if (get_config("local_treestudyplan","enableplansharing") && !$am_teaching) {
if (get_config("local_treestudyplan", "enableplansharing") && !$amteaching) {
print '<a class="btn btn-primary" href="invitations.php" id="manage_invites">';
print '&nbsp;<i class="fa fa-share"></i>&nbsp;'.t('manage_invites').'</a>';
}
@ -83,7 +83,7 @@ print " <span class='sr-only'>Loading...</span>";
print " </div>";
print " </div>";
print " <div v-cloak>";
if ($am_teaching) {
if ($amteaching) {
print " <r-report type='teaching' teachermode ></r-report>";
} else {
print " <r-report type='own' :userid='userid'></r-report>";

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
/**
* Report
* Report
* @package local_treestudyplan
* @copyright 2023 P.M. Kuipers
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@ -45,18 +45,16 @@ $contextname = $ci->pathstr();
$firstperiod = optional_param('firstperiod', 0, PARAM_INT); // First period to show
$lastperiod = optional_param('lastperiod', 0, PARAM_INT); // Last periode to show
$PAGE->set_pagelayout('report');
$PAGE->set_title(get_string('studyplan_report', 'local_treestudyplan'));
$PAGE->set_heading(get_string('studyplan_report', 'local_treestudyplan'));
if (!premium::enabled()) {
throw new \moodle_exception("error:nopremiumaccess","local_treestudyplan","",premium::statusdescription());
throw new \moodle_exception("error:nopremiumaccess", "local_treestudyplan", "", premium::statusdescription());
}
if(!has_capability('local/treestudyplan:viewuserreports', $context)) {
throw new \moodle_exception("error:nostudyplanviewaccess","local_treestudyplan","",$contextname);
if (!has_capability('local/treestudyplan:viewuserreports', $context)) {
throw new \moodle_exception("error:nostudyplanviewaccess", "local_treestudyplan", "", $contextname);
}
// Load javascripts and specific css.
@ -66,7 +64,6 @@ if ($CFG->debugdeveloper) {
}
$PAGE->requires->js_call_amd('local_treestudyplan/page-result-overview', 'init', [$studyplan->id(), $page->id(), $firstperiod, $lastperiod]);
/**
* Shortcut function to provide translations
*
@ -80,8 +77,8 @@ function t($str, $param = null, $plugin = 'local_treestudyplan') {
}
print $OUTPUT->header();
print "<h3><b>{$contextname}</b> / {$studyplan->name()}</h3>";
if($studyplan->name() != $page->fullname()) {
print "<h3><b>{$contextname}</b> / {$studyplan->name()}</h3>";
if ($studyplan->name() != $page->fullname()) {
print "<h4>{$page->fullname()}</h4>";
}
?>
@ -104,8 +101,8 @@ if($studyplan->name() != $page->fullname()) {
<div class="col-sm-6">
<select class="custom-select" :value="page.id" @change="selectedPage">
<template v-if="studyplan">
<option v-for="p in studyplan.pages"
:key="p.id"
<option v-for="p in studyplan.pages"
:key="p.id"
:value="p.id"
:selected="(page.id == p.id)?true:false"
>{{p.fullname}}</option>
@ -119,8 +116,8 @@ if($studyplan->name() != $page->fullname()) {
<div class="col-sm-2">
<select class="custom-select" @change="selectedFirstPeriod">
<template v-if="page">
<option v-for="p in page.perioddesc"
:key="p.id"
<option v-for="p in page.perioddesc"
:key="p.id"
:value="p.period"
:selected="(structure.firstperiod == p.period)?true:false"
>{{p.fullname}}</option>
@ -133,7 +130,7 @@ if($studyplan->name() != $page->fullname()) {
<template v-if="page">
<template v-for="p in page.perioddesc">
<option v-if="p.period >= structure.firstperiod"
:key="p.id"
:key="p.id"
:value="p.period"
:selected="(structure.lastperiod == p.period)?true:false"
>{{p.fullname}}</option>

View File

@ -6,7 +6,7 @@
// 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,.
// 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.
@ -56,12 +56,12 @@ if ($hassiteconfig) {
));
// Default image for study plans
$page->add(new admin_setting_configstoredfile('local_treestudyplan/defaulticon',
get_string('setting_defaulticon', 'local_treestudyplan'),
$page->add(new admin_setting_configstoredfile('local_treestudyplan/defaulticon',
get_string('setting_defaulticon', 'local_treestudyplan'),
get_string('settingdesc_defaulticon', 'local_treestudyplan'),
'defaulticon', 0,
[
'maxfiles' => 1,
'maxfiles' => 1,
'accepted_types' => ['.jpg', '.png']]
));
@ -89,7 +89,7 @@ if ($hassiteconfig) {
get_string('settingdesc_display_heading', 'local_treestudyplan')
));
$displayfields = ["shortname" => get_string("shortname"), "idnumber" => get_string("idnumber"), "fullname" => get_string("fullname"), ];
$displayfields = ["shortname" => get_string("shortname"), "idnumber" => get_string("idnumber"), "fullname" => get_string("fullname") ];
$infofields = ["" => get_string('none'), "description" => get_string("description"), "contacts" => get_string("teachers"), "idnumber" => get_string("idnumber")];
$handler = \core_customfield\handler::get_handler('core_course', 'course');
@ -106,49 +106,49 @@ if ($hassiteconfig) {
}
}
}
//get_config("local_treestudyplan","enableplansharing")
//get_config("local_treestudyplan", "enableplansharing")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/enableplansharing',
get_string('setting_enableplansharing', 'local_treestudyplan'),
get_string('settingdesc_enableplansharing', 'local_treestudyplan'),
true,
));
//get_config("local_treestudyplan","timelessperiods")
//get_config("local_treestudyplan", "timelessperiods")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/timelessperiods',
get_string('setting_timelessperiods', 'local_treestudyplan'),
get_string('settingdesc_timelessperiods', 'local_treestudyplan'),
false,
));
//get_config("local_treestudyplan","limitcourselist")
//get_config("local_treestudyplan", "limitcourselist")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/limitcourselist',
get_string('setting_limitcourselist', 'local_treestudyplan'),
get_string('settingdesc_limitcourselist', 'local_treestudyplan'),
false,
));
//get_config("local_treestudyplan","hivizdropslots")
//get_config("local_treestudyplan", "hivizdropslots")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/hivizdropslots',
get_string('setting_hivizdropslots', 'local_treestudyplan'),
get_string('settingdesc_hivizdropslots', 'local_treestudyplan'),
false,
));
//get_config("local_treestudyplan","toolboxleft")
//get_config("local_treestudyplan", "toolboxleft")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/toolboxleft',
get_string('setting_toolboxleft', 'local_treestudyplan'),
get_string('settingdesc_toolboxleft', 'local_treestudyplan'),
true,
));
//get_config("local_treestudyplan","copystudylinesnewpage")
//get_config("local_treestudyplan", "copystudylinesnewpage")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/copystudylinesnewpage',
get_string('setting_copystudylinesnewpage', 'local_treestudyplan'),
get_string('settingdesc_copystudylinesnewpage', 'local_treestudyplan'),
false,
));
//get_config("local_treestudyplan","continueperiodnumberingnewpage")
//get_config("local_treestudyplan", "continueperiodnumberingnewpage")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/continueperiodnumberingnewpage',
get_string('setting_continueperiodnumberingnewpage', 'local_treestudyplan'),
get_string('settingdesc_continueperiodnumberingnewpage', 'local_treestudyplan'),
@ -156,7 +156,7 @@ if ($hassiteconfig) {
));
if (premium::enabled()) {
//get_config("local_treestudyplan","enablecoach")
//get_config("local_treestudyplan", "enablecoach")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/enablecoach',
get_string('setting_enablecoach', 'local_treestudyplan'),
get_string('settingdesc_enablecoach', 'local_treestudyplan'),
@ -182,8 +182,8 @@ if ($hassiteconfig) {
get_string('settingdesc_infofields_heading', 'local_treestudyplan')
));
$positions = [ "above" => get_string('infofield_position_above', 'local_treestudyplan'),
"below" => get_string("infofield_position_below", 'local_treestudyplan'),
$positions = [ "above" => get_string('infofield_position_above', 'local_treestudyplan'),
"below" => get_string("infofield_position_below", 'local_treestudyplan'),
];
for ($i=1;$i<=5;$i++) {
@ -211,19 +211,19 @@ if ($hassiteconfig) {
get_string('setting_competency_displayname', 'local_treestudyplan'),
get_string('settingdesc_competency_displayname', 'local_treestudyplan'),
"idnumber",
["shortname" => get_string("name","core",),
"idnumber" => get_string("idnumber","core",),
"description" => get_string("description","core",)]
["shortname" => get_string("name", "core", ),
"idnumber" => get_string("idnumber", "core", ),
"description" => get_string("description", "core", )]
));
$page->add(new admin_setting_configselect('local_treestudyplan/competency_detailfield',
get_string('setting_competency_detailfield', 'local_treestudyplan'),
get_string('settingdesc_competency_detailfield', 'local_treestudyplan'),
"shortname",
["" => get_string("none","core",),
"shortname" => get_string("name","core",),
"idnumber" => get_string("idnumber","core",),
"description" => get_string("description","core",)]
["" => get_string("none", "core", ),
"shortname" => get_string("name", "core", ),
"idnumber" => get_string("idnumber", "core", ),
"description" => get_string("description", "core", )]
));
$page->add(new admin_setting_heading('local_treestudyplan/competency_aggregation_heading',
@ -381,7 +381,6 @@ if ($hassiteconfig) {
get_string('cfg_help', 'local_treestudyplan', null, true),
$CFG->wwwroot . '/local/treestudyplan/doc.php/index.htm'));
/**************************************
*
* Settings page: Premium registration
@ -418,7 +417,6 @@ if ($hassiteconfig) {
));
}
// Add settings page2 to the admin settings category.
$ADMIN->add('local_treestudyplan', $pagepremium);
}

View File

@ -1,11 +1,11 @@
<?php
function sitematch($key,$site){
function sitematch($key, $site) {
// Add double slashes to key and site if no scheme is set.
// Basically: if no double slashes present before any dots,shashes or @s.
if(!\preg_match_all('#^[^./@]*?//#',$key )) {
// Basically: if no double slashes present before any dots, shashes or @s.
if (!\preg_match_all('#^[^./@]*?//#', $key )) {
$key = "//".$key;
}
if(!\preg_match_all('#^[^./@]*?//#',$site)) {
if (!\preg_match_all('#^[^./@]*?//#', $site)) {
$site = "//".$site;
}
// Use parse_url() to split path and host.
@ -23,17 +23,17 @@ function sitematch($key,$site){
}
// First match the host part.
$keyparts = \array_reverse(\explode(".",$keyurl->host));
$siteparts = \array_reverse(\explode(".",$siteurl->host));
$keyparts = \array_reverse(\explode(".", $keyurl->host));
$siteparts = \array_reverse(\explode(".", $siteurl->host));
// Trim starting www from both parts, since site.domain and www.site.domain should be treated as the same.
if (($x = \array_pop($keyparts)) != "www") {\array_push($keyparts,$x);}
if (($x = \array_pop($siteparts)) != "www") {\array_push($siteparts,$x);}
if (($x = \array_pop($keyparts)) != "www") {\array_push($keyparts, $x);}
if (($x = \array_pop($siteparts)) != "www") {\array_push($siteparts, $x);}
for ($i = 0; $i < count($keyparts); $i++) {
// No match if the site does not have a part, but the key does. Unless the key part is *
if (!isset($siteparts[$i]) ) {
if($keyparts[$i] != "*") {
if ($keyparts[$i] != "*") {
return false;
} else {
$i++; //increment $i by one before break, to make sure the comparison following this loop holds.
@ -43,7 +43,7 @@ function sitematch($key,$site){
// Now do a proper case insensitive check for matching.
// Uses fnmatch to easily handle shell type wildcards.
if ( ! \fnmatch($keyparts[$i],$siteparts[$i],\FNM_CASEFOLD)) {
if ( ! \fnmatch($keyparts[$i], $siteparts[$i], \FNM_CASEFOLD)) {
return false;
}
}
@ -54,19 +54,19 @@ function sitematch($key,$site){
// If we made it here then the host part matches. Now check the path.
// If path is /*, matches all subpaths including /
$keypath = empty($keyurl->path)?"/":$keyurl->path;
$sitepath = empty($siteurl->path)?"/":$siteurl->path;
$keypath = empty($keyurl->path) ? "/" : $keyurl->path;
$sitepath = empty($siteurl->path) ? "/" : $siteurl->path;
// Trim trailing / from both paths before comparison
if (\strlen($sitepath) > 1) {
$sitepath = \rtrim($sitepath,"/");
$sitepath = \rtrim($sitepath, "/");
}
if (\strlen($keypath) > 1) {
$keypath = \rtrim($keypath,"/");
$keypath = \rtrim($keypath, "/");
}
// Do a case insensitive fnmatch on the site so wildcards are matched too.
return \fnmatch($keypath,$sitepath,\FNM_CASEFOLD);
return \fnmatch($keypath, $sitepath, \FNM_CASEFOLD);
}
$tests = [
@ -74,10 +74,10 @@ $tests = [
["*/*", "https://www.miqra.nl"],
["*", "https://clients.openedu.nl/fith"],
["clients.openedu.nl/fith", "https://clients.openedu.nl/fith/"],
["clients.openedu.nl/fith/", "https://clients.openedu.nl/fith"]
["clients.openedu.nl/fith/", "https://clients.openedu.nl/fith"],
];
foreach($tests as $test) {
[$key, $site] = $test;
print("Checking key '{$key}' on site '{$site}': " . (sitematch($key,$site)?"MATCH":"FAIL") . "\n");
print("Checking key '{$key}' on site '{$site}': " . (sitematch($key, $site)?"MATCH":"FAIL") . "\n");
}

View File

@ -29,7 +29,7 @@ require_once($CFG->libdir.'/weblib.php');
$systemcontext = context_system::instance();
$PAGE->set_url("/local/treestudyplan/view-plan.php", array());
$PAGE->set_url("/local/treestudyplan/view-plan.php", []);
require_login();
// Figure out the context (category or system, based on either category or context parameter).
@ -64,9 +64,6 @@ if ($categoryid > 0) {
$ci = new contextinfo($studyplancontext);
$contextname = $ci->pathstr();
$PAGE->set_pagelayout('base');
//$PAGE->set_context($studyplancontext);
$PAGE->set_title(get_string('view_plan', 'local_treestudyplan')." - ".$contextname);
@ -77,18 +74,18 @@ if ($studyplancontext->id > 1) {
$PAGE->navbar->add(get_string('view_plan', 'local_treestudyplan'));
// Coursecat context
$cat = \core_course_category::get($studyplancontext->instanceid,IGNORE_MISSING,true); // We checck visibility later
} else {
$cat = \core_course_category::get($studyplancontext->instanceid, IGNORE_MISSING, true); // We checck visibility later
} else {
// System context
$cat = \core_course_category::top();
}
if (!$cat->is_uservisible()) {
throw new \moodle_exception("error:cannotviewcategory","local_treestudyplan","/local/treestudyplan/view_plan.php",$contextname);
throw new \moodle_exception("error:cannotviewcategory", "local_treestudyplan", "/local/treestudyplan/view_plan.php", $contextname);
}
if(!has_capability('local/treestudyplan:viewuserreports', $studyplancontext)) {
throw new \moodle_exception("error:nostudyplanviewaccess","local_treestudyplan","/local/treestudyplan/view_plan.php",$contextname);
if (!has_capability('local/treestudyplan:viewuserreports', $studyplancontext)) {
throw new \moodle_exception("error:nostudyplanviewaccess", "local_treestudyplan", "/local/treestudyplan/view_plan.php", $contextname);
}
// Load javascripts and specific css.
@ -121,16 +118,16 @@ print $OUTPUT->header();
<div v-cloak>
<div v-if='!activestudyplan && usedcontexts' class='ml-3 mb-3 s-context-selector'>
<b-form-select text='<?php print($contextname);?>' :value="contextid" @change='switchContext'
:class="(!(usedcontexts.length))?'text-primary':''">
:class="(!(usedcontexts.length)) ? 'text-primary' : ''">
<b-form-select-option v-if='!(usedcontexts.length)' :value="contextid"
:class="'text-primary'">
<span><?php t("loading",null,"core"); ?>...</span></b-form-select-option>
<b-form-select-option v-for='ctx in usedcontexts' :key='ctx.id' :value="ctx.context_id"
<span><?php t("loading", null, "core"); ?>...</span></b-form-select-option>
<b-form-select-option v-for='ctx in usedcontexts' :key='ctx.id' :value="ctx.context_id"
:class="(ctx.studyplancount > 0) ? 'font-weight-bold' : ''"
><span v-for="(p, i) in ctx.category.path"><span v-if="i>0"> / </span>{{ p }}</span>
<span>({{ ctx.studyplancount }})</span></b-form-select-option>
</b-form-select>
<div v-if="!(usedcontexts.length)" style="position: relative; top: 0.3rem; width: 1.2rem; height: 1.2rem; font-size: 0.7rem;"
<div v-if="!(usedcontexts.length)" style="position: relative; top: 0.3rem; width: 1.2rem; height: 1.2rem; font-size: 0.7rem;"
class="spinner-border text-primary" role="status"></div>
</div>
<h3 v-else><?php print $contextname; ?></h3>
@ -147,11 +144,11 @@ print $OUTPUT->header();
:value='studyplan.id'
>{{ studyplan.name }}</b-form-select-option>
</b-form-select>&nbsp;
<s-studyplan-details
v-model="displayedstudyplan"
<s-studyplan-details
v-model="displayedstudyplan"
v-if="displayedstudyplan.description"
></s-studyplan-details>
<div class="flex-grow-1"><!-- Spacer to align student selector right --></div>
<div class="flex-grow-1"><!-- Spacer to align student selector right --></div>
<div>
<span><?php t('selectstudent_btn') ?></span>
<s-prevnext-selector