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 * @param mixed $configstr Configuration string for aggregator
* @throws ValueError If method is not found * @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)) { if (self::supported($method)) {
$agclass = self::aggregator_name($method); $agclass = self::aggregator_name($method);
return new $agclass($configstr); return new $agclass($configstr);
@ -95,7 +95,7 @@ abstract class aggregator {
* @param mixed $method Aggregation method * @param mixed $method Aggregation method
* @param mixed $configstr Configuration string for aggregator * @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 { try {
return self::create($method, $configstr); return self::create($method, $configstr);
} catch (\ValueError $x) { } catch (\ValueError $x) {
@ -190,7 +190,7 @@ abstract class aggregator {
* Determine if Aggregation method makes use of "required grades" in a course/module. * 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. * @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; return false;
} }
@ -198,11 +198,10 @@ abstract class aggregator {
* Determine if aggregation method makes use of item conditions * Determine if aggregation method makes use of item conditions
* @return bool True if aggregation method makes use of * @return bool True if aggregation method makes use of
*/ */
public function use_item_conditions(){ public function use_item_conditions() {
return false; return false;
} }
/** /**
* Return the current configuration string. * Return the current configuration string.
* @return string Configuration string * @return string Configuration string
@ -211,12 +210,11 @@ abstract class aggregator {
return ""; return "";
} }
/** /**
* Webservice structure for basic aggregator info * Webservice structure for basic aggregator info
* @param int $value Webservice requirement constant * @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([ return new \external_single_structure([
"useRequiredGrades" => new \external_value(PARAM_BOOL, 'id of studyplan'), "useRequiredGrades" => new \external_value(PARAM_BOOL, 'id of studyplan'),
"useItemConditions" => new \external_value(PARAM_BOOL, 'name of studyplan'), "useItemConditions" => new \external_value(PARAM_BOOL, 'name of studyplan'),
@ -239,7 +237,7 @@ abstract class aggregator {
* @param int $value Webservice requirement constant * @param int $value Webservice requirement constant
* @return mixed Webservice output structure * @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([ return new \external_multiple_structure(new \external_single_structure([
"id" => new \external_value(PARAM_TEXT, 'id of aggregator'), "id" => new \external_value(PARAM_TEXT, 'id of aggregator'),
"name" => new \external_value(PARAM_TEXT, 'name of agregator'), "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 * 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([ return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'user id'), "id" => new \external_value(PARAM_INT, 'user id'),
"username" => new \external_value(PARAM_TEXT, 'username'), "username" => new \external_value(PARAM_TEXT, 'username'),
@ -80,7 +80,7 @@ class associationservice extends \external_api {
/** /**
* Webservice structure to use in describing a cohort * 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([ return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'cohort id'), "id" => new \external_value(PARAM_INT, 'cohort id'),
"name" => new \external_value(PARAM_TEXT, 'name'), "name" => new \external_value(PARAM_TEXT, 'name'),
@ -124,14 +124,14 @@ class associationservice extends \external_api {
"shortpath" => array_map(function($c) { "shortpath" => array_map(function($c) {
return \context::instance_by_id($c)->get_context_name(false, true); return \context::instance_by_id($c)->get_context_name(false, true);
}, $ctxpath), }, $ctxpath),
] ],
]; ];
return $result; return $result;
} }
public static function user_lastaccess($userid,$studyplanid=null) { public static function user_lastaccess($userid, $studyplanid=null) {
global $DB; global $DB;
if (!empty($studyplanid)) { if (!empty($studyplanid)) {
$lasql = "SELECT MAX(a.timeaccess) FROM {user_lastaccess} a $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_line} l ON l.id = i.line_id
INNER JOIN {local_treestudyplan_page} p ON l.page_id = p.id INNER JOIN {local_treestudyplan_page} p ON l.page_id = p.id
WHERE a.userid = :userid AND p.studyplan_id = :studyplanid"; 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 { } else {
$lasql = "SELECT MAX(a.timeaccess) FROM {user_lastaccess} a $lasql = "SELECT MAX(a.timeaccess) FROM {user_lastaccess} a
WHERE a.userid = :userid"; WHERE a.userid = :userid";
$lastaccess = $DB->get_field_sql($lasql,["userid" => $userid]); $lastaccess = $DB->get_field_sql($lasql, ["userid" => $userid]);
} }
return $lastaccess; return $lastaccess;
} }
/** /**
* Parameter description for webservice function list_cohort * 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( [ return new \external_function_parameters( [
'like' => new \external_value(PARAM_TEXT, 'search text'), 'like' => new \external_value(PARAM_TEXT, 'search text'),
'studyplan_id' => new \external_value(PARAM_INT, 'id of studyplan to list for'), '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 * 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()); return new \external_multiple_structure(self::cohort_structure());
} }
/** /**
* Search cohorts for matching string * Search cohorts for matching string
* @param string $like String to match cohorts with * @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 * @return array
*/ */
public static function list_cohort($like, $studyplan_id) { public static function list_cohort($like, $studyplanid) {
global $CFG, $DB; global $CFG, $DB;
// Only allow this if the user has the right to edit in this context. // 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(); $context = $studyplan->context();
webservicehelper::require_capabilities(self::CAP_EDIT, $context); webservicehelper::require_capabilities(self::CAP_EDIT, $context);
$pattern = "%{$like}%"; $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 $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) 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)"; AND (j.studyplan_id IS NULL OR j.studyplan_id != :exclude_id)";
$params['exclude_id'] = $studyplan_id; $params['exclude_id'] = $studyplanid;
$cohorts = []; $cohorts = [];
$rs = $DB->get_recordset_sql($sql, $params); $rs = $DB->get_recordset_sql($sql, $params);
@ -203,7 +201,7 @@ class associationservice extends \external_api {
/** /**
* Parameter description for webservice function find_user * 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( [ return new \external_function_parameters( [
'like' => new \external_value(PARAM_TEXT, 'search text'), 'like' => new \external_value(PARAM_TEXT, 'search text'),
'studyplan_id' => new \external_value(PARAM_INT, 'id of studyplan to list for'), '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 * 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()); 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) * @param int $contextid Context to search (default system)
* @return array * @return array
*/ */
public static function find_user($like, $studyplan_id) { public static function find_user($like, $studyplanid) {
global $CFG, $DB; global $CFG, $DB;
// Only allow this if the user has the right to edit in this context. // 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(); $context = $studyplan->context();
webservicehelper::require_capabilities(self::CAP_EDIT, $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 $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) 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)"; AND (j.studyplan_id IS NULL OR j.studyplan_id != :exclude_id)";
$params['exclude_id'] = $studyplan_id; $params['exclude_id'] = $studyplanid;
$users = []; $users = [];
$rs = $DB->get_recordset_sql($sql, $params); $rs = $DB->get_recordset_sql($sql, $params);
@ -256,7 +254,7 @@ class associationservice extends \external_api {
/** /**
* Parameter description for webservice function connect_cohort * 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( [ return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL), "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), "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 * 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([ return new \external_single_structure([
"success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'), "success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'),
"msg" => new \external_value(PARAM_TEXT, 'message'), "msg" => new \external_value(PARAM_TEXT, 'message'),
@ -303,7 +301,7 @@ class associationservice extends \external_api {
/** /**
* Parameter description for webservice function disconnect_cohort * 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( [ return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL), "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), "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 * 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([ return new \external_single_structure([
"success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'), "success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'),
"msg" => new \external_value(PARAM_TEXT, 'message'), "msg" => new \external_value(PARAM_TEXT, 'message'),
@ -350,7 +348,7 @@ class associationservice extends \external_api {
/** /**
* Parameter description for webservice function connect_user * 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( [ return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL), "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), "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 * 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([ return new \external_single_structure([
"success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'), "success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'),
"msg" => new \external_value(PARAM_TEXT, 'message'), "msg" => new \external_value(PARAM_TEXT, 'message'),
@ -396,7 +394,7 @@ class associationservice extends \external_api {
/** /**
* Parameter description for webservice function disconnect_user * 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( [ return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL), "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), "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 * 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([ return new \external_single_structure([
"success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'), "success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'),
"msg" => new \external_value(PARAM_TEXT, 'message'), "msg" => new \external_value(PARAM_TEXT, 'message'),
@ -441,7 +439,7 @@ class associationservice extends \external_api {
/** /**
* Parameter description for webservice function associated_users * 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( [ return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL), "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 * 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()); return new \external_multiple_structure(self::user_structure());
} }
@ -481,7 +479,7 @@ class associationservice extends \external_api {
$users = []; $users = [];
foreach ($rs as $u) { foreach ($rs as $u) {
$user = self::make_user_model($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; $users[] = $user;
} }
@ -493,7 +491,7 @@ class associationservice extends \external_api {
/** /**
* Parameter description for webservice function associated_cohorts * 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( [ return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL), "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 * 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()); return new \external_multiple_structure(self::cohort_structure());
} }
@ -530,7 +528,7 @@ class associationservice extends \external_api {
/** /**
* Parameter description for webservice function all_associated * 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( [ return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL), "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 * 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()); return new \external_multiple_structure(self::user_structure());
} }
@ -577,10 +575,10 @@ class associationservice extends \external_api {
return $users; return $users;
} }
/** /**
* Parameter description for webservice function all_associated * 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( [ return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL), "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 * 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([ return new \external_multiple_structure(new \external_single_structure([
'id' => new \external_value(PARAM_INT, 'id of group'), '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()), 'users' => new \external_multiple_structure(self::user_structure()),
])); ]));
} }
@ -615,9 +613,9 @@ class associationservice extends \external_api {
$userlist = [ $userlist = [
[ [
'id' => 0, 'id' => 0,
'label' => get_string("individuals",'local_treestudyplan'), 'label' => get_string("individuals", 'local_treestudyplan'),
'users' => self::associated_users($studyplanid), 'users' => self::associated_users($studyplanid),
] ],
]; ];
$sql = "SELECT DISTINCT c.* FROM {cohort} c INNER JOIN {local_treestudyplan_cohort} j ON j.cohort_id = c.id $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) { foreach ($rs as $u) {
$user = self::make_user_model($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; $users[] = $user;
} }
$rs->close(); $rs->close();
@ -650,7 +648,6 @@ class associationservice extends \external_api {
return $userlist; return $userlist;
} }
/** /**
* Sort a list of user models by firstname->lastname * Sort a list of user models by firstname->lastname
* @param array $list Reference to list of user models * @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 * 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( [ return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL), "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 * 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(); return success::structure();
} }
@ -705,11 +702,10 @@ class associationservice extends \external_api {
} }
/**
/**
* Parameter description for webservice function connect_user * 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( [ return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL), "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), "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 * 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([ return new \external_single_structure([
"success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'), "success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'),
"msg" => new \external_value(PARAM_TEXT, 'message'), "msg" => new \external_value(PARAM_TEXT, 'message'),
@ -738,8 +734,8 @@ class associationservice extends \external_api {
$studyplan = studyplan::find_by_id($studyplanid); $studyplan = studyplan::find_by_id($studyplanid);
webservicehelper::require_capabilities(self::CAP_EDIT, $studyplan->context()); webservicehelper::require_capabilities(self::CAP_EDIT, $studyplan->context());
$user = $DB->get_record("user",["id" => $userid]); $user = $DB->get_record("user", ["id" => $userid]);
if( has_capability(self::CAP_COACH,$studyplan->context(),$user)) { if ( has_capability(self::CAP_COACH, $studyplan->context(), $user)) {
if (!$DB->record_exists('local_treestudyplan_coach', ['studyplan_id' => $studyplanid, 'user_id' => $userid])) { if (!$DB->record_exists('local_treestudyplan_coach', ['studyplan_id' => $studyplanid, 'user_id' => $userid])) {
$id = $DB->insert_record('local_treestudyplan_coach', [ $id = $DB->insert_record('local_treestudyplan_coach', [
'studyplan_id' => $studyplanid, 'studyplan_id' => $studyplanid,
@ -759,7 +755,7 @@ class associationservice extends \external_api {
/** /**
* Parameter description for webservice function disconnect_user * 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( [ return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL), "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), "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 * 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([ return new \external_single_structure([
"success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'), "success" => new \external_value(PARAM_BOOL, 'operation completed succesfully'),
"msg" => new \external_value(PARAM_TEXT, 'message'), "msg" => new \external_value(PARAM_TEXT, 'message'),
@ -793,18 +789,16 @@ class associationservice extends \external_api {
'user_id' => $userid, 'user_id' => $userid,
]); ]);
return ['success' => true, 'msg' => 'User Disconnected as coach']; return ['success' => true, 'msg' => 'User Disconnected as coach'];
} else { } else {
return ['success' => true, 'msg' => 'Connection does not exist']; return ['success' => true, 'msg' => 'Connection does not exist'];
} }
} }
/** /**
* Parameter description for webservice function find_user * 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( [ return new \external_function_parameters( [
'like' => new \external_value(PARAM_TEXT, 'search text'), 'like' => new \external_value(PARAM_TEXT, 'search text'),
'studyplan_id' => new \external_value(PARAM_INT, 'studyplan id to associate for', VALUE_OPTIONAL), '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 * 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()); 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) * @param int $contextid Context to search (default system)
* @return array * @return array
*/ */
public static function find_coach($like, $studyplan_id) { public static function find_coach($like, $studyplanid) {
global $CFG, $DB; global $CFG, $DB;
// Only allow this if the user has the right to edit in this context. // 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(); $context = $studyplan->context();
webservicehelper::require_capabilities(self::CAP_EDIT, $context); webservicehelper::require_capabilities(self::CAP_EDIT, $context);
@ -849,7 +842,7 @@ class associationservice extends \external_api {
$users = []; $users = [];
$rs = $DB->get_recordset_sql($sql, $params); $rs = $DB->get_recordset_sql($sql, $params);
foreach ($rs as $r) { 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); $users[] = static::make_user_model($r);
} }
} }
@ -861,7 +854,7 @@ class associationservice extends \external_api {
/** /**
* Parameter description for webservice function associated_users * 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( [ return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'id of studyplan', VALUE_OPTIONAL), "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 * 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()); return new \external_multiple_structure(self::user_structure());
} }

View File

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

View File

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

View File

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

View File

@ -75,7 +75,7 @@ class completion {
* Webservice structure for basic info * Webservice structure for basic info
* @param int $value Webservice requirement constant * @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, return new \external_value( PARAM_TEXT,
'completion state (failed|incomplete|pending|progress|completed|good|excellent)', 'completion state (failed|incomplete|pending|progress|completed|good|excellent)',
$value); $value);

View File

@ -69,7 +69,7 @@ class completionscanner {
* Check if a certain activity type is supported for scanning pending results * Check if a certain activity type is supported for scanning pending results
* @param string $mod name of activity module * @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)) { if (!array_key_exists($mod, self::$modsupported)) {
self::$modsupported[$mod] = class_exists("\local_treestudyplan\\local\\ungradedscanners\\{$mod}_scanner"); 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 * @param int[] $studentlist Array of student id's
* @return int[] * @return int[]
*/ */
private function filter_studentlist(array $studentlist) : array { private function filter_studentlist(array $studentlist): array {
$coursestudents = courseinfo::get_course_students($this->courseid); $coursestudents = courseinfo::get_course_students($this->courseid);
return array_intersect($studentlist, $coursestudents); 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 * Check if the criteria this scanner scans has pending submissions for a specific user
* @param int $userid ID of the user to check for * @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 (!array_key_exists($userid, $this->pendingcache)) {
if ($this->scanner === null) { if ($this->scanner === null) {
$this->pendingcache[$userid] = false; $this->pendingcache[$userid] = false;
@ -145,7 +145,7 @@ class completionscanner {
* Webservice structure for basic info * Webservice structure for basic info
* @param int $value Webservice requirement constant * @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([ return new \external_single_structure([
"ungraded" => new \external_value(PARAM_INT, 'number of ungraded submissions'), "ungraded" => new \external_value(PARAM_INT, 'number of ungraded submissions'),
"completed" => new \external_value(PARAM_INT, 'number of completed students'), "completed" => new \external_value(PARAM_INT, 'number of completed students'),
@ -159,7 +159,7 @@ class completionscanner {
* Webservice model for basic info * Webservice model for basic info
* @param int[]|null $studentlist Array of student userids to use for checking. Leave empty to use all course students * @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), 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 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 * Describe the result for the webservice model
* @param int $value Webservice requirement constant * @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([ return new \external_single_structure([
"name" => new \external_value(PARAM_TEXT, 'context name'), "name" => new \external_value(PARAM_TEXT, 'context name'),
"shortname" => new \external_value(PARAM_TEXT, 'context short name'), "shortname" => new \external_value(PARAM_TEXT, 'context short name'),
@ -61,7 +61,6 @@ class contextinfo {
*/ */
public function model() { public function model() {
return [ return [
"name" => $this->context->get_context_name(false, false), "name" => $this->context->get_context_name(false, false),
"shortname" => $this->context->get_context_name(false, true), "shortname" => $this->context->get_context_name(false, true),
@ -75,7 +74,7 @@ class contextinfo {
* @param $short Use short names of contexts in path * @param $short Use short names of contexts in path
* @return array of context path names * @return array of context path names
*/ */
public function path($short=false){ public function path($short=false) {
if ($short) { if ($short) {
return array_map(function($c) { return array_map(function($c) {
return \context::instance_by_id($c)->get_context_name(false, true); 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 * @param $short Use short names of contexts in path
* @return string Concatenated string of paths * @return string Concatenated string of paths
*/ */
public function pathstr($short=false){ public function pathstr($short=false) {
return implode(" / ", $this->path($short)); return implode(" / ", $this->path($short));
} }
/** /**
* Make new Contextinfo for context id * Make new Contextinfo for context id
* @param int $contextid Context id * @param int $contextid Context id

View File

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

View File

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

View File

@ -114,7 +114,7 @@ class courseinfo {
* Check if current user is teacher in this course * Check if current user is teacher in this course
* @return book * @return book
*/ */
protected function am_teacher() : bool { protected function am_teacher(): bool {
global $USER; global $USER;
return is_enrolled($this->coursecontext, $USER, 'mod/assign:grade'); return is_enrolled($this->coursecontext, $USER, 'mod/assign:grade');
} }
@ -246,7 +246,7 @@ class courseinfo {
* Webservice structure for basic info * Webservice structure for basic info
* @param int $value Webservice requirement constant * @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([ return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'linked course id'), "id" => new \external_value(PARAM_INT, 'linked course id'),
"fullname" => new \external_value(PARAM_TEXT, 'linked course name'), "fullname" => new \external_value(PARAM_TEXT, 'linked course name'),
@ -277,7 +277,7 @@ class courseinfo {
* Webservice structure for editor info * Webservice structure for editor info
* @param int $value Webservice requirement constant * @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([ return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'linked course id'), "id" => new \external_value(PARAM_INT, 'linked course id'),
"fullname" => new \external_value(PARAM_TEXT, 'linked course name'), "fullname" => new \external_value(PARAM_TEXT, 'linked course name'),
@ -343,7 +343,7 @@ class courseinfo {
foreach ($gradables as $gradable) { foreach ($gradables as $gradable) {
$info['grades'][] = $gradable->editor_model($this->studyitem); $info['grades'][] = $gradable->editor_model($this->studyitem);
} }
} }
if ($aggregator->use_corecompletioninfo()) { if ($aggregator->use_corecompletioninfo()) {
$cc = new corecompletioninfo($this->course, $this->studyitem); $cc = new corecompletioninfo($this->course, $this->studyitem);
$studentlist = $this->studyitem->studyline()->studyplan()->find_linked_userids(); $studentlist = $this->studyitem->studyline()->studyplan()->find_linked_userids();
@ -353,7 +353,7 @@ class courseinfo {
$ci = new coursecompetencyinfo($this->course, $this->studyitem); $ci = new coursecompetencyinfo($this->course, $this->studyitem);
$studentlist = $this->studyitem->studyline()->studyplan()->find_linked_userids(); $studentlist = $this->studyitem->studyline()->studyplan()->find_linked_userids();
$info['competency'] = $ci->editor_model($studentlist); $info['competency'] = $ci->editor_model($studentlist);
} }
} }
return $info; return $info;
} }
@ -362,7 +362,7 @@ class courseinfo {
* Webservice structure for userinfo * Webservice structure for userinfo
* @param int $value Webservice requirement constant * @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([ return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'linked course id'), "id" => new \external_value(PARAM_INT, 'linked course id'),
"fullname" => new \external_value(PARAM_TEXT, 'linked course name'), "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 * @param int $courseid Course id of the course to check
* @return int[] Array if user ids * @return int[] Array if user ids
*/ */
public static function get_course_students($courseid) : array { public static function get_course_students($courseid): array {
global $CFG; global $CFG;
if (!array_key_exists($courseid, self::$coursestudents)) { if (!array_key_exists($courseid, self::$coursestudents)) {
$students = []; $students = [];
@ -406,9 +406,9 @@ class courseinfo {
* (Has a gradebook role) * (Has a gradebook role)
* @param int $userid The user Id to check * @param int $userid The user Id to check
*/ */
public function is_enrolled_student($userid) : bool { public function is_enrolled_student($userid): bool {
global $CFG; global $CFG;
foreach (explode(',', $CFG->gradebookroles) as $roleid) { foreach (explode(', ', $CFG->gradebookroles) as $roleid) {
if (user_has_role_assignment($userid, $roleid, $this->coursecontext->id)) { if (user_has_role_assignment($userid, $roleid, $this->coursecontext->id)) {
return true; return true;
} }
@ -455,10 +455,9 @@ class courseinfo {
'grades' => [], 'grades' => [],
'enrolled' => $this->is_enrolled_student($userid), 'enrolled' => $this->is_enrolled_student($userid),
'extrafields' => $this->extrafields_model(), 'extrafields' => $this->extrafields_model(),
'showprogressbar' => get_config("local_treestudyplan","courseprogressbar"), 'showprogressbar' => get_config("local_treestudyplan", "courseprogressbar"),
]; ];
if (isset($this->studyitem)) { if (isset($this->studyitem)) {
$aggregator = $this->studyitem->studyline()->studyplan()->aggregator(); $aggregator = $this->studyitem->studyline()->studyplan()->aggregator();
@ -467,7 +466,7 @@ class courseinfo {
foreach ($gradables as $gi) { foreach ($gradables as $gi) {
$info['grades'][] = $gi->user_model($userid); $info['grades'][] = $gi->user_model($userid);
} }
} }
if ($aggregator->use_corecompletioninfo()) { if ($aggregator->use_corecompletioninfo()) {
$cc = new corecompletioninfo($this->course, $this->studyitem); $cc = new corecompletioninfo($this->course, $this->studyitem);
$info['completion'] = $cc->user_model($userid); $info['completion'] = $cc->user_model($userid);
@ -475,24 +474,23 @@ class courseinfo {
if ($aggregator->use_coursecompetencies()) { if ($aggregator->use_coursecompetencies()) {
$ci = new coursecompetencyinfo($this->course, $this->studyitem); $ci = new coursecompetencyinfo($this->course, $this->studyitem);
$info['competency'] = $ci->user_model($userid); $info['competency'] = $ci->user_model($userid);
} }
} }
return $info; return $info;
} }
/** /**
* Webservice structure for extra fields * Webservice structure for extra fields
* @param int $value Webservice requirement constant * @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([ return new \external_multiple_structure(new \external_single_structure([
"title" => new \external_value(PARAM_RAW, 'title'), "title" => new \external_value(PARAM_RAW, 'title'),
"value" => new \external_value(PARAM_RAW, 'value'), "value" => new \external_value(PARAM_RAW, 'value'),
"position" => new \external_value(PARAM_TEXT, 'position'), "position" => new \external_value(PARAM_TEXT, 'position'),
"type" => new \external_value(PARAM_TEXT, 'value type'), "type" => new \external_value(PARAM_TEXT, 'value type'),
"fieldname" => new \external_value(PARAM_TEXT, 'field name'), "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'), "courseid" => new \external_value(PARAM_TEXT, 'course id number'),
], 'referenced course information'), $value); ], 'referenced course information'), $value);
} }
@ -505,11 +503,11 @@ class courseinfo {
public function extrafields_model($includeteachervisible=false) { public function extrafields_model($includeteachervisible=false) {
$list = []; $list = [];
for ($i=1; $i <= 5; $i++) { for ($i=1; $i <= 5; $i++) {
$field = get_config('local_treestudyplan','courseinfo'.$i.'_field'); $field = get_config('local_treestudyplan', 'courseinfo'.$i.'_field');
if ($field) { if ($field) {
$title = self::extrafields_localize_title(get_config('local_treestudyplan','courseinfo'.$i.'_title')); $title = self::extrafields_localize_title(get_config('local_treestudyplan', 'courseinfo'.$i.'_title'));
$pos = get_config('local_treestudyplan','courseinfo'.$i.'_position'); $pos = get_config('local_treestudyplan', 'courseinfo'.$i.'_position');
[$value,$type, $raw] = $this->extrafields_value($field,$includeteachervisible); [$value, $type, $raw] = $this->extrafields_value($field, $includeteachervisible);
if ($type) { if ($type) {
$list[] = [ $list[] = [
"title" => $title, "title" => $title,
@ -518,7 +516,7 @@ class courseinfo {
"type" => $type, "type" => $type,
"fieldname" => $field, "fieldname" => $field,
"courseid" => $this->course->id, "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) { protected static function extrafields_localize_title($field) {
$lang = trim(current_language()); $lang = trim(current_language());
$lines = explode("\n",$field); $lines = explode("\n", $field);
$title = ""; $title = "";
$fallback = ""; // Fallback to first title $fallback = ""; // Fallback to first title
foreach ($lines as $l) { foreach ($lines as $l) {
$parts = explode("|",$l,2); $parts = explode("|", $l, 2);
if (count($parts) > 0) { if (count($parts) > 0) {
// Set the first line as fallback. // Set the first line as fallback.
if (empty($firsttitle) && !empty($parts[0])) { if (empty($firsttitle) && !empty($parts[0])) {
@ -543,7 +541,7 @@ class courseinfo {
$title = trim($parts[0]); $title = trim($parts[0]);
} else if (trim($parts[1]) == $lang) { } else if (trim($parts[1]) == $lang) {
return trim($parts[0]); return trim($parts[0]);
} }
} }
} }
@ -553,9 +551,9 @@ class courseinfo {
/** /**
* Determine value and type of an extra field for this course * 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; global $PAGE;
if ($fieldname == "description") { if ($fieldname == "description") {
// Process embedded files. // Process embedded files.
@ -580,7 +578,7 @@ class courseinfo {
$contacts = $cle->get_course_contacts(); $contacts = $cle->get_course_contacts();
$value = ""; $value = "";
foreach ($contacts as $uid => $contact) { foreach ($contacts as $uid => $contact) {
if(strlen($value) > 0) { if (strlen($value) > 0) {
$value .= ", "; $value .= ", ";
} }
$value .= $contact["username"]; $value .= $contact["username"];
@ -610,7 +608,7 @@ class courseinfo {
$value = ""; $value = "";
} else { } else {
// Convert to YYYY-MM-DD format. // Convert to YYYY-MM-DD format.
$value = date("Y-m-d", $raw); $value = date("Y-m-d", $raw);
} }
} else { } else {
// Everything else can just use the export value. // Everything else can just use the export value.
@ -618,12 +616,12 @@ class courseinfo {
$value = $data->export_value(); $value = $data->export_value();
} }
return [$value,$type,$raw]; return [$value, $type, $raw];
} }
} }
} }
} }
// Fallback to empty if finding a match fails. // 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"; const CAP_VIEW = "local/treestudyplan:viewuserreports";
/** /**
* Get the topmost categories for the specicied user. * 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. * 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 * @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; global $DB, $USER;
if ($userid == null) { if ($userid == null) {
$userid = $USER->id; $userid = $USER->id;
} }
$tops = []; $tops = [];
if (has_capability($capability,\context_system::instance(),$userid)) { if (has_capability($capability, \context_system::instance(), $userid)) {
if ($capability == 'moodle/category:viewcourselist') { if ($capability == 'moodle/category:viewcourselist') {
// We are now just looking for the visible main level categories. // We are now just looking for the visible main level categories.
// Add all categories of depth = 1; // 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) { foreach( $rs as $rcat) {
// Get the category, and double check if the category is visible to the current user. // 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. // 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); $cat = \core_course_category::get($rcat->id, \IGNORE_MISSING, false, $userid);
if ($cat !== null) { if ($cat !== null) {
// Register the category. // Register the category.
array_push($tops,$cat); array_push($tops, $cat);
} }
} }
$rs->close(); $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. // Use recordset to handle the eventuality of a really big and complex moodle setup.
$recordset = $DB->get_records_sql($sql, ["userid" => $userid, "capability" => $capability, $recordset = $DB->get_records_sql($sql, ["userid" => $userid, "capability" => $capability,
"ctxl_coursecat" => \CONTEXT_COURSECAT,]); "ctxl_coursecat" => \CONTEXT_COURSECAT ]);
$params = ["userid" => $userid, "capability" => $capability, $params = ["userid" => $userid, "capability" => $capability,
"ctxl_coursecat" => \CONTEXT_COURSECAT,]; "ctxl_coursecat" => \CONTEXT_COURSECAT ];
$contextids = []; $contextids = [];
foreach ($recordset as $r) { foreach ($recordset as $r) {
// Get the paths as an array. // Get the paths as an array.
$parents = explode("/",$r->path); $parents = explode("/", $r->path);
// Strip the first item, since it is an empty one. // Strip the first item, since it is an empty one.
array_shift($parents); array_shift($parents);
// Strip the last item, since it refers to self. // Strip the last item, since it refers to self.
array_pop($parents); array_pop($parents);
// Figure out if any of the remaining parent contexts are already contexts with permission. // 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) { if (count($intersect) == 0) {
// Double check permissions according to the moodle capability system. // Double check permissions according to the moodle capability system.
$ctx = \context::instance_by_id($r->id); $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. // 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. // 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); $cat = \core_course_category::get($r->instanceid, \IGNORE_MISSING, false, $userid);
if ($cat !== null) { if ($cat !== null) {
// Register the context id in the list now, since we know the category is really visible. // 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. // Register the category.
array_push($tops,$cat); array_push($tops, $cat);
} else { } else {
// The category is not visible. Add the first known visible subcategories. // 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) { foreach ($children as $cat) {
array_push($tops,$cat); array_push($tops, $cat);
} }
} }
} }
} }
} }
//$recordset->close(); //$recordset->close();
} }
return $tops; return $tops;
@ -142,7 +141,7 @@ class courseservice extends \external_api {
/** /**
* Find the top-most child categories for a given category that are visible. * Find the top-most child categories for a given category that are visible.
* *
* @param int $parentid The category to search for * @param int $parentid The category to search for
* @return array of \core_course_category * @return array of \core_course_category
*/ */
@ -151,7 +150,7 @@ class courseservice extends \external_api {
$capability = 'moodle/category:viewcourselist'; $capability = 'moodle/category:viewcourselist';
$tops = []; $tops = [];
$path_like = $DB->sql_like('ctx.path',':pathsearch'); $pathlike = $DB->sql_like('ctx.path', ':pathsearch');
$sql = "SELECT UNIQUE ctx.* FROM {context} AS ctx $sql = "SELECT UNIQUE ctx.* FROM {context} AS ctx
INNER JOIN {role_assignments} AS ra ON ra.contextid = ctx.id 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 LEFT JOIN {course_categories} AS cat ON ctx.instanceid = cat.id
WHERE ( ctx.contextlevel = :ctxl_coursecat ) WHERE ( ctx.contextlevel = :ctxl_coursecat )
AND ra.userid = :userid AND rc.capability = :capability AND ra.userid = :userid AND rc.capability = :capability
AND {$path_like} AND {$pathlike}
ORDER BY ctx.depth ASC, cat.sortorder ASC"; ORDER BY ctx.depth ASC, cat.sortorder ASC";
// Use recordset to handle the eventuality of a really big and complex moodle setup. // 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, "capability" => $capability,
"ctxl_coursecat" => \CONTEXT_COURSECAT, "ctxl_coursecat" => \CONTEXT_COURSECAT,
"pathsearch" => "%/{$parentid}/%", "pathsearch" => "%/{$parentid}/%",
]); ]);
$contextids = []; $contextids = [];
foreach ($recordset as $r) { foreach ($recordset as $r) {
// Get the paths as an array. // Get the paths as an array.
$parents = explode("/",$r->path); $parents = explode("/", $r->path);
// Strip the first item, since it is an empty one. // Strip the first item, since it is an empty one.
array_shift($parents); array_shift($parents);
// Strip the last item, since it refers to self. // Strip the last item, since it refers to self.
array_pop($parents); array_pop($parents);
// Figure out if any of the remaining parent contexts are already contexts with permission. // 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) { if (count($intersect) == 0) {
// Double check permissions according to the moodle capability system. // Double check permissions according to the moodle capability system.
$ctx = \context::instance_by_id($r->id); $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. // 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. // 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); $cat = \core_course_category::get($r->instanceid, \IGNORE_MISSING, false, $userid);
if ($cat !== null) { if ($cat !== null) {
// Register the context id in the list now, since we know the category is really visible. // 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. // Register the category.
array_push($tops,$cat); array_push($tops, $cat);
} }
} }
} }
} }
$recordset->close(); $recordset->close();
return $tops; return $tops;
} }
/** /**
* Return value description for map_categories function * 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( [ return new \external_function_parameters( [
"studyplan_id" => new \external_value(PARAM_INT, 'ID of studyplan to map the categories for', VALUE_DEFAULT), "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 * 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)); 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) { public static function map_categories($studyplanid = 0) {
global $USER; global $USER;
// Determine top categories from provided context. // Determine top categories from provided context.
if ($studyplanid == 0) { 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. // This uses a custom function, since moodle's "core_course_category::user_top()" is somewhat deficient.
$children = self::user_tops(); $children = self::user_tops();
if (count($children) == 0) { if (count($children) == 0) {
throw new moodle_exception("error:nocategoriesvisible","local_treestudyplan"); throw new moodle_exception("error:nocategoriesvisible", "local_treestudyplan");
} }
} else { } 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); $studyplan = studyplan::find_by_id($studyplanid);
$context = $studyplan->context(); $context = $studyplan->context();
if ($context->contextlevel == \CONTEXT_SYSTEM) { if ($context->contextlevel == \CONTEXT_SYSTEM) {
$children = self::user_tops(); $children = self::user_tops();
} else if ($context->contextlevel == \CONTEXT_COURSECAT) { } else if ($context->contextlevel == \CONTEXT_COURSECAT) {
$cat = \core_course_category::get($context->instanceid,\MUST_EXIST,true); $cat = \core_course_category::get($context->instanceid, \MUST_EXIST, true);
if ($cat->is_uservisible()) { if ($cat->is_uservisible()) {
$children = [$cat]; $children = [$cat];
} else { } else {
$ci = new contextinfo($context); $ci = new contextinfo($context);
$contextname = $ci->pathstr(); $contextname = $ci->pathstr();
throw new moodle_exception("error:cannotviewcategory","local_treestudyplan",'',$contextname); throw new moodle_exception("error:cannotviewcategory", "local_treestudyplan", '', $contextname);
} }
} else { } else {
$children = []; $children = [];
@ -278,7 +275,7 @@ class courseservice extends \external_api {
} else { } else {
$children = self::user_tops(); $children = self::user_tops();
if (count($children) == 0) { 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 * 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( [ return new \external_function_parameters( [
"id" => new \external_value(PARAM_INT, 'id of category'), "id" => new \external_value(PARAM_INT, 'id of category'),
] ); ] );
@ -302,7 +299,7 @@ class courseservice extends \external_api {
/** /**
* Parameter description for get_category function * 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); return static::map_category_structure(false);
} }
@ -362,8 +359,8 @@ class courseservice extends \external_api {
global $USER; global $USER;
// List the categories in which the user has a specific capability. // List the categories in which the user has a specific capability.
$list = []; $list = [];
$parents = self::user_tops($USER->id,$capability); $parents = self::user_tops($USER->id, $capability);
array_merge($list,$parents); array_merge($list, $parents);
foreach ($parents as $parent) { foreach ($parents as $parent) {
// For optimization purposes, we include all its children now, since they will have inherited the permission. // 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 * 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( [ return new \external_function_parameters( [
"operation" => new \external_value(PARAM_TEXT, 'type of operation ["view"|"edit"]', VALUE_DEFAULT), "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), "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 * 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)); return new \external_multiple_structure(static::map_category_structure(true));
} }
@ -421,10 +418,10 @@ class courseservice extends \external_api {
} else { // Operation == "view" || default. } else { // Operation == "view" || default.
$capability = self::CAP_VIEW; $capability = self::CAP_VIEW;
} }
// Get the context ids of all categories the user has access to view and wich have the given permission. // Get the context ids of all categories the user has access to view and wich have the given permission.
$contextids = []; $contextids = [];
$tops = self::user_tops(null,$capability); $tops = self::user_tops(null, $capability);
foreach ($tops as $cat) { foreach ($tops as $cat) {
$ctx = \context_coursecat::instance($cat->id); $ctx = \context_coursecat::instance($cat->id);
$contextids[] = $ctx->id; $contextids[] = $ctx->id;
@ -440,7 +437,7 @@ class courseservice extends \external_api {
$contextcounts[$r->context_id] = $r->num; $contextcounts[$r->context_id] = $r->num;
// Add any of the categories containing studyplans to the list. // Add any of the categories containing studyplans to the list.
$ctx = \context::instance_by_id($r->context_id); $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; $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 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)) { if ($refctxid > 1 && !in_array($refctxid, $contextids)) {
try { try {
// Get the context. // Get the context.
$refctx = \context::instance_by_id($refctxid); $refctx = \context::instance_by_id($refctxid);
// Double check permissions. // Double check permissions.
if (has_capability($capability,$refctx)) { if (has_capability($capability, $refctx)) {
$insertctxs[] = $refctx; $insertctxs[] = $refctx;
} }
} catch(\dml_missing_record_exception $x) { } catch(\dml_missing_record_exception $x) {
@ -468,12 +465,12 @@ class courseservice extends \external_api {
$ipath = $ictx->get_parent_context_ids(true); $ipath = $ictx->get_parent_context_ids(true);
$found = false; $found = false;
foreach ($ipath as $i => $pid) { foreach ($ipath as $i => $pid) {
$idx = array_search($pid,$contextids); $idx = array_search($pid, $contextids);
if($idx !== false) { if ($idx !== false) {
$contextids = array_merge( $contextids = array_merge(
array_slice($contextids, 0, $idx+1), 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) array_slice($contextids, $idx+1, count($contextids) - 1)
) ; ) ;
@ -481,12 +478,11 @@ class courseservice extends \external_api {
break; break;
} }
} }
if(!$found) { if (!$found) {
array_unshift($contextids,$ictx->id); array_unshift($contextids, $ictx->id);
} }
} }
// Now translate this to the list of categories. // Now translate this to the list of categories.
foreach ($contextids as $ctxid ) { foreach ($contextids as $ctxid ) {
try { try {
@ -494,7 +490,7 @@ class courseservice extends \external_api {
if ($ctx->contextlevel == CONTEXT_SYSTEM) { if ($ctx->contextlevel == CONTEXT_SYSTEM) {
$cat = \core_course_category::top(); $cat = \core_course_category::top();
} else if ($ctx->contextlevel == CONTEXT_COURSECAT) { } 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; $cats[] = $cat;
// In edit mode, also include direct children of the currently selected context. // 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. // Include direct children for navigation purposes.
foreach ($cat->get_children() as $ccat) { foreach ($cat->get_children() as $ccat) {
$ccatctx = \context_coursecat::instance($ccat->id); $ccatctx = \context_coursecat::instance($ccat->id);
if (!in_array($ccatctx->id,$contextids)) { if (!in_array($ccatctx->id, $contextids)) {
$cats[] = $ccat; $cats[] = $ccat;
} }
} }
@ -529,7 +525,6 @@ class courseservice extends \external_api {
} }
/************************************** /**************************************
* *
* Progress scanners for teacherview * Progress scanners for teacherview
@ -540,7 +535,7 @@ class courseservice extends \external_api {
* Return value description for scan_grade_progress function * Return value description for scan_grade_progress function
* @return external_function_parameters * @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( [ return new \external_function_parameters( [
"gradeitemid" => new \external_value(PARAM_INT, 'Grade item ID to scan progress for', VALUE_DEFAULT), "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), "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 * 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); return gradingscanner::structure(VALUE_REQUIRED);
} }
@ -585,7 +580,7 @@ class courseservice extends \external_api {
/** /**
* Return value description for scan_completion_progress function * 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( [ return new \external_function_parameters( [
"criteriaid" => new \external_value(PARAM_INT, 'CriteriaID to scan progress for', VALUE_DEFAULT), "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), "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 * 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); return completionscanner::structure(VALUE_REQUIRED);
} }
@ -621,7 +616,7 @@ class courseservice extends \external_api {
/** /**
* Return value description for scan_badge_progress function * 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( [ return new \external_function_parameters( [
"badgeid" => new \external_value(PARAM_INT, 'Badge to scan progress for', VALUE_DEFAULT), "badgeid" => new \external_value(PARAM_INT, 'Badge to scan progress for', VALUE_DEFAULT),
"studyplanid" => new \external_value(PARAM_INT, "studyplanid" => new \external_value(PARAM_INT,
@ -632,7 +627,7 @@ class courseservice extends \external_api {
/** /**
* Parameter description for scan_badge_progress function * 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([ return new \external_single_structure([
"total" => new \external_value(PARAM_INT, 'Total number of students scanned'), "total" => new \external_value(PARAM_INT, 'Total number of students scanned'),
"issued" => new \external_value(PARAM_INT, 'Number of issued badges'), "issued" => new \external_value(PARAM_INT, 'Number of issued badges'),

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -69,7 +69,7 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
*/ */
protected function initialize($configstr) { protected function initialize($configstr) {
// First initialize with the defaults. // 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}")); $val = intval(get_config('local_treestudyplan', "bistate_{$key}"));
if ($val >= 0 && $val <= 100) { if ($val >= 0 && $val <= 100) {
$this->cfg()->$key = floatval($val) / 100; $this->cfg()->$key = floatval($val) / 100;
@ -84,7 +84,7 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
if (is_array($config)) { if (is_array($config)) {
// Copy all valid config settings to this item. // 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)) { if (array_key_exists($key, $config)) {
$val = $config[$key]; $val = $config[$key];
if ($val >= 0 && $val <= 100) { 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. * 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. * @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; return true;
} }
@ -173,7 +173,7 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
$totalrequired = 0; $totalrequired = 0;
$requiredmet = 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) { foreach ($completions as $index => $c) {
@ -181,7 +181,7 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
$progress += ($c >= $minprogress) ? 1 : 0; $progress += ($c >= $minprogress) ? 1 : 0;
$failed += ($c <= completion::FAILED) ? 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. // Not using count($required) to prevent nonexistant indices in the required list from messing things up.
$totalrequired += 1; $totalrequired += 1;
if ($c >= completion::COMPLETED) { if ($c >= completion::COMPLETED) {
@ -193,10 +193,10 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
$started = $progress + $failed; $started = $progress + $failed;
$allrequiredmet = ($requiredmet >= $totalrequired); $allrequiredmet = ($requiredmet >= $totalrequired);
$fractioncompleted = ($total > 0) ? (floatval($completed) / floatval($total)) : 0.0; $fractioncompleted = ($total > 0) ? (floatval($completed) / floatval($total)): 0.0;
$fractionprogress = ($total > 0) ? (floatval($progress) / floatval($total)) : 0.0; $fractionprogress = ($total > 0) ? (floatval($progress) / floatval($total)): 0.0;
$fractionfailed = ($total > 0) ? (floatval($failed) / floatval($total)) : 0.0; $fractionfailed = ($total > 0) ? (floatval($failed) / floatval($total)): 0.0;
$fractionstarted = ($total > 0) ? (floatval($started) / floatval($total)) : 0.0; $fractionstarted = ($total > 0) ? (floatval($started) / floatval($total)): 0.0;
if ($total == 0) { if ($total == 0) {
return completion::INCOMPLETE; return completion::INCOMPLETE;
@ -230,7 +230,7 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
*/ */
public function aggregate_course(courseinfo $courseinfo, studyitem $studyitem, $userid) { public function aggregate_course(courseinfo $courseinfo, studyitem $studyitem, $userid) {
$course = $courseinfo->course(); $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. // Note: studyitem condition config is not used in this aggregator.
// Loop through all associated gradables and count the totals, completed, etc.. // Loop through all associated gradables and count the totals, completed, etc..
$completions = []; $completions = [];
@ -323,12 +323,12 @@ class bistate_aggregator extends \local_treestudyplan\aggregator {
$gradeitem = $gradeinfo->get_gradeitem(); $gradeitem = $gradeinfo->get_gradeitem();
$grade = $gradeitem->get_final($userid); $grade = $gradeitem->get_final($userid);
$course = \get_course($gradeitem->courseid); // Fetch course from cache. $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)) { if (empty($grade)) {
return completion::INCOMPLETE; return completion::INCOMPLETE;
} else if ($grade->finalgrade === null) { } 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. // 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. // 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) { protected function initialize($configstr) {
// First initialize with the defaults. // First initialize with the defaults.
foreach (["thresh_completed", ] as $key) { foreach (["thresh_completed" ] as $key) {
$val = intval(get_config('local_treestudyplan', "competency_{$key}")); $val = intval(get_config('local_treestudyplan', "competency_{$key}"));
if ($val >= 0 && $val <= 100) { if ($val >= 0 && $val <= 100) {
$this->cfg()->$key = floatval($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}")); $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)) { if (is_array($config)) {
// Copy all valid config settings to this item. // Copy all valid config settings to this item.
foreach (["thresh_completed", ] as $key) { foreach (["thresh_completed" ] as $key) {
if (array_key_exists($key, $config)) { if (array_key_exists($key, $config)) {
$val = $config[$key]; $val = $config[$key];
if ($val >= 0 && $val <= 100) { 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)) { if (array_key_exists($key, $config)) {
$this->cfg()->$key = boolval($config[$key]); $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) { public function aggregate_course(courseinfo $courseinfo, studyitem $studyitem, $userid) {
// Retrieve the course competencies // Retrieve the course competencies
$course = $courseinfo->course(); $course = $courseinfo->course();
$cci = new coursecompetencyinfo($course,$studyitem); $cci = new coursecompetencyinfo($course, $studyitem);
$competencies = $cci->course_competencies(); $competencies = $cci->course_competencies();
if (count($competencies) == 0) { if (count($competencies) == 0) {
@ -180,14 +180,14 @@ class competency_aggregator extends \local_treestudyplan\aggregator {
$requiredcount = 0; $requiredcount = 0;
foreach ($competencies as $c) { foreach ($competencies as $c) {
$count += 1; $count += 1;
$p = $cci->proficiency($c,$userid); $p = $cci->proficiency($c, $userid);
if ($p->proficient) { if ($p->proficient) {
$proficient += 1; $proficient += 1;
} }
if ($p->courseproficient) { if ($p->courseproficient) {
$courseproficient += 1; $courseproficient += 1;
} }
if ($cci->is_required(($c))){ if ($cci->is_required(($c))) {
$requiredcount += 1; $requiredcount += 1;
if ($p->proficient) { if ($p->proficient) {
$requiredmet += 1; $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; $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 ($proficient >= $count && $requiredmet >= $requiredcount) {
if ($limit < $count) { if ($limit < $count) {
@ -280,7 +280,6 @@ class competency_aggregator extends \local_treestudyplan\aggregator {
} }
} }
/** /**
* Determine completion for a single grade and user * Determine completion for a single grade and user
* @param gradeinfo $gradeinfo Gradeinfo object for grade to check * @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. // COURSE COMPETENCIES DOESN'T REALLY USE THIS FUNCTION.
} }
} }

View File

@ -35,7 +35,6 @@ class core_aggregator extends \local_treestudyplan\aggregator {
/** @var bool */ /** @var bool */
public const DEPRECATED = false; public const DEPRECATED = false;
/** /**
* Create new instance of aggregation method * Create new instance of aggregation method
* @param string $configstr Aggregation configuration string * @param string $configstr Aggregation configuration string
@ -50,7 +49,7 @@ class core_aggregator extends \local_treestudyplan\aggregator {
* @param string $configstr Aggregation configuration string * @param string $configstr Aggregation configuration string
*/ */
protected function initialize($configstr) { protected function initialize($configstr) {
} }
/** /**
@ -208,7 +207,6 @@ class core_aggregator extends \local_treestudyplan\aggregator {
} }
} }
/** /**
* Determine completion for a single grade and user * Determine completion for a single grade and user
* @param gradeinfo $gradeinfo Gradeinfo object for grade to check * @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) { public function aggregate_course(courseinfo $courseinfo, studyitem $studyitem, $userid) {
$condition = self::DEFAULT_CONDITION; $condition = self::DEFAULT_CONDITION;
$list = []; $list = [];
foreach (gradeinfo::list_studyitem_gradables($studyitem) as $gi) { foreach (gradeinfo::list_studyitem_gradables($studyitem) as $gi) {
$list[] = $this->grade_completion($gi, $userid); $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) { public function aggregate_junction(array $completion, studyitem $studyitem, $userid) {
$completed = self::aggregate_completion($completion, $studyitem->conditions()); $completed = self::aggregate_completion($completion, $studyitem->conditions());
// If null result (conditions are unknown/null) - default to ALL. // 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)) { if (empty($grade)) {
return completion::INCOMPLETE; return completion::INCOMPLETE;
} else if ($grade->finalgrade === null) { } 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. // 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. // 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 * @param string $capability The capability to scan for in the categories
* @return boolean * @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; global $USER;
if ($userid == null) { if ($userid == null) {
$userid = $USER->id; $userid = $USER->id;
} }
$list = courseservice::user_tops($userid,$capability); $list = courseservice::user_tops($userid, $capability);
return boolval(count($list) > 0); 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 \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 * @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()); $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); imagefilledpolygon($im, $pts, $color);
} }
@ -100,7 +100,6 @@ class randomimage {
imagefilledarc($im, $cx, $cy, $w, $h, $s, $e, $col, $style); imagefilledarc($im, $cx, $cy, $w, $h, $s, $e, $col, $style);
} }
/** /**
* Generates an array of random alpha color values. * Generates an array of random alpha color values.
* @return Array [r, g, b, a] * @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 * @param integer $length Number of sets of points to generate
* @return Array The resulting array of points * @return Array The resulting array of points
*/ */
@ -130,7 +129,7 @@ class randomimage {
return $pts; return $pts;
} }
public function __construct($shapes=3,$width=256,$height=256) { public function __construct($shapes=3, $width=256, $height=256) {
$this->shapes = $shapes; $this->shapes = $shapes;
$this->width = $width; $this->width = $width;
$this->height = $height; $this->height = $height;
@ -143,7 +142,7 @@ class randomimage {
} }
$this->name = $string.".png"; $this->name = $string.".png";
$im = imagecreatetruecolor($this->width, $this->height); $im = imagecreatetruecolor($this->width, $this->height);
for ($i = 0; $i < $this->shapes; $i++) { for ($i = 0; $i < $this->shapes; $i++) {
switch(\random_int(1, 2)) { switch(\random_int(1, 2)) {
@ -155,8 +154,8 @@ class randomimage {
break; break;
} }
} }
$this->tempfile = \tempnam("/tmp","tsp"); $this->tempfile = \tempnam("/tmp", "tsp");
imagepng($im,$this->tempfile); imagepng($im, $this->tempfile);
imagedestroy($im); imagedestroy($im);
} }

View File

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

View File

@ -20,7 +20,6 @@
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
namespace local_treestudyplan; namespace local_treestudyplan;
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
@ -30,7 +29,6 @@ use DateTime;
use moodle_url; use moodle_url;
use stdClass; use stdClass;
/** /**
* Handle badge information in the same style as the other classes * 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. // 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. // 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----- private static $premiumcrt = "-----BEGIN CERTIFICATE-----
MIIDSzCCAjMCFFlyhmKf1fN7U5lQL/dtlsyP24AQMA0GCSqGSIb3DQEBCwUAMGEx MIIDSzCCAjMCFFlyhmKf1fN7U5lQL/dtlsyP24AQMA0GCSqGSIb3DQEBCwUAMGEx
@ -64,31 +62,31 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
private static $cachedpremiumstatus = null; private static $cachedpremiumstatus = null;
public static function supported() { public static function supported() {
return self::$premium_supported; return self::$premiumsupported;
} }
private static function decrypt($encrypted) { private static function decrypt($encrypted) {
// Get the public key. // Get the public key.
$key = \openssl_get_publickey(self::$premiumcrt); $key = \openssl_get_publickey(self::$premiumcrt);
if ($key === false ){ if ($key === false ) {
throw new \ValueError("Error parsing public key data)"); throw new \ValueError("Error parsing public key data)");
} }
// Determine the key size. // Determine the key size.
$keysize = \openssl_pkey_get_details($key)["bits"]; $keysize = \openssl_pkey_get_details($key)["bits"];
// //
$blocksize = ($keysize / 8); // Bits / 8. Whether padded or not. $blocksize = ($keysize / 8); // Bits / 8. Whether padded or not.
// Decode data in // Decode data in
$b64 = \base64_decode($encrypted); $b64 = \base64_decode($encrypted);
if ($b64 === false) { if ($b64 === false) {
throw new \ValueError("Error in base64 decoding"); throw new \ValueError("Error in base64 decoding");
} }
$data = \str_split($b64,$blocksize); $data = \str_split($b64, $blocksize);
$decrypted = ""; $decrypted = "";
$i = 0; $i = 0;
foreach($data as $chunk) { 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; $decrypted .= $dchunk;
} else { } else {
throw new \ValueError("Error decrypting chunk $i ({$blocksize} bytes)"); throw new \ValueError("Error decrypting chunk $i ({$blocksize} bytes)");
@ -104,23 +102,23 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
return $decrypted; return $decrypted;
} }
private static function trim_headers($data) { private static function trim_headers($data) {
// Headers are repeated in this function for easier testing and copy-pasting into other projects. // Headers are repeated in this function for easier testing and copy-pasting into other projects.
$START_HEADER = "----- BEGIN ACTIVATION KEY -----"; $STARTHEADER = "----- BEGIN ACTIVATION KEY -----";
$END_HEADER = "----- END ACTIVATION KEY -----"; $ENDHEADER = "----- END ACTIVATION KEY -----";
$parts = preg_split("/\r?\n/",\trim($data)); $parts = preg_split("/\r?\n/", \trim($data));
if (count($parts) > 2) { if (count($parts) > 2) {
$start = -1; $start = -1;
$end = -1; $end = -1;
for($i = 0; $i < count($parts); $i++) { 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... $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; $start = $i+1;
} }
if ($start > 0 && $p == $END_HEADER) { if ($start > 0 && $p == $ENDHEADER) {
$end = $i; $end = $i;
} }
} }
@ -129,7 +127,7 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
throw new \ValueError("Invalid activation key wrappers"); throw new \ValueError("Invalid activation key wrappers");
} else { } else {
$keyslice = array_slice($parts, $start, $end - $start); $keyslice = array_slice($parts, $start, $end - $start);
return implode("\n",$keyslice); return implode("\n", $keyslice);
} }
} else { } else {
throw new \ValueError("Invalid activation key"); throw new \ValueError("Invalid activation key");
@ -141,7 +139,7 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
* @return bool * @return bool
*/ */
public static function enabled() { public static function enabled() {
if (self::$premium_supported) { if (self::$premiumsupported) {
$status = self::premiumStatus(); $status = self::premiumStatus();
return $status->enabled; return $status->enabled;
} else { } else {
@ -154,10 +152,10 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
* @param string $intent The intent to search for * @param string $intent The intent to search for
* @return bool * @return bool
*/ */
public static function has_intent($intent){ public static function has_intent($intent) {
$status = self::premiumStatus(); $status = self::premiumStatus();
if ($status->enabled) { if ($status->enabled) {
return \in_array(\strtolower($intent),$status->intents); return \in_array(\strtolower($intent), $status->intents);
} else { } else {
return false; return false;
} }
@ -166,25 +164,25 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
public static function debuginfo() { public static function debuginfo() {
$s = "<pre>"; $s = "<pre>";
try { try {
$activationkey = \get_config("local_treestudyplan","premium_key"); $activationkey = \get_config("local_treestudyplan", "premium_key");
if (strlen($activationkey) > 0) { if (strlen($activationkey) > 0) {
$keydata = self::trim_headers($activationkey); $keydata = self::trim_headers($activationkey);
$json = self::decrypt($keydata); $json = self::decrypt($keydata);
$s .= "Decoded key data:\n----\n"; $s .= "Decoded key data:\n----\n";
$s .= $json . "\n----\n"; $s .= $json . "\n----\n";
$decoded = \json_decode($json,false); $decoded = \json_decode($json, false);
$s .= "Read as object:\n----\n"; $s .= "Read as object:\n----\n";
$s .= print_r($decoded,true) ."\n----\n"; $s .= print_r($decoded, true) ."\n----\n";
$status = self::premiumStatus(); $status = self::premiumStatus();
$s .= "Parsed premium status block:\n----\n"; $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"; $s .= "Message: " . self::statusdescription() . "\n";
} else { } else {
$s .= "Premium key empty"; $s .= "Premium key empty";
} }
} catch (\Throwable $x) { } catch (\Throwable $x) {
$s .= "!!! " . get_class($x) . ": " . $x->getCode() . " | " . $x->getMessage(). "\n"; $s .= "!!! " . get_class($x) . ": " . $x->getCode() . " | " . $x->getMessage(). "\n";
$stack = explode("\n",$x->getTraceAsString()); $stack = explode("\n", $x->getTraceAsString());
foreach ($stack as $l) { foreach ($stack as $l) {
$s .= " " . trim($l) ."\n"; $s .= " " . trim($l) ."\n";
} }
@ -193,13 +191,13 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
$s.="</pre>"; $s.="</pre>";
return $s; return $s;
} }
/** /**
* Determine, cache and retrieve premium status * Determine, cache and retrieve premium status
* @return object * @return object
*/ */
protected static function premiumStatus() { protected static function premiumStatus() {
if (!isset(self::$cachedpremiumstatus)) { if (!isset(self::$cachedpremiumstatus)) {
// Initialize default object. // Initialize default object.
$o = new \stdClass; $o = new \stdClass;
$o->enabled = false; $o->enabled = false;
@ -210,28 +208,28 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
$o->expired = false; $o->expired = false;
$o->issued = ""; $o->issued = "";
try { try {
$activationkey = \get_config("local_treestudyplan","premium_key"); $activationkey = \get_config("local_treestudyplan", "premium_key");
if (strlen($activationkey) > 0) { if (strlen($activationkey) > 0) {
$keydata = self::trim_headers($activationkey); $keydata = self::trim_headers($activationkey);
$json = self::decrypt($keydata); $json = self::decrypt($keydata);
$decoded = \json_decode($json,false); $decoded = \json_decode($json, false);
if (is_object($decoded)) { if (is_object($decoded)) {
// Copy basic data/ // Copy basic data/
$keys = ["name","website","expires","issued"]; $keys = ["name", "website", "expires", "issued"];
foreach ( $keys as $k) { foreach ( $keys as $k) {
if (isset($decoded->$k)) { if (isset($decoded->$k)) {
$o->$k = $decoded->$k; $o->$k = $decoded->$k;
} }
} }
if(!empty($decoded->intent)) { if (!empty($decoded->intent)) {
$o->intents = explode(",",$decoded->intent); $o->intents = explode(", ", $decoded->intent);
} }
// Convert dates to DateTime for // Convert dates to DateTime for
$now = new \DateTime(); $now = new \DateTime();
$issuedate = new \DateTime($o->issued); $issuedate = new \DateTime($o->issued);
$expirydate = new \DateTime(); // Default to now $expirydate = new \DateTime(); // Default to now
@ -244,7 +242,7 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
} catch (\Exception $x) {} } catch (\Exception $x) {}
} }
if ( \in_array('treestudyplan',$o->intents) if ( \in_array('treestudyplan', $o->intents)
&& !empty($o->issued) && !empty($o->issued)
&& self::website_match($o->website) && self::website_match($o->website)
) { ) {
@ -256,17 +254,17 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
$o->enabled = false; $o->enabled = false;
} }
// Format dates localized. // 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") { if ($o->expires == "never") {
$o->expires = \get_string("premium:never",'local_treestudyplan'); $o->expires = \get_string("premium:never", 'local_treestudyplan');
} else { } else {
$o->expires = \userdate($expirydate->getTimestamp(),\get_string('strftimedate','langconfig')); $o->expires = \userdate($expirydate->getTimestamp(), \get_string('strftimedate', 'langconfig'));
} }
} }
} }
} }
} catch (\ValueError $x) { } catch (\ValueError $x) {
$o->status = \get_string("premium:invalidactivationcontent","local_treestudyplan"); $o->status = \get_string("premium:invalidactivationcontent", "local_treestudyplan");
} }
self::$cachedpremiumstatus = $o; self::$cachedpremiumstatus = $o;
@ -280,13 +278,13 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
private static function website_match($key) { private static function website_match($key) {
global $CFG; global $CFG;
$site = $CFG->wwwroot; $site = $CFG->wwwroot;
// Add double slashes to key and site if no scheme is set. // Add double slashes to key and site if no scheme is set.
// Basically: if no double slashes present before any dots,slashes or @s. // Basically: if no double slashes present before any dots, slashes or @s.
if(!\preg_match_all('#^[^./@]*?//#',$key )) { if (!\preg_match_all('#^[^./@]*?//#', $key )) {
$key = "//".$key; $key = "//".$key;
} }
if(!\preg_match_all('#^[^./@]*?//#',$site)) { if (!\preg_match_all('#^[^./@]*?//#', $site)) {
$site = "//".$site; $site = "//".$site;
} }
// Use parse_url() to split path and host. // Use parse_url() to split path and host.
@ -304,17 +302,17 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
} }
// First match the host part. // First match the host part.
$keyparts = \array_reverse(\explode(".",$keyurl->host)); $keyparts = \array_reverse(\explode(".", $keyurl->host));
$siteparts = \array_reverse(\explode(".",$siteurl->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. // 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($keyparts)) != "www") {\array_push($keyparts, $x);}
if (($x = \array_pop($siteparts)) != "www") {\array_push($siteparts,$x);} if (($x = \array_pop($siteparts)) != "www") {\array_push($siteparts, $x);}
for ($i = 0; $i < count($keyparts); $i++) { 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 * // No match if the site does not have a part, but the key does. Unless the key part is *
if (!isset($siteparts[$i]) ) { if (!isset($siteparts[$i]) ) {
if($keyparts[$i] != "*") { if ($keyparts[$i] != "*") {
return false; return false;
} else { } else {
$i++; //increment $i by one before break, to make sure the comparison following this loop holds. $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. // Now do a proper case insensitive check for matching.
// Uses fnmatch to easily handle shell type wildcards. // 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; return false;
} }
} }
@ -335,39 +333,39 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
// If we made it here then the host part matches. Now check the path. // If we made it here then the host part matches. Now check the path.
// If path is /*, matches all subpaths including / // If path is /*, matches all subpaths including /
$keypath = empty($keyurl->path)?"/":$keyurl->path; $keypath = empty($keyurl->path) ? "/" : $keyurl->path;
$sitepath = empty($siteurl->path)?"/":$siteurl->path; $sitepath = empty($siteurl->path) ? "/" : $siteurl->path;
// Trim trailing / from both paths before comparison // Trim trailing / from both paths before comparison
if (\strlen($sitepath) > 1) { if (\strlen($sitepath) > 1) {
$sitepath = \rtrim($sitepath,"/"); $sitepath = \rtrim($sitepath, "/");
} }
if (\strlen($keypath) > 1) { if (\strlen($keypath) > 1) {
$keypath = \rtrim($keypath,"/"); $keypath = \rtrim($keypath, "/");
} }
// Do a case insensitive fnmatch on the site so wildcards are matched too. // 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 * 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 new \external_function_parameters([]);
} }
/** /**
* Return value description for webservice function get_premiumstatus * 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([ return new \external_single_structure([
"enabled" => new \external_value(PARAM_BOOL, 'premium status enabled'), "enabled" => new \external_value(PARAM_BOOL, 'premium status enabled'),
"website" => new \external_value(PARAM_TEXT, 'premium registration website'), "website" => new \external_value(PARAM_TEXT, 'premium registration website'),
"name" => new \external_value(PARAM_TEXT, 'premium registration name'), "name" => new \external_value(PARAM_TEXT, 'premium registration name'),
"expires" => new \external_value(PARAM_TEXT, 'premium registration expiry date'), "expires" => new \external_value(PARAM_TEXT, 'premium registration expiry date'),
"expired" => new \external_value(PARAM_BOOL, 'premium status expired'), "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 * @return object
*/ */
public static function get_premiumstatus() { public static function get_premiumstatus() {
if (self::$premium_supported) { if (self::$premiumsupported) {
$status = self::premiumStatus(); $status = self::premiumStatus();
$keys = [ $keys = [
"enabled", "enabled",
@ -386,7 +384,7 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
"expired", "expired",
"intents", "intents",
]; ];
$result = []; $result = [];
foreach ( $keys as $param) { foreach ( $keys as $param) {
$result[$param] = $status->$param; $result[$param] = $status->$param;
@ -416,19 +414,19 @@ Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
$msg->issued = $status->issued; $msg->issued = $status->issued;
$msg->expires = $status->expires; $msg->expires = $status->expires;
if ($status->website != "*") { if ($status->website != "*") {
$msg->sitestatus = \get_string("premium:onsite",'local_treestudyplan',$status); $msg->sitestatus = \get_string("premium:onsite", 'local_treestudyplan', $status);
} else { } else {
$msg->sitestatus = \get_string("premium:anywhere",'local_treestudyplan'); $msg->sitestatus = \get_string("premium:anywhere", 'local_treestudyplan');
} }
if($status->enabled) { if ($status->enabled) {
return \get_string("premium:active",'local_treestudyplan',$msg); return \get_string("premium:active", 'local_treestudyplan', $msg);
} else if ($status->expired) { } 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)) { } 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 { } 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") { public static function require_premium($message="premiumfeature:warning") {
if (! self::enabled()) { 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. * @param int $userid The user to search.
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin. * @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 = new \core_privacy\local\request\contextlist();
$contextlist->add_system_context(); // For invitations. $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. // Determine the relevant plan_ids for this context.
$sql = "SELECT s.id FROM {local_treestudyplan} $sql = "SELECT s.id FROM {local_treestudyplan}
WHERE ( s.context_id IS NULL OR s.context_id == 0 OR s.context_id = :contextid)) "; 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. // If plan ids not empty, they will be processed later.
// Also delete all invitations for these users. // 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) { } else if ($context->contextlevel == CONTEXT_COURSECAT) {
$sql = "SELECT s.id FROM {local_treestudyplan} $sql = "SELECT s.id FROM {local_treestudyplan}
WHERE (s.context_id = :contextid)"; 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. // 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->addElement('hidden', 'update', 0);
$mform->setType('update', PARAM_INT); $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->setType('name', PARAM_NOTAGS); // Set type of element.
$mform->setDefault('name', ''); // Default value. $mform->setDefault('name', ''); // Default value.
$mform->addRule('name', get_string('required'), 'required', null, 'client'); $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->setType('email', PARAM_NOTAGS); // Set type of element.
$mform->setDefault('email', ''); // Default value. $mform->setDefault('email', ''); // Default value.
$mform->addRule('email', get_string('required'), 'required', null, 'client'); $mform->addRule('email', get_string('required'), 'required', null, 'client');
@ -68,7 +68,7 @@ class reportinvite_form extends moodleform {
* @return array validation data * @return array validation data
*/ */
public function validation($data, $files) { 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"; 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([ return new \external_function_parameters([
"pageid" => new \external_value(PARAM_INT, 'id of studyplan page'), "pageid" => new \external_value(PARAM_INT, 'id of studyplan page'),
"firstperiod" => new \external_value(PARAM_INT, 'first 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), "lastperiod" => new \external_value(PARAM_INT, 'last period to include in report', VALUE_DEFAULT),
]); ]);
} }
/** /**
* Return value description for webservice function list_user_studyplans * 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([ return new \external_single_structure([
"periods" => new \external_multiple_structure(new \external_single_structure([ "periods" => new \external_multiple_structure(new \external_single_structure([
"period" => period::structure(), "period" => period::structure(),
@ -75,14 +74,14 @@ class reportservice extends \external_api {
* @param int|null $lastperiod Last period to include in report * @param int|null $lastperiod Last period to include in report
* @return object * @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); $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(); $plan = $page->studyplan();
if (empty($firstperiod)) { if (empty($firstperiod)) {
$firstperiod = 1; $firstperiod = 1;
} }
if (empty($lastperiod)) { if (empty($lastperiod)) {
// Index for periods starts at 1, so the period count is same as length // Index for periods starts at 1, so the period count is same as length
$lastperiod = $page->periods(); $lastperiod = $page->periods();
@ -111,30 +110,29 @@ class reportservice extends \external_api {
"line" => $line->simple_model(), "line" => $line->simple_model(),
"items" => [], "items" => [],
]; ];
$items = studyitem::search_studyline_children($line,$i,studyitem::COURSE); $items = studyitem::search_studyline_children($line, $i, studyitem::COURSE);
if (count($items) > 0) { if (count($items) > 0) {
foreach ($items as $item) { foreach ($items as $item) {
$lmodel["items"][] = $item->editor_model(); $lmodel["items"][] = $item->editor_model();
} }
// Only include the line if it has actual children - saves us from muddying up the report. // Only include the line if it has actual children - saves us from muddying up the report.
$pmodel['lines'][] = $lmodel; $pmodel['lines'][] = $lmodel;
} }
} }
$model["periods"][] = $pmodel; $model["periods"][] = $pmodel;
} }
return $model; 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([ return new \external_function_parameters([
"pageid" => new \external_value(PARAM_INT, 'id of studyplan page'), "pageid" => new \external_value(PARAM_INT, 'id of studyplan page'),
"userid" => new \external_value(PARAM_INT, 'id of user'), "userid" => new \external_value(PARAM_INT, 'id of user'),
"firstperiod" => new \external_value(PARAM_INT, 'first 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), "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 * 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"); 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); $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(); $plan = $page->studyplan();
if (!$plan->has_linked_user($userid)) { 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)) { if (empty($firstperiod)) {
$firstperiod = 1; $firstperiod = 1;
} }
if (empty($lastperiod)) { if (empty($lastperiod)) {
// Index for periods starts at 1, so the period count is same as length // Index for periods starts at 1, so the period count is same as length
$lastperiod = $page->periods(); $lastperiod = $page->periods();
@ -170,7 +167,7 @@ class reportservice extends \external_api {
for($i = $firstperiod; $i <= $lastperiod; $i++) { for($i = $firstperiod; $i <= $lastperiod; $i++) {
$lines = studyline::find_page_children($page); $lines = studyline::find_page_children($page);
foreach ($lines as $line) { 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) { if (count($items) > 0) {
foreach ($items as $item) { foreach ($items as $item) {
$model[] = $item->user_model($userid); $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([ return new \external_function_parameters([
"itemid" => new \external_value(PARAM_INT, 'id of studyitem'), "itemid" => new \external_value(PARAM_INT, 'id of studyitem'),
"userid" => new \external_value(PARAM_INT, 'id of user'), "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 * 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(); return studyitem::user_structure();
} }
@ -205,16 +200,15 @@ class reportservice extends \external_api {
* @param int $userid ID of user to check specific info for * @param int $userid ID of user to check specific info for
* @return array * @return array
*/ */
public static function get_report_details($itemid,$userid) { public static function get_report_details($itemid, $userid) {
$item = studyitem::find_by_id($itemid); $item = studyitem::find_by_id($itemid);
$plan = $item->studyline()->studyplan(); $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)) { 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); return $item->user_model($userid);
} }
} }

View File

@ -48,11 +48,11 @@ class studentstudyplanservice extends \external_api {
* list_user_studyplans * * list_user_studyplans *
* * * *
************************/ ************************/
/** /**
* Parameter description for webservice function 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([ return new \external_function_parameters([
"userid" => new \external_value(PARAM_INT, 'id of student', VALUE_DEFAULT), "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 * 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( return new \external_multiple_structure(
studyplan::simple_structure() studyplan::simple_structure()
); );
@ -95,7 +95,7 @@ class studentstudyplanservice extends \external_api {
/** /**
* Parameter description for webservice function get_user_studyplan * 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( [ return new \external_function_parameters( [
"userid" => new \external_value(PARAM_INT, 'id of user'), "userid" => new \external_value(PARAM_INT, 'id of user'),
"studyplanid" => new \external_value(PARAM_INT, 'id of specific studyplan to provide'), "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 * 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(); return studyplan::user_structure();
} }
@ -126,7 +126,7 @@ class studentstudyplanservice extends \external_api {
} }
if ($studyplan->exist_for_user($userid)) { if ($studyplan->exist_for_user($userid)) {
$model = $studyplan->user_model($userid); $model = $studyplan->user_model($userid);
return $model; return $model;
} else { } else {
@ -143,7 +143,7 @@ class studentstudyplanservice extends \external_api {
/** /**
* Parameter description for webservice function get_user_page * 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( [ return new \external_function_parameters( [
"userid" => new \external_value(PARAM_INT, 'id of user'), "userid" => new \external_value(PARAM_INT, 'id of user'),
"pageid" => new \external_value(PARAM_INT, 'id of specific studyplan to provide'), "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 * 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(); return studyplan::user_structure();
} }
@ -185,7 +185,7 @@ class studentstudyplanservice extends \external_api {
/** /**
* Parameter description for webservice function list_invited_studyplan * 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( [ return new \external_function_parameters( [
"invitekey" => new \external_value(PARAM_RAW, 'invite key'), "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 * 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( return new \external_multiple_structure(
studyplan::simple_structure() studyplan::simple_structure()
); );
@ -208,7 +208,7 @@ class studentstudyplanservice extends \external_api {
public static function list_invited_studyplans($invitekey) { public static function list_invited_studyplans($invitekey) {
global $DB; global $DB;
// First check if studyplan sharing is enabled. // First check if studyplan sharing is enabled.
if (!get_config("local_treestudyplan","enableplansharing")) { if (!get_config("local_treestudyplan", "enableplansharing")) {
return []; return [];
} }
@ -243,7 +243,7 @@ class studentstudyplanservice extends \external_api {
/** /**
* Parameter description for webservice function get_invited_studyplan * 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( [ return new \external_function_parameters( [
"invitekey" => new \external_value(PARAM_RAW, 'invite key'), "invitekey" => new \external_value(PARAM_RAW, 'invite key'),
"studyplanid" => new \external_value(PARAM_INT, 'studyplan_id'), "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 * 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(); return studyplan::user_structure();
} }
@ -263,10 +263,10 @@ class studentstudyplanservice extends \external_api {
* @param int $studyplanid ID of the studyplan to retrieve * @param int $studyplanid ID of the studyplan to retrieve
* @return array * @return array
*/ */
public static function get_invited_studyplan($invitekey,$studyplanid) { public static function get_invited_studyplan($invitekey, $studyplanid) {
global $DB; global $DB;
// First check if studyplan sharing is enabled. // First check if studyplan sharing is enabled.
if (!get_config("local_treestudyplan","enableplansharing")) { if (!get_config("local_treestudyplan", "enableplansharing")) {
return []; return [];
} }
$invite = $DB->get_record_select( $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 // Do not validate the context in this instance to avoid requiring logins when this is not wanted
$studyplan = studyplan::find_by_id($studyplanid); $studyplan = studyplan::find_by_id($studyplanid);
$userid = $invite->user_id; $userid = $invite->user_id;
@ -290,7 +290,7 @@ class studentstudyplanservice extends \external_api {
} else { } else {
throw new \moodle_exception("The selected studyplan is suspended"); throw new \moodle_exception("The selected studyplan is suspended");
} }
} else { } else {
throw new \moodle_exception("Invitation's user is not linked to this studyplan"); 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 * 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( [ return new \external_function_parameters( [
"invitekey" => new \external_value(PARAM_RAW, 'invite key'), "invitekey" => new \external_value(PARAM_RAW, 'invite key'),
"pageid" => new \external_value(PARAM_INT, 'studyplan page id'), "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 * 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(); return studyplanpage::user_structure();
} }
@ -325,10 +325,10 @@ class studentstudyplanservice extends \external_api {
* @param int $pageid ID of the studyplan to retrieve * @param int $pageid ID of the studyplan to retrieve
* @return array * @return array
*/ */
public static function get_invited_page($invitekey,$pageid) { public static function get_invited_page($invitekey, $pageid) {
global $DB; global $DB;
// First check if studyplan sharing is enabled. // First check if studyplan sharing is enabled.
if (!get_config("local_treestudyplan","enableplansharing")) { if (!get_config("local_treestudyplan", "enableplansharing")) {
return []; return [];
} }
$invite = $DB->get_record_select( $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 // Do not validate the context in this instance to avoid requiring logins when this is not wanted
$page = studyplanpage::find_by_id($pageid); $page = studyplanpage::find_by_id($pageid);
$studyplan = $page->studyplan(); $studyplan = $page->studyplan();
$userid = $invite->user_id; $userid = $invite->user_id;
@ -363,14 +363,14 @@ class studentstudyplanservice extends \external_api {
/** /**
* Parameter description for webservice function list_own_studyplans * 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 new \external_function_parameters([]);
} }
/** /**
* Return value description for webservice function list_own_studyplans * 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( return new \external_multiple_structure(
studyplan::simple_structure() studyplan::simple_structure()
); );
@ -401,7 +401,7 @@ class studentstudyplanservice extends \external_api {
/** /**
* Parameter description for webservice function get_own_studyplan * 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( [ return new \external_function_parameters( [
"studyplanid" => new \external_value(PARAM_INT, 'id of studyplan to retrieve'), "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 * 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(); return studyplan::user_structure();
} }
@ -446,7 +446,7 @@ class studentstudyplanservice extends \external_api {
/** /**
* Parameter description for webservice function get_own_page * 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( [ return new \external_function_parameters( [
"pageid" => new \external_value(PARAM_INT, 'id of studyplan to retrieve'), "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 * 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(); return studyplan::user_structure();
} }
/** /**
* Get studyplanpage for current user * Get studyplanpage for current user
* @param int $pagid ID of specific studyplan page * @param int $pagid ID of specific studyplan page
* @return array * @return array
*/ */
@ -491,14 +491,14 @@ class studentstudyplanservice extends \external_api {
/** /**
* Parameter description for webservice function list_teaching_studyplans * 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 new \external_function_parameters( [] );
} }
/** /**
* Return value description for webservice function list_teaching_studyplans * 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( return new \external_multiple_structure(
studyplan::simple_structure() studyplan::simple_structure()
); );
@ -532,14 +532,14 @@ class studentstudyplanservice extends \external_api {
/** /**
* Parameter description for webservice function list_teaching_studyplans * 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 new \external_function_parameters( [] );
} }
/** /**
* Return value description for webservice function list_teaching_studyplans * 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( return new \external_multiple_structure(
studyplan::simple_structure() studyplan::simple_structure()
); );
@ -557,17 +557,17 @@ class studentstudyplanservice extends \external_api {
\external_api::validate_context(\context_system::instance()); \external_api::validate_context(\context_system::instance());
// Return empty list if coach role not enabled // 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 []; return [];
} }
$records = $DB->get_records("local_treestudyplan_coach",["user_id" => $userid]); $records = $DB->get_records("local_treestudyplan_coach", ["user_id" => $userid]);
$list = []; $list = [];
foreach ($records as $r) { foreach ($records as $r) {
try { try {
$studyplan = studyplan::find_by_id($r->studyplan_id); $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(); $list[] = $studyplan->simple_model_coach();
} }
} catch(\Exception $x) {} } catch(\Exception $x) {}
@ -584,7 +584,7 @@ class studentstudyplanservice extends \external_api {
/** /**
* Parameter description for webservice function get_teaching_studyplan * 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( [ return new \external_function_parameters( [
"studyplanid" => new \external_value(PARAM_INT, 'id of specific studyplan to provide', VALUE_DEFAULT), "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 * 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(); return studyplan::editor_structure();
} }
@ -625,7 +625,7 @@ class studentstudyplanservice extends \external_api {
/** /**
* Parameter description for webservice function get_teaching_page * 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( [ return new \external_function_parameters( [
"pageid" => new \external_value(PARAM_INT, 'id of specific studyplan page to provide', VALUE_DEFAULT), "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 * 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(); return studyplanpage::editor_structure();
} }
@ -667,7 +667,7 @@ class studentstudyplanservice extends \external_api {
/** /**
* Parameter description for webservice function get_teaching_page * 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( [ return new \external_function_parameters( [
"id" => new \external_value(PARAM_INT, 'id of specific studyline to enrol into'), "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 * 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(); return studyline::enrol_info_structure();
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -33,7 +33,6 @@ class teachingfinder {
/** @var string */ /** @var string */
const TABLE = "local_treestudyplan_teachers"; const TABLE = "local_treestudyplan_teachers";
/** /**
* List all studyplans the current user is teaching * List all studyplans the current user is teaching
* (Updates the cache if no results are found the first time) * (Updates the cache if no results are found the first time)
@ -62,7 +61,7 @@ class teachingfinder {
* @param studyplan $plan Studyplan to check * @param studyplan $plan Studyplan to check
* @return bool If teaching in this plan * @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; global $DB;
$count = $DB->count_records(self::TABLE, ['teacher_id' => $userid, "studyplan_id" => $plan->id()]); $count = $DB->count_records(self::TABLE, ['teacher_id' => $userid, "studyplan_id" => $plan->id()]);
return ($count > 0)?true:false; return ($count > 0)?true:false;
@ -80,7 +79,6 @@ class teachingfinder {
return ($count > 0)?true:false; return ($count > 0)?true:false;
} }
/** /**
* Check if current user is teaching in a specific studyplan * Check if current user is teaching in a specific studyplan
* (Does not update the cache if results are 0) * (Does not update the cache if results are 0)
@ -89,7 +87,7 @@ class teachingfinder {
*/ */
public static function am_teaching_studyplan(studyplan $plan) { public static function am_teaching_studyplan(studyplan $plan) {
global $USER; 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); return self::is_teaching($USER->id);
} }
/** /**
* Check if a user is teaching in a specific course * Check if a user is teaching in a specific course
* @param int $courseid ID of the course * @param int $courseid ID of the course
* @param int $userid ID of the user * @param int $userid ID of the user
@ -114,14 +112,14 @@ class teachingfinder {
return is_enrolled($coursecontext, $userid, 'mod/assign:grade'); return is_enrolled($coursecontext, $userid, 'mod/assign:grade');
} }
/** /**
* Check if current user is teaching in a specific course * Check if current user is teaching in a specific course
* @param int $courseid ID of the course * @param int $courseid ID of the course
* @return bool True if teaching in the course * @return bool True if teaching in the course
*/ */
public static function am_teaching_course($courseid) { public static function am_teaching_course($courseid) {
global $USER; 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"; const CAP_VIEW = "local/treestudyplan:viewuserreports";
protected static function load_mform($formname, $params, $ajaxformdata = null) { protected static function load_mform($formname, $params, $ajaxformdata = null) {
global $CFG; global $CFG;
/* We don't need to load the form php file (class autoloading will handle that) /* 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 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"; $modmoodleform = "$CFG->dirroot/local/treestudyplan/classes/form/{$formname}.php";
if (!file_exists($modmoodleform)) { 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}"; $mformclassname = "\\local_treestudyplan\\form\\{$formname}";
// Check if the form is a subclass of formbase. // 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); $jsonparams = json_decode($params);
$mform = new $mformclassname( $jsonparams, $ajaxformdata); $mform = new $mformclassname( $jsonparams, $ajaxformdata);
return $mform; return $mform;
@ -92,8 +91,7 @@ class utilityservice extends \external_api {
global $OUTPUT, $PAGE, $CFG; global $OUTPUT, $PAGE, $CFG;
\external_api::validate_context(\context_system::instance()); \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. // Hack alert: Set a default URL to stop the annoying debug.
$PAGE->set_url('/'); $PAGE->set_url('/');
@ -106,7 +104,7 @@ class utilityservice extends \external_api {
// Load the form before any output is started. // Load the form before any output is started.
$mform = self::load_mform($formname, $params); $mform = self::load_mform($formname, $params);
// Perform actual render. // Perform actual render.
$html = $mform->render(); $html = $mform->render();
$jsfooter = $PAGE->requires->get_end_code(); $jsfooter = $PAGE->requires->get_end_code();
$output = ['html' => $html, 'javascript' => $jsfooter]; $output = ['html' => $html, 'javascript' => $jsfooter];
@ -130,7 +128,7 @@ class utilityservice extends \external_api {
/** /**
* Parameter description for webservice function submit_cm_editform * 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( [ return new \external_function_parameters( [
'formname' => new \external_value(PARAM_COMPONENT, 'name of the treestudyplan form to parse'), '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'), '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 * 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. 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) { public static function submit_mform($formname, $params, $formdata) {
\external_api::validate_context(\context_system::instance()); \external_api::validate_context(\context_system::instance());
require_login(null,false,null); require_login(null, false, null);
$ajaxformdata = []; $ajaxformdata = [];
parse_str($formdata,$ajaxformdata); parse_str($formdata, $ajaxformdata);
// Load the form, provide submitted form data and perform security checks // Load the form, provide submitted form data and perform security checks
$mform = self::load_mform($formname, $params, $ajaxformdata); $mform = self::load_mform($formname, $params, $ajaxformdata);
$return = $mform->process_submission(); $return = $mform->process_submission();
// Pass form processing result as success data component. // Pass form processing result as success data component.
return success::success($return)->model(); return success::success($return)->model();
} }
/** /**
* Parameter description for webservice function submit_cm_editform * 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( [ return new \external_function_parameters( [
] ); ] );
} }
@ -179,7 +176,7 @@ class utilityservice extends \external_api {
/** /**
* Return value description for webservice function submit_cm_editform * 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([ return new \external_single_structure([
"hivizdropslots" => new \external_value(PARAM_BOOL, 'High visibility drop slots for items'), "hivizdropslots" => new \external_value(PARAM_BOOL, 'High visibility drop slots for items'),
"toolboxleft" => new \external_value(PARAM_BOOL, 'Start toolbox default on left side'), "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() { public static function getsettings() {
\external_api::validate_context(\context_system::instance()); \external_api::validate_context(\context_system::instance());
require_login(null,false,null); require_login(null, false, null);
return [ return [
"hivizdropslots" => get_config("local_treestudyplan","hivizdropslots"), "hivizdropslots" => get_config("local_treestudyplan", "hivizdropslots"),
"toolboxleft" => get_config("local_treestudyplan","toolboxleft") "toolboxleft" => get_config("local_treestudyplan", "toolboxleft")
]; ];
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -26,7 +26,7 @@ require_once($CFG->libdir.'/weblib.php');
$systemcontext = context_system::instance(); $systemcontext = context_system::instance();
$PAGE->set_url("/local/treestudyplan/doc.php", array()); $PAGE->set_url("/local/treestudyplan/doc.php", []);
if ($CFG->debugdeveloper) { if ($CFG->debugdeveloper) {
$PAGE->requires->css(new moodle_url($CFG->wwwroot.'/local/treestudyplan/css/devstyles.css')); $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)) { } 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; $data->update = $update;
if (empty($data) || $data->user_id != $USER->id) { if (empty($data) || $data->user_id != $USER->id) {
throw new \moodle_exception('invalidaction', 'local_treestudyplan');; throw new \moodle_exception('invalidaction', 'local_treestudyplan');;
@ -64,7 +64,7 @@ if (!empty($add)) {
} }
} else if (!empty($resend)) { } 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; $data->resend = $resend;
if (empty($data) || $data->user_id != $USER->id) { if (empty($data) || $data->user_id != $USER->id) {
throw new \moodle_exception('invalidaction', 'local_treestudyplan');; throw new \moodle_exception('invalidaction', 'local_treestudyplan');;
@ -77,7 +77,7 @@ if (!empty($add)) {
print $OUTPUT->footer(); print $OUTPUT->footer();
exit; exit;
} else if (!empty($delete)) { } 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; $data->delete = $delete;
if (empty($data) || $data->user_id != $USER->id) { if (empty($data) || $data->user_id != $USER->id) {
throw new \moodle_exception('invalidaction', 'local_treestudyplan');; throw new \moodle_exception('invalidaction', 'local_treestudyplan');;

View File

@ -31,7 +31,7 @@ use local_treestudyplan\debug;
$systemcontext = context_system::instance(); $systemcontext = context_system::instance();
$PAGE->set_url("/local/treestudyplan/edit-plan.php", array()); $PAGE->set_url("/local/treestudyplan/edit-plan.php", []);
require_login(); require_login();
// Figure out the context (category or system, based on either category or context parameter). // 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')); $PAGE->navbar->add(get_string('cfg_plans', 'local_treestudyplan'));
// Coursecat context // Coursecat context
$cat = \core_course_category::get($studyplancontext->instanceid,IGNORE_MISSING,true); // We checck visibility later $cat = \core_course_category::get($studyplancontext->instanceid, IGNORE_MISSING, true); // We checck visibility later
} else { } else {
// System context // System context
$cat = \core_course_category::top(); $cat = \core_course_category::top();
} }
if (!$cat->is_uservisible()) { 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)) { 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. // 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->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, [ $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-cloak>
<div v-if='!activestudyplan && usedcontexts && !loadingstudyplan' class='ml-3 mb-3 s-context-selector'> <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' <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" <b-form-select-option v-if='!(usedcontexts.length)' :value="contextid"
:class="'text-primary'"> :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" <b-form-select-option v-for='ctx in usedcontexts' :key='ctx.id' :value="ctx.context_id"
:class="(ctx.studyplancount > 0) ? 'font-weight-bold' : ''" :class="(ctx.studyplancount > 0) ? 'font-weight-bold' : ''"
><span v-for="(p, i) in ctx.category.path" ><span v-for="(p, i) in ctx.category.path"
><span v-if="i>0"> / </span>{{ p }}</span> <span>({{ ctx.studyplancount }})</span> ><span v-if="i>0"> / </span>{{ p }}</span> <span>({{ ctx.studyplancount }})</span>
</b-form-select-option> </b-form-select-option>
</b-form-select> </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> class="spinner-border text-primary" role="status"></div>
</div> </div>
@ -154,15 +154,15 @@ print $OUTPUT->header();
v-model="create.studyplan" v-model="create.studyplan"
type="button" type="button"
variant="primary" variant="primary"
default-aggregation="<?php print(get_config("local_treestudyplan","aggregation_mode")); ?>" default-aggregation="<?php print(get_config("local_treestudyplan", "aggregation_mode")); ?>"
:contextid='contextid' :contextid='contextid'
><i class='fa fa-plus'></i> {{ text.studyplan_add }}</t-studyplan-edit> ><i class='fa fa-plus'></i> {{ text.studyplan_add }}</t-studyplan-edit>
<b-button <b-button
variant='danger' href='#' role='presentation' @click="import_studyplan " variant='danger' href='#' role='presentation' @click="import_studyplan "
><i class='fa fa-upload'></i> {{ text.advanced_import_from_file }}</b-button ><i class='fa fa-upload'></i> {{ text.advanced_import_from_file }}</b-button
><mform v-if="premiumenabled && templatecount > 0" ><mform v-if="premiumenabled && templatecount > 0"
name="studyplan_fromtemplateform" name="studyplan_fromtemplateform"
:params="{contextid: contextid }" :params="{contextid: contextid }"
@saved="onStudyPlanCreated" @saved="onStudyPlanCreated"
variant="success" variant="success"
type="button" type="button"

View File

@ -31,7 +31,7 @@ $invitedurl = "/local/treestudyplan/invited.php";
$systemcontext = context_system::instance(); $systemcontext = context_system::instance();
$PAGE->set_url("/local/treestudyplan/invitations.php", array()); $PAGE->set_url("/local/treestudyplan/invitations.php", []);
require_login(); require_login();
$PAGE->set_pagelayout('base'); $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. // Retrieve list of courses that the student is enrolled in.
$sent = optional_param('sent', '', PARAM_INT); $sent = optional_param('sent', '', PARAM_INT);
if (!empty($sent)) { 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)); \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_title(get_string('accessdenied', 'admin'));
$PAGE->set_heading(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). // Render page for skill level 0 (global).
print "<div class='box errorbox alert alert-danger'>"; print "<div class='box errorbox alert alert-danger'>";
print get_string('accessdenied','admin'); print get_string('accessdenied', 'admin');
print "</div>"; print "</div>";
print $OUTPUT->footer(); print $OUTPUT->footer();
@ -71,7 +71,7 @@ if (!get_config("local_treestudyplan","enableplansharing")) {
print "<p>".get_string('invite_description', 'local_treestudyplan')."</p>"; 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 "<h3>".get_string('invite_tablecaption', 'local_treestudyplan')."</h3>";
print "<table class='m-manage_invites'>"; 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. // See if we can get a valid user for this invited.
$invitekey = optional_param('key', '', PARAM_ALPHANUM); // Module name. $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", $invite = $DB->get_record_select("local_treestudyplan_invit",
$DB->sql_compare_text("invitekey"). " = " . $DB->sql_compare_text(":invitekey"), $DB->sql_compare_text("invitekey"). " = " . $DB->sql_compare_text(":invitekey"),
['invitekey' => $invitekey]); ['invitekey' => $invitekey]);
if (!get_config("local_treestudyplan","enableplansharing")) { if (!get_config("local_treestudyplan", "enableplansharing")) {
$PAGE->set_title(get_string('accessdenied', 'admin')); $PAGE->set_title(get_string('accessdenied', 'admin'));
$PAGE->set_heading(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). // Render page for skill level 0 (global).
print "<div class='box errorbox alert alert-danger'>"; print "<div class='box errorbox alert alert-danger'>";
print get_string('accessdenied','admin'); print get_string('accessdenied', 'admin');
print "</div>"; print "</div>";
print $OUTPUT->footer(); 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]); $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_title(get_string('report_invited', 'local_treestudyplan', "{$student->firstname} {$student->lastname}" ));
$PAGE->set_heading(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_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_subject"] = 'Shared grade card of {$a->sender}';
$string["invite_mail_text"] = ' $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>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>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> <p>Click the link below to view the study plan:<br>
<a href="{$a->link}">{$a->link}</a></p> <a href="{$a->link}">{$a->link}</a></p>
<p>Kind regards,<br> <p>Kind regards, <br>
{$a->sender}</p> {$a->sender}</p>
'; ';
@ -271,7 +271,6 @@ $string["studyplan_past"] = "Past study plans";
$string["studyplan_present"] = "Current study plans"; $string["studyplan_present"] = "Current study plans";
$string["studyplan_future"] = "Upcoming study plans"; $string["studyplan_future"] = "Upcoming study plans";
$string["link_myreport"] = "My study plan"; $string["link_myreport"] = "My study plan";
$string["link_viewplan"] = "Study plans"; $string["link_viewplan"] = "Study plans";
$string["link_editplan"] = "Manage 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"] = '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_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_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_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"; $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["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["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: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: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.'; $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:lineunenrol"] = "Beheer inschrijvingen van studenten in leerlijnen";
$string["treestudyplan:coach"] = "Beschikbaar als coach"; $string["treestudyplan:coach"] = "Beschikbaar als coach";
$string["report"] = 'Voortgangsrapport'; $string["report"] = 'Voortgangsrapport';
$string["report_invited"] = 'Voortgang van {$a}'; $string["report_invited"] = 'Voortgang van {$a}';
$string["report_index"] = 'Studieplannen van studenten inzien'; $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_title"] = 'Cursuscompetenties';
$string["competency_aggregator_desc"] = 'Gebruik de bij de cursus ingestelde competenties'; $string["competency_aggregator_desc"] = 'Gebruik de bij de cursus ingestelde competenties';
$string["setting_bistate_heading"] = 'Standaardwaarden voor Behaald + Vereiste leerdoelen '; $string["setting_bistate_heading"] = 'Standaardwaarden voor Behaald + Vereiste leerdoelen ';
$string["settingdesc_bistate_heading"] = 'Stel de standaardwaarden in voor deze verzamelmethode'; $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["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["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_include"] = 'Doel';
$string["grade_require"] = 'Verplicht'; $string["grade_require"] = 'Verplicht';
$string["required_goal"] = 'Verplicht leerdoel'; $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]; 'trusttext' => 0];
} }
/** /**
* Create primary navigation links for studyplan if needed * 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/view-plan.php" => ["included" => false, "strkey" => "link_viewplan"],
"/local/treestudyplan/edit-plan.php" => ["included" => false, "strkey" => "link_editplan"], "/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 // Also include the coach role if enabled
$navitems["/local/treestudyplan/coach.php"] = ["included" => false, "strkey" => "link_coach"]; $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. Studieplannen beheren|/local/treestudyplan/edit-plan.php.
Using some javascript magic we'll hide the links that are not accessible. 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). 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. 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. // Create studyplan node.
$node = navigation_node::create( $node = navigation_node::create(
get_string("link_myreport", "local_treestudyplan"), 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, global_navigation::TYPE_SYSTEM,
null, null,
"local_treestudyplan_myreport", "local_treestudyplan_myreport",
@ -152,7 +151,7 @@ function local_treestudyplan_extend_navigation(global_navigation $navigation) {
// Create invitenode node. // Create invitenode node.
$invitenode = navigation_node::create( $invitenode = navigation_node::create(
get_string("manage_invites", "local_treestudyplan"), 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 , global_navigation::TYPE_CUSTOM ,
null, null,
"local_treestudyplan_invitemgmt", "local_treestudyplan_invitemgmt",
@ -169,7 +168,7 @@ function local_treestudyplan_extend_navigation(global_navigation $navigation) {
|| webservicehelper::has_capability_in_any_category('local/treestudyplan:viewuserreports')) { || webservicehelper::has_capability_in_any_category('local/treestudyplan:viewuserreports')) {
$node = navigation_node::create( $node = navigation_node::create(
get_string("link_viewplan", "local_treestudyplan"), 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 , global_navigation::TYPE_SYSTEM ,
null, null,
"local_treestudyplan_viewplan", "local_treestudyplan_viewplan",
@ -186,7 +185,7 @@ function local_treestudyplan_extend_navigation(global_navigation $navigation) {
) { ) {
$node = navigation_node::create( $node = navigation_node::create(
get_string("link_editplan", "local_treestudyplan"), 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 , global_navigation::TYPE_SYSTEM ,
null, null,
"local_treestudyplan_editplan", "local_treestudyplan_editplan",
@ -198,19 +197,19 @@ function local_treestudyplan_extend_navigation(global_navigation $navigation) {
} else { } else {
$hideprimaryhrefs[] = "/local/treestudyplan/edit-plan.php"; $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 INNER JOIN {local_treestudyplan} AS t ON c.studyplan_id = t.id
WHERE c.user_id = :user_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()) (has_capability('local/treestudyplan:coach', context_system::instance())
|| webservicehelper::has_capability_in_any_category('local/treestudyplan:coach') || 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( $node = navigation_node::create(
get_string("link_coach", "local_treestudyplan"), 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 , global_navigation::TYPE_SYSTEM ,
null, null,
"local_treestudyplan_coach", "local_treestudyplan_coach",
@ -231,7 +230,7 @@ function local_treestudyplan_extend_navigation(global_navigation $navigation) {
// Create invitenode node. // Create invitenode node.
$invitenode = navigation_node::create( $invitenode = navigation_node::create(
get_string("nav_invited", "local_treestudyplan"), 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 , global_navigation::TYPE_USER ,
null, null,
"local_treestudyplan_invitemgmt", "local_treestudyplan_invitemgmt",
@ -315,7 +314,7 @@ function local_treestudyplan_reset_fontawesome_icon_map() {
*/ */
function local_treestudyplan_send_invite($inviteid) { function local_treestudyplan_send_invite($inviteid) {
global $DB, $USER, $CFG; 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); $noreply = 'noreply@' . get_host_from_url($CFG->wwwroot);
$mailer = get_mailer(); $mailer = get_mailer();
@ -433,20 +432,18 @@ function local_treestudyplan_pluginfile(
bool $forcedownload, bool $forcedownload,
array $options = [] array $options = []
): bool { ): bool {
global $DB,$USER; global $DB, $USER;
$studyplanfilecaps = ["local/treestudyplan:editstudyplan", "local/treestudyplan:viewuserreports"];
$studyplan_filecaps = ["local/treestudyplan:editstudyplan","local/treestudyplan:viewuserreports"];
// Check the contextlevel is as expected - the studyplan plugin only uses system context for storing files. // 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) { if ($context->contextlevel != CONTEXT_SYSTEM) {
return false; return false;
} }
// Make sure the filearea is one of those used by the plugin. // 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]. // The args is an array containing [itemid, path].
// Fetch the itemid from the path. // Fetch the itemid from the path.
$itemid = array_shift($args); $itemid = array_shift($args);
@ -476,7 +473,7 @@ function local_treestudyplan_pluginfile(
return false; return false;
} }
} else if (in_array($filearea,['defaulticon'])) { } else if (in_array($filearea, ['defaulticon'])) {
// The args is an array containing [itemid, path]. // The args is an array containing [itemid, path].
// Fetch the itemid from the path. // Fetch the itemid from the path.
$itemid = array_shift($args); $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(); $systemcontext = context_system::instance();
$PAGE->set_url("/local/treestudyplan/myreport.php", array()); $PAGE->set_url("/local/treestudyplan/myreport.php", []);
require_login(); require_login();
$PAGE->set_pagelayout('base'); $PAGE->set_pagelayout('base');
$PAGE->set_context($systemcontext); $PAGE->set_context($systemcontext);
//$teachermode = has_capability("local/treestudyplan:viewuserreports", $systemcontext); //$teachermode = has_capability("local/treestudyplan:viewuserreports", $systemcontext);
$am_teaching = teachingfinder::is_teaching($USER->id); $amteaching = teachingfinder::is_teaching($USER->id);
$have_plans = studyplan::exist_for_user($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_title(get_string('myreport_teachermode', 'local_treestudyplan'));
$PAGE->set_heading(get_string('myreport_teachermode', 'local_treestudyplan')); $PAGE->set_heading(get_string('myreport_teachermode', 'local_treestudyplan'));
} else { } else {
@ -52,7 +52,7 @@ $PAGE->requires->css(new moodle_url($CFG->wwwroot.'/local/treestudyplan/css/boot
if ($CFG->debugdeveloper) { if ($CFG->debugdeveloper) {
$PAGE->requires->css(new moodle_url($CFG->wwwroot.'/local/treestudyplan/css/devstyles.css')); $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 * Shortcut function to provide translations
@ -70,7 +70,7 @@ print $OUTPUT->header();
print '<div class="m-buttonbar" style="margin-bottom: 1em; text-align: right;">'; 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 '<a class="btn btn-primary" href="invitations.php" id="manage_invites">';
print '&nbsp;<i class="fa fa-share"></i>&nbsp;'.t('manage_invites').'</a>'; 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>"; print " </div>";
print " <div v-cloak>"; print " <div v-cloak>";
if ($am_teaching) { if ($amteaching) {
print " <r-report type='teaching' teachermode ></r-report>"; print " <r-report type='teaching' teachermode ></r-report>";
} else { } else {
print " <r-report type='own' :userid='userid'></r-report>"; 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 // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <https://www.gnu.org/licenses/>. // along with Moodle. If not, see <https://www.gnu.org/licenses/>.
/** /**
* Report * Report
* @package local_treestudyplan * @package local_treestudyplan
* @copyright 2023 P.M. Kuipers * @copyright 2023 P.M. Kuipers
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @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 $firstperiod = optional_param('firstperiod', 0, PARAM_INT); // First period to show
$lastperiod = optional_param('lastperiod', 0, PARAM_INT); // Last periode to show $lastperiod = optional_param('lastperiod', 0, PARAM_INT); // Last periode to show
$PAGE->set_pagelayout('report'); $PAGE->set_pagelayout('report');
$PAGE->set_title(get_string('studyplan_report', 'local_treestudyplan')); $PAGE->set_title(get_string('studyplan_report', 'local_treestudyplan'));
$PAGE->set_heading(get_string('studyplan_report', 'local_treestudyplan')); $PAGE->set_heading(get_string('studyplan_report', 'local_treestudyplan'));
if (!premium::enabled()) { 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)) { if (!has_capability('local/treestudyplan:viewuserreports', $context)) {
throw new \moodle_exception("error:nostudyplanviewaccess","local_treestudyplan","",$contextname); throw new \moodle_exception("error:nostudyplanviewaccess", "local_treestudyplan", "", $contextname);
} }
// Load javascripts and specific css. // 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]); $PAGE->requires->js_call_amd('local_treestudyplan/page-result-overview', 'init', [$studyplan->id(), $page->id(), $firstperiod, $lastperiod]);
/** /**
* Shortcut function to provide translations * Shortcut function to provide translations
* *
@ -80,8 +77,8 @@ function t($str, $param = null, $plugin = 'local_treestudyplan') {
} }
print $OUTPUT->header(); print $OUTPUT->header();
print "<h3><b>{$contextname}</b> / {$studyplan->name()}</h3>"; print "<h3><b>{$contextname}</b> / {$studyplan->name()}</h3>";
if($studyplan->name() != $page->fullname()) { if ($studyplan->name() != $page->fullname()) {
print "<h4>{$page->fullname()}</h4>"; print "<h4>{$page->fullname()}</h4>";
} }
?> ?>
@ -104,8 +101,8 @@ if($studyplan->name() != $page->fullname()) {
<div class="col-sm-6"> <div class="col-sm-6">
<select class="custom-select" :value="page.id" @change="selectedPage"> <select class="custom-select" :value="page.id" @change="selectedPage">
<template v-if="studyplan"> <template v-if="studyplan">
<option v-for="p in studyplan.pages" <option v-for="p in studyplan.pages"
:key="p.id" :key="p.id"
:value="p.id" :value="p.id"
:selected="(page.id == p.id)?true:false" :selected="(page.id == p.id)?true:false"
>{{p.fullname}}</option> >{{p.fullname}}</option>
@ -119,8 +116,8 @@ if($studyplan->name() != $page->fullname()) {
<div class="col-sm-2"> <div class="col-sm-2">
<select class="custom-select" @change="selectedFirstPeriod"> <select class="custom-select" @change="selectedFirstPeriod">
<template v-if="page"> <template v-if="page">
<option v-for="p in page.perioddesc" <option v-for="p in page.perioddesc"
:key="p.id" :key="p.id"
:value="p.period" :value="p.period"
:selected="(structure.firstperiod == p.period)?true:false" :selected="(structure.firstperiod == p.period)?true:false"
>{{p.fullname}}</option> >{{p.fullname}}</option>
@ -133,7 +130,7 @@ if($studyplan->name() != $page->fullname()) {
<template v-if="page"> <template v-if="page">
<template v-for="p in page.perioddesc"> <template v-for="p in page.perioddesc">
<option v-if="p.period >= structure.firstperiod" <option v-if="p.period >= structure.firstperiod"
:key="p.id" :key="p.id"
:value="p.period" :value="p.period"
:selected="(structure.lastperiod == p.period)?true:false" :selected="(structure.lastperiod == p.period)?true:false"
>{{p.fullname}}</option> >{{p.fullname}}</option>

View File

@ -6,7 +6,7 @@
// the Free Software Foundation, either version 3 of the License, or. // the Free Software Foundation, either version 3 of the License, or.
// (at your option) any later version. // (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. // but WITHOUT ANY WARRANTY; without even the implied warranty of.
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the.
// GNU General Public License for more details. // GNU General Public License for more details.
@ -56,12 +56,12 @@ if ($hassiteconfig) {
)); ));
// Default image for study plans // Default image for study plans
$page->add(new admin_setting_configstoredfile('local_treestudyplan/defaulticon', $page->add(new admin_setting_configstoredfile('local_treestudyplan/defaulticon',
get_string('setting_defaulticon', 'local_treestudyplan'), get_string('setting_defaulticon', 'local_treestudyplan'),
get_string('settingdesc_defaulticon', 'local_treestudyplan'), get_string('settingdesc_defaulticon', 'local_treestudyplan'),
'defaulticon', 0, 'defaulticon', 0,
[ [
'maxfiles' => 1, 'maxfiles' => 1,
'accepted_types' => ['.jpg', '.png']] 'accepted_types' => ['.jpg', '.png']]
)); ));
@ -89,7 +89,7 @@ if ($hassiteconfig) {
get_string('settingdesc_display_heading', 'local_treestudyplan') 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")]; $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'); $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', $page->add(new admin_setting_configcheckbox('local_treestudyplan/enableplansharing',
get_string('setting_enableplansharing', 'local_treestudyplan'), get_string('setting_enableplansharing', 'local_treestudyplan'),
get_string('settingdesc_enableplansharing', 'local_treestudyplan'), get_string('settingdesc_enableplansharing', 'local_treestudyplan'),
true, true,
)); ));
//get_config("local_treestudyplan","timelessperiods") //get_config("local_treestudyplan", "timelessperiods")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/timelessperiods', $page->add(new admin_setting_configcheckbox('local_treestudyplan/timelessperiods',
get_string('setting_timelessperiods', 'local_treestudyplan'), get_string('setting_timelessperiods', 'local_treestudyplan'),
get_string('settingdesc_timelessperiods', 'local_treestudyplan'), get_string('settingdesc_timelessperiods', 'local_treestudyplan'),
false, false,
)); ));
//get_config("local_treestudyplan","limitcourselist") //get_config("local_treestudyplan", "limitcourselist")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/limitcourselist', $page->add(new admin_setting_configcheckbox('local_treestudyplan/limitcourselist',
get_string('setting_limitcourselist', 'local_treestudyplan'), get_string('setting_limitcourselist', 'local_treestudyplan'),
get_string('settingdesc_limitcourselist', 'local_treestudyplan'), get_string('settingdesc_limitcourselist', 'local_treestudyplan'),
false, false,
)); ));
//get_config("local_treestudyplan","hivizdropslots") //get_config("local_treestudyplan", "hivizdropslots")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/hivizdropslots', $page->add(new admin_setting_configcheckbox('local_treestudyplan/hivizdropslots',
get_string('setting_hivizdropslots', 'local_treestudyplan'), get_string('setting_hivizdropslots', 'local_treestudyplan'),
get_string('settingdesc_hivizdropslots', 'local_treestudyplan'), get_string('settingdesc_hivizdropslots', 'local_treestudyplan'),
false, false,
)); ));
//get_config("local_treestudyplan","toolboxleft") //get_config("local_treestudyplan", "toolboxleft")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/toolboxleft', $page->add(new admin_setting_configcheckbox('local_treestudyplan/toolboxleft',
get_string('setting_toolboxleft', 'local_treestudyplan'), get_string('setting_toolboxleft', 'local_treestudyplan'),
get_string('settingdesc_toolboxleft', 'local_treestudyplan'), get_string('settingdesc_toolboxleft', 'local_treestudyplan'),
true, true,
)); ));
//get_config("local_treestudyplan","copystudylinesnewpage") //get_config("local_treestudyplan", "copystudylinesnewpage")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/copystudylinesnewpage', $page->add(new admin_setting_configcheckbox('local_treestudyplan/copystudylinesnewpage',
get_string('setting_copystudylinesnewpage', 'local_treestudyplan'), get_string('setting_copystudylinesnewpage', 'local_treestudyplan'),
get_string('settingdesc_copystudylinesnewpage', 'local_treestudyplan'), get_string('settingdesc_copystudylinesnewpage', 'local_treestudyplan'),
false, false,
)); ));
//get_config("local_treestudyplan","continueperiodnumberingnewpage") //get_config("local_treestudyplan", "continueperiodnumberingnewpage")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/continueperiodnumberingnewpage', $page->add(new admin_setting_configcheckbox('local_treestudyplan/continueperiodnumberingnewpage',
get_string('setting_continueperiodnumberingnewpage', 'local_treestudyplan'), get_string('setting_continueperiodnumberingnewpage', 'local_treestudyplan'),
get_string('settingdesc_continueperiodnumberingnewpage', 'local_treestudyplan'), get_string('settingdesc_continueperiodnumberingnewpage', 'local_treestudyplan'),
@ -156,7 +156,7 @@ if ($hassiteconfig) {
)); ));
if (premium::enabled()) { if (premium::enabled()) {
//get_config("local_treestudyplan","enablecoach") //get_config("local_treestudyplan", "enablecoach")
$page->add(new admin_setting_configcheckbox('local_treestudyplan/enablecoach', $page->add(new admin_setting_configcheckbox('local_treestudyplan/enablecoach',
get_string('setting_enablecoach', 'local_treestudyplan'), get_string('setting_enablecoach', 'local_treestudyplan'),
get_string('settingdesc_enablecoach', 'local_treestudyplan'), get_string('settingdesc_enablecoach', 'local_treestudyplan'),
@ -182,8 +182,8 @@ if ($hassiteconfig) {
get_string('settingdesc_infofields_heading', 'local_treestudyplan') get_string('settingdesc_infofields_heading', 'local_treestudyplan')
)); ));
$positions = [ "above" => get_string('infofield_position_above', 'local_treestudyplan'), $positions = [ "above" => get_string('infofield_position_above', 'local_treestudyplan'),
"below" => get_string("infofield_position_below", 'local_treestudyplan'), "below" => get_string("infofield_position_below", 'local_treestudyplan'),
]; ];
for ($i=1;$i<=5;$i++) { for ($i=1;$i<=5;$i++) {
@ -211,19 +211,19 @@ if ($hassiteconfig) {
get_string('setting_competency_displayname', 'local_treestudyplan'), get_string('setting_competency_displayname', 'local_treestudyplan'),
get_string('settingdesc_competency_displayname', 'local_treestudyplan'), get_string('settingdesc_competency_displayname', 'local_treestudyplan'),
"idnumber", "idnumber",
["shortname" => get_string("name","core",), ["shortname" => get_string("name", "core", ),
"idnumber" => get_string("idnumber","core",), "idnumber" => get_string("idnumber", "core", ),
"description" => get_string("description","core",)] "description" => get_string("description", "core", )]
)); ));
$page->add(new admin_setting_configselect('local_treestudyplan/competency_detailfield', $page->add(new admin_setting_configselect('local_treestudyplan/competency_detailfield',
get_string('setting_competency_detailfield', 'local_treestudyplan'), get_string('setting_competency_detailfield', 'local_treestudyplan'),
get_string('settingdesc_competency_detailfield', 'local_treestudyplan'), get_string('settingdesc_competency_detailfield', 'local_treestudyplan'),
"shortname", "shortname",
["" => get_string("none","core",), ["" => get_string("none", "core", ),
"shortname" => get_string("name","core",), "shortname" => get_string("name", "core", ),
"idnumber" => get_string("idnumber","core",), "idnumber" => get_string("idnumber", "core", ),
"description" => get_string("description","core",)] "description" => get_string("description", "core", )]
)); ));
$page->add(new admin_setting_heading('local_treestudyplan/competency_aggregation_heading', $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), get_string('cfg_help', 'local_treestudyplan', null, true),
$CFG->wwwroot . '/local/treestudyplan/doc.php/index.htm')); $CFG->wwwroot . '/local/treestudyplan/doc.php/index.htm'));
/************************************** /**************************************
* *
* Settings page: Premium registration * Settings page: Premium registration
@ -418,7 +417,6 @@ if ($hassiteconfig) {
)); ));
} }
// Add settings page2 to the admin settings category. // Add settings page2 to the admin settings category.
$ADMIN->add('local_treestudyplan', $pagepremium); $ADMIN->add('local_treestudyplan', $pagepremium);
} }

View File

@ -1,11 +1,11 @@
<?php <?php
function sitematch($key,$site){ function sitematch($key, $site) {
// Add double slashes to key and site if no scheme is set. // Add double slashes to key and site if no scheme is set.
// Basically: if no double slashes present before any dots,shashes or @s. // Basically: if no double slashes present before any dots, shashes or @s.
if(!\preg_match_all('#^[^./@]*?//#',$key )) { if (!\preg_match_all('#^[^./@]*?//#', $key )) {
$key = "//".$key; $key = "//".$key;
} }
if(!\preg_match_all('#^[^./@]*?//#',$site)) { if (!\preg_match_all('#^[^./@]*?//#', $site)) {
$site = "//".$site; $site = "//".$site;
} }
// Use parse_url() to split path and host. // Use parse_url() to split path and host.
@ -23,17 +23,17 @@ function sitematch($key,$site){
} }
// First match the host part. // First match the host part.
$keyparts = \array_reverse(\explode(".",$keyurl->host)); $keyparts = \array_reverse(\explode(".", $keyurl->host));
$siteparts = \array_reverse(\explode(".",$siteurl->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. // 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($keyparts)) != "www") {\array_push($keyparts, $x);}
if (($x = \array_pop($siteparts)) != "www") {\array_push($siteparts,$x);} if (($x = \array_pop($siteparts)) != "www") {\array_push($siteparts, $x);}
for ($i = 0; $i < count($keyparts); $i++) { 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 * // No match if the site does not have a part, but the key does. Unless the key part is *
if (!isset($siteparts[$i]) ) { if (!isset($siteparts[$i]) ) {
if($keyparts[$i] != "*") { if ($keyparts[$i] != "*") {
return false; return false;
} else { } else {
$i++; //increment $i by one before break, to make sure the comparison following this loop holds. $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. // Now do a proper case insensitive check for matching.
// Uses fnmatch to easily handle shell type wildcards. // 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; 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 we made it here then the host part matches. Now check the path.
// If path is /*, matches all subpaths including / // If path is /*, matches all subpaths including /
$keypath = empty($keyurl->path)?"/":$keyurl->path; $keypath = empty($keyurl->path) ? "/" : $keyurl->path;
$sitepath = empty($siteurl->path)?"/":$siteurl->path; $sitepath = empty($siteurl->path) ? "/" : $siteurl->path;
// Trim trailing / from both paths before comparison // Trim trailing / from both paths before comparison
if (\strlen($sitepath) > 1) { if (\strlen($sitepath) > 1) {
$sitepath = \rtrim($sitepath,"/"); $sitepath = \rtrim($sitepath, "/");
} }
if (\strlen($keypath) > 1) { if (\strlen($keypath) > 1) {
$keypath = \rtrim($keypath,"/"); $keypath = \rtrim($keypath, "/");
} }
// Do a case insensitive fnmatch on the site so wildcards are matched too. // 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 = [ $tests = [
@ -74,10 +74,10 @@ $tests = [
["*/*", "https://www.miqra.nl"], ["*/*", "https://www.miqra.nl"],
["*", "https://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/"],
["clients.openedu.nl/fith/", "https://clients.openedu.nl/fith"] ["clients.openedu.nl/fith/", "https://clients.openedu.nl/fith"],
]; ];
foreach($tests as $test) { foreach($tests as $test) {
[$key, $site] = $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(); $systemcontext = context_system::instance();
$PAGE->set_url("/local/treestudyplan/view-plan.php", array()); $PAGE->set_url("/local/treestudyplan/view-plan.php", []);
require_login(); require_login();
// Figure out the context (category or system, based on either category or context parameter). // 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); $ci = new contextinfo($studyplancontext);
$contextname = $ci->pathstr(); $contextname = $ci->pathstr();
$PAGE->set_pagelayout('base'); $PAGE->set_pagelayout('base');
//$PAGE->set_context($studyplancontext); //$PAGE->set_context($studyplancontext);
$PAGE->set_title(get_string('view_plan', 'local_treestudyplan')." - ".$contextname); $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')); $PAGE->navbar->add(get_string('view_plan', 'local_treestudyplan'));
// Coursecat context // Coursecat context
$cat = \core_course_category::get($studyplancontext->instanceid,IGNORE_MISSING,true); // We checck visibility later $cat = \core_course_category::get($studyplancontext->instanceid, IGNORE_MISSING, true); // We checck visibility later
} else { } else {
// System context // System context
$cat = \core_course_category::top(); $cat = \core_course_category::top();
} }
if (!$cat->is_uservisible()) { 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)) { if (!has_capability('local/treestudyplan:viewuserreports', $studyplancontext)) {
throw new \moodle_exception("error:nostudyplanviewaccess","local_treestudyplan","/local/treestudyplan/view_plan.php",$contextname); throw new \moodle_exception("error:nostudyplanviewaccess", "local_treestudyplan", "/local/treestudyplan/view_plan.php", $contextname);
} }
// Load javascripts and specific css. // Load javascripts and specific css.
@ -121,16 +118,16 @@ print $OUTPUT->header();
<div v-cloak> <div v-cloak>
<div v-if='!activestudyplan && usedcontexts' class='ml-3 mb-3 s-context-selector'> <div v-if='!activestudyplan && usedcontexts' class='ml-3 mb-3 s-context-selector'>
<b-form-select text='<?php print($contextname);?>' :value="contextid" @change='switchContext' <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" <b-form-select-option v-if='!(usedcontexts.length)' :value="contextid"
:class="'text-primary'"> :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" <b-form-select-option v-for='ctx in usedcontexts' :key='ctx.id' :value="ctx.context_id"
:class="(ctx.studyplancount > 0) ? 'font-weight-bold' : ''" :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 v-for="(p, i) in ctx.category.path"><span v-if="i>0"> / </span>{{ p }}</span>
<span>({{ ctx.studyplancount }})</span></b-form-select-option> <span>({{ ctx.studyplancount }})</span></b-form-select-option>
</b-form-select> </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> class="spinner-border text-primary" role="status"></div>
</div> </div>
<h3 v-else><?php print $contextname; ?></h3> <h3 v-else><?php print $contextname; ?></h3>
@ -147,11 +144,11 @@ print $OUTPUT->header();
:value='studyplan.id' :value='studyplan.id'
>{{ studyplan.name }}</b-form-select-option> >{{ studyplan.name }}</b-form-select-option>
</b-form-select>&nbsp; </b-form-select>&nbsp;
<s-studyplan-details <s-studyplan-details
v-model="displayedstudyplan" v-model="displayedstudyplan"
v-if="displayedstudyplan.description" v-if="displayedstudyplan.description"
></s-studyplan-details> ></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> <div>
<span><?php t('selectstudent_btn') ?></span> <span><?php t('selectstudent_btn') ?></span>
<s-prevnext-selector <s-prevnext-selector