From 9c87e62bdc10a2ccc26db03e0eadd7020b23e411 Mon Sep 17 00:00:00 2001 From: mcquenji <60017181+mcquenji@users.noreply.github.com> Date: Sat, 28 Oct 2023 02:37:48 +0200 Subject: [PATCH 01/92] LP-171 generate docs for plugin app and public api (#31) --- .github/workflows/gen_docs.yaml | 47 ++++++ document_services.py | 281 ++++++++++++++++++++++++++++++++ 2 files changed, 328 insertions(+) create mode 100644 .github/workflows/gen_docs.yaml create mode 100644 document_services.py diff --git a/.github/workflows/gen_docs.yaml b/.github/workflows/gen_docs.yaml new file mode 100644 index 00000000..91705d17 --- /dev/null +++ b/.github/workflows/gen_docs.yaml @@ -0,0 +1,47 @@ +name: Generate API Docs + +on: + push: + branches: + - LP-176-Backend-Refactor # This is temporary and will be replaced by `moodle` once the refactor is complete + workflow_dispatch: # For manual triggering + +jobs: + generate-api-docs: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + with: + ref: LP-176-Backend-Refactor # This is temporary and will be replaced by `moodle` once the refactor is complete + path: moodle + + - name: Checkout docs branch + uses: actions/checkout@v3 + with: + ref: docs + clean: false + path: docs + + - name: Setup Python + uses: actions/setup-python@v4.7.1 + with: + python-version: 3.10 + + - name: Clear old documentation in /moodle subdir + run: | + rm -f docs/moodle/script.js + + - name: Generate docs + working-directory: moodle + run: python document_services.py ../moodle + + - name: Push new documentation to docs branch + working-directory: docs + run: | + git config user.name "GitHub Actions Bot" + git config user.email "github-actions-bot@users.noreply.github.com" + git add -A + git commit -m "GitHub Actions - Update Web Service Documentation to ${{ github.sha }}" + git push \ No newline at end of file diff --git a/document_services.py b/document_services.py new file mode 100644 index 00000000..2b7e2304 --- /dev/null +++ b/document_services.py @@ -0,0 +1,281 @@ +import json +import re +import sys + + +def extract_function_info(file_content): + function_info = [] + + # Removing comments, PHP tags, and definitions + clean_content = re.sub(r"//.*|<\?php|defined\(.*\)\s*\|\|\s*die\(\);", "", file_content) + + # Splitting the content based on function definition blocks + functions = re.findall(r"'(.*?)' => array\((.*?)\),", clean_content, re.DOTALL) + + for function in functions: + func_dict = {} + + # Extracting function name and group + func_name_match = re.match(r"local_lbplanner_(.*?)_(.*)", function[0]) + if func_name_match: + func_dict["function_name"] = function[0] + func_dict["group"] = func_name_match.group(1) + else: + continue + + # Extracting and adjusting capabilities + capabilities = re.search(r"'capabilities' => '.*:(.*?)'", function[1]) + func_dict["capabilities"] = capabilities.group(1) if capabilities else None + + # Extracting description + description = re.search(r"'description' => '(.*?)'", function[1]) + func_dict["description"] = description.group(1) if description else None + + # Extracting and adjusting path + classpath = re.search(r"'classpath' => 'local/(.*?)'", function[1]) + func_dict["path"] = classpath.group(1) if classpath else None + + # Only adding to the list if all information is present + if all(value is not None for value in func_dict.values()): + function_info.append(func_dict) + + return function_info + + +def extract_php_functions(php_code): + # Regular expression to match the function names and bodies + pattern = re.compile(r"(public static function \w+_(?:returns|parameters).*?{.*?})", re.DOTALL) + + # Find all matches in the PHP code + matches = pattern.findall(php_code) + + parameters_function = None + returns_function = None + + for match in matches: + # Extract function name + function_name = re.search(r"public static function (\w+)", match).group(1) + + if function_name.endswith("_parameters"): + parameters_function = match + elif function_name.endswith("_returns"): + returns_function = match + + return parameters_function, returns_function + + +def parse_returns(input_str): + pattern = r"'(\w+)' => new external_value\((\w+), '([^']+)'" + matches = re.findall(pattern, input_str) + + output_dict = {} + for match in matches: + key, value_type, description = match + output_dict[key] = {"type": convert_param_type_to_normal_type(value_type), "description": description} + + # Check for the presence of 'external_multiple_structure' + is_multiple_structure = "external_multiple_structure" in input_str + + return output_dict, is_multiple_structure + + +def convert_param_type_to_normal_type(param_type): + CONVERSIONS = { + "PARAM_INT": "int", + "PARAM_TEXT": "String", + "PARAM_URL": "String", + } + + return CONVERSIONS.get(param_type, param_type) + + +def parse_params(input_text): + # Regular expression to match the parameters inside the 'new external_value()' function + pattern = r"'(\w+)' => new external_value\s*\(\s*(\w+)\s*,\s*'([^']+)',\s*(\w+),\s*([\w\d]+|\w+),\s*(\w+)\s*\)" + + # Find all matches of the pattern in the input text + matches = re.findall(pattern, input_text) + + result = {} + for match in matches: + param_name = match[0] + result[param_name] = { + "type": convert_param_type_to_normal_type(match[1]), + "description": match[2], + "required": True if match[3] == "VALUE_REQUIRED" else False, + "default_value": match[4] if match[4] != "null" else None, + "nullable": False if match[5] == "NULL_NOT_ALLOWED" else True, + } + + return result + + +SCRIPT = r""" + +const funcs = /* JSON data here */; + + +let groups = []; + +for (let func of funcs) { + let group = groups.find(g => g.groupName === func.group); + if (!group) { + group = { + groupName: func.group, + functions: [] + }; + groups.push(group); + } + group.functions.push(func); +} + +const sidebar = document.getElementById('sidebar'); +const content = document.getElementById('content'); + +let currentFunction = null; + + +function searchFunction() { + + const input = document.getElementById('search').value.toUpperCase(); + const functions = document.querySelectorAll('.func-name'); + + for (let i = 0; i < functions.length; i++) { + const textValue = functions[i].textContent || functions[i].innerText; + if (funcName(textValue).toUpperCase().includes(input)) { + functions[i].style.display = ""; + } else { + functions[i].style.display = "none"; + } + } + + // check for func-group and if it has any children that are visible and if not hide it + const groups = document.querySelectorAll('.func-group'); + for (let group of groups) { + let visible = false; + for (let child of group.children) { + if (!child.classList.contains('func-name')) continue; + + child.style.display !== 'none' ? visible = true : null; + + if (visible) break; + } + + visible ? group.style.display = '' : group.style.display = 'none'; + } +} + +const groupsElement = document.querySelector('#func-groups'); +const detailsPane = document.querySelector('#func-details'); + +function displayGroupsAndFunctions() { + groups.forEach(group => { + const groupElement = document.createElement('div'); + groupElement.classList.add('func-group'); + + groupName = document.createElement('h1'); + groupName.textContent = group.groupName; + + groupElement.appendChild(groupName); + groupsElement.appendChild(groupElement); + + group.functions.forEach(func => { + const funcElement = document.createElement('p'); + funcElement.classList.add('func-name'); + funcElement.textContent = func.function_name; + funcElement.onclick = () => { + if (currentFunction) { + currentFunction.removeAttribute('active'); + } + + funcElement.setAttribute('active', ''); + + currentFunction = funcElement; + + displayFunctionDetails(func); + }; + groupElement.appendChild(funcElement); + }); + }); + let bottomSpacer = document.createElement('div'); + bottomSpacer.style.height = '100px'; + groupsElement.appendChild(bottomSpacer); +} + +function funcName(fullName) { + // remove everything from the third underscore + const split = fullName.split('_'); + return split.slice(3, split.length).join(' '); +} + +function displayFunctionDetails(func) { + + detailsPane.innerHTML = ` +

${funcName(func.function_name)}

+

${func.function_name}

+
+

${func.description}

+

Parmeters

+
+ ${Object.keys(func.parameters).map(param => ` +
+
+

${param}

+

${func.parameters[param].type}

+

${func.parameters[param].required ? 'required' : 'optional'}

+
+

${func.parameters[param].description}

+
+`).join('')} +

Returns${func.returns_multiple ? '

Array

' : ""}

+
+ ${Object.keys(func.returns).map(ret => ` +
+
+

${ret}

+

${func.returns[ret].type}

+
+

${func.returns[ret].description}

+
+`).join('')} + `; + + let copy = document.getElementById('copy'); + copy.onclick = () => { + navigator.clipboard.writeText(func.function_name); + } +} + +displayGroupsAndFunctions(); + +document.getElementById('search').addEventListener('keyup', searchFunction); +""" + +if __name__ == "__main__": + with open("lbplanner/db/services.php", "r") as file: + content = file.read() + info = extract_function_info(content) + + complete_info = [] + + for i, info in enumerate(info): + with open(info["path"], "r") as func_file: + func_content = func_file.read() + params_func, returns_func = extract_php_functions(func_content) + + returns, returns_multiple = parse_returns(returns_func) + + incomplete_info = info + + params = parse_params(params_func) + + incomplete_info["parameters"] = params + incomplete_info["returns"] = returns + incomplete_info["returns_multiple"] = returns_multiple + + complete_info.append(incomplete_info) + + script = SCRIPT.replace("/* JSON data here */", json.dumps(complete_info)) + + with open(f"{sys.argv[1]}/script.js", "w") as output_file: + output_file.write(script) From d6d4456cbea6aef4df12d1b65f06efa4961b74c7 Mon Sep 17 00:00:00 2001 From: mcquenji <60017181+mcquenji@users.noreply.github.com> Date: Sat, 28 Oct 2023 02:40:34 +0200 Subject: [PATCH 02/92] fixed gen_docs workflow (#32) --- .github/workflows/gen_docs.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gen_docs.yaml b/.github/workflows/gen_docs.yaml index 91705d17..13f7fa4a 100644 --- a/.github/workflows/gen_docs.yaml +++ b/.github/workflows/gen_docs.yaml @@ -27,7 +27,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4.7.1 with: - python-version: 3.10 + python-version: '3.10' - name: Clear old documentation in /moodle subdir run: | @@ -44,4 +44,4 @@ jobs: git config user.email "github-actions-bot@users.noreply.github.com" git add -A git commit -m "GitHub Actions - Update Web Service Documentation to ${{ github.sha }}" - git push \ No newline at end of file + git push From 27490da10431bc0c923a20e4410c3a659a2277a8 Mon Sep 17 00:00:00 2001 From: mcquenji <60017181+mcquenji@users.noreply.github.com> Date: Sat, 28 Oct 2023 02:43:44 +0200 Subject: [PATCH 03/92] fixed gen_docs workflow II (#33) --- .github/workflows/gen_docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gen_docs.yaml b/.github/workflows/gen_docs.yaml index 13f7fa4a..866afafa 100644 --- a/.github/workflows/gen_docs.yaml +++ b/.github/workflows/gen_docs.yaml @@ -35,7 +35,7 @@ jobs: - name: Generate docs working-directory: moodle - run: python document_services.py ../moodle + run: python document_services.py ../docs/moodle - name: Push new documentation to docs branch working-directory: docs From b3ce5d74ea809e0266523191e80879efbdef4631 Mon Sep 17 00:00:00 2001 From: mcquenji <60017181+mcquenji@users.noreply.github.com> Date: Sat, 28 Oct 2023 02:50:07 +0200 Subject: [PATCH 04/92] added PARAM_BOOL type conversion (#34) --- document_services.py | 1 + 1 file changed, 1 insertion(+) diff --git a/document_services.py b/document_services.py index 2b7e2304..1113e4ca 100644 --- a/document_services.py +++ b/document_services.py @@ -84,6 +84,7 @@ def convert_param_type_to_normal_type(param_type): "PARAM_INT": "int", "PARAM_TEXT": "String", "PARAM_URL": "String", + "PARAM_BOOL": "bool", } return CONVERSIONS.get(param_type, param_type) From c975639df33981604149dacc0f65210b08ec247b Mon Sep 17 00:00:00 2001 From: mcquenji <60017181+mcquenji@users.noreply.github.com> Date: Sat, 28 Oct 2023 03:12:16 +0200 Subject: [PATCH 05/92] copy parameters and return values on click (#35) --- document_services.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/document_services.py b/document_services.py index 1113e4ca..cddaba13 100644 --- a/document_services.py +++ b/document_services.py @@ -245,6 +245,21 @@ def parse_params(input_text): copy.onclick = () => { navigator.clipboard.writeText(func.function_name); } + + let returnValues = document.querySelectorAll('.value-name'); + let params = document.querySelectorAll('.param-name'); + + for (let value of returnValues){ + value.addEventListener('click', () => { + navigator.clipboard.writeText(value.innerText) + }); + } + + for (let param of params){ + param.addEventListener('click', () => { + navigator.clipboard.writeText(param.innerText) + }); + } } displayGroupsAndFunctions(); From ce94c788aeaace6a15826062e44c998b30545752 Mon Sep 17 00:00:00 2001 From: mcquenji <60017181+mcquenji@users.noreply.github.com> Date: Sat, 28 Oct 2023 03:25:00 +0200 Subject: [PATCH 06/92] added capabilities to func details (#36) --- document_services.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/document_services.py b/document_services.py index cddaba13..776ce8cb 100644 --- a/document_services.py +++ b/document_services.py @@ -216,6 +216,9 @@ def parse_params(input_text):

${func.function_name}


${func.description}

+

Capabilities

+
+

${func.capabilities}

Parmeters


${Object.keys(func.parameters).map(param => ` From c251e3439908e3e804727636bd4c830c9476446b Mon Sep 17 00:00:00 2001 From: Riedler's Sockpuppet <150551914+Riedlers-sockpuppet@users.noreply.github.com> Date: Wed, 15 Nov 2023 13:48:23 +0100 Subject: [PATCH 07/92] refactored enums inside plan_helper (#50) (#51) Co-authored-by: RiedleroD --- lbplanner/classes/helpers/plan_helper.php | 108 +++++++++------------ lbplanner/services/plan/accept_invite.php | 14 +-- lbplanner/services/plan/decline_invite.php | 7 +- lbplanner/services/plan/invite_user.php | 5 +- lbplanner/services/plan/leave_plan.php | 16 +-- lbplanner/services/plan/update_access.php | 9 +- lbplanner/services/plan/update_invite.php | 16 +-- lbplanner/services/user/delete_user.php | 8 +- lbplanner/services/user/register_user.php | 6 +- 9 files changed, 95 insertions(+), 94 deletions(-) diff --git a/lbplanner/classes/helpers/plan_helper.php b/lbplanner/classes/helpers/plan_helper.php index eee5da31..d6c0cefd 100644 --- a/lbplanner/classes/helpers/plan_helper.php +++ b/lbplanner/classes/helpers/plan_helper.php @@ -21,59 +21,37 @@ use external_multiple_structure; /** - * Provides helper methods for any tables related with the planning function of the app. + * Levels of access that a user can have for a plan */ -class plan_helper { - /** - * Enum value for the plan owner. - */ - const ACCESS_TYPE_OWNER = 0; - - /** - * Enum value for plan members with write access to the plan. - */ - const ACCESS_TYPE_WRITE = 1; - - /** - * Enum value for plan members with read access to the plan. - */ - const ACCESS_TYPE_READ = 2; - - /** - * Enum value for plan members with no access to the plan. - */ - const ACCESS_TYPE_NONE = -1; - - /** - * Boolean value for ek-modules disabled. - */ - const EK_DISABLED = 0; - - /** - * Boolean value for ek-modules enabled. - */ - const EK_ENABLED = 1; - - /** - * Enum value for invites: The invite is pending and has not been accepted yet. - */ - const INVITE_PENDING = 0; - - /** - * Enum value for invites: The invite has been accepted. - */ - const INVITE_ACCEPTED = 1; +enum PLAN_ACCESS_TYPE: int { + case OWNER = 0; + case WRITE = 1; + case READ = 2; + case NONE = -1; +} - /** - * Enum value for invites: The invite has been declined. - */ - const INVITE_DECLINED = 2; +/** + * Whether EK modules are enabled inside the planner + */ +enum PLAN_EK: int { + case DISABLED = 0; + case ENABLED = 1; +} - /** - * Enum value for invites: The invite has expired. - */ - const INVITE_EXPIRED = 3; +/** + * States an invite can be in + */ +enum PLAN_INVITE_STATE: int { + case PENDING = 0; + case ACCEPTED = 1; + case DECLINED = 2; + case EXPIRED = 3; +} +/** + * Provides helper methods for any tables related with the planning function of the app. + */ +class plan_helper { /** * local_lbplanner_plans table. */ @@ -117,7 +95,7 @@ public static function get_owner(int $planid):int { $owner = $DB->get_field( self::ACCESS_TABLE, - 'userid', array('planid' => $planid, 'accesstype' => self::ACCESS_TYPE_OWNER) + 'userid', array('planid' => $planid, 'accesstype' => PLAN_ACCESS_TYPE::OWNER->value) ); return $owner; @@ -138,31 +116,37 @@ public static function get_plan_id(int $userid):int { /** * Returns the access type of the given user for the given plan. * - * @param integer $planid The id of the plan. - * @param integer $userid The id of the user. - * @return integer The access type of the given user for the given plan. + * @param int $planid The id of the plan. + * @param int $userid The id of the user. + * @return PLAN_ACCESS_TYPE The access type of the given user for the given plan. */ - public static function get_access_type(int $userid, int $planid):int { + public static function get_access_type(int $userid, int $planid): PLAN_ACCESS_TYPE { global $DB; - if ($DB->record_exists(self::ACCESS_TABLE, array('planid' => $planid, 'userid' => $userid))) { - return $DB->get_field(self::ACCESS_TABLE, 'accesstype', array('planid' => $planid, 'userid' => $userid)); + $field = $DB->get_field( + self::ACCESS_TABLE, + 'accesstype', + array('planid' => $planid, 'userid' => $userid) + ); + + if ($field === false) { + return PLAN_ACCESS_TYPE::NONE; } else { - return self::ACCESS_TYPE_NONE; + return PLAN_ACCESS_TYPE::from($field); } } /** * Checks if the given user has editing permissions for the given plan. * - * @param integer $planid The id of the plan. - * @param integer $userid The id of the user. + * @param int $planid The id of the plan. + * @param int $userid The id of the user. * @return boolean True if the given user has editing permissions for the given plan. */ public static function check_edit_permissions(int $planid, int $userid):bool { $access = self::get_access_type($userid, $planid); - return $access == self::ACCESS_TYPE_OWNER || $access == self::ACCESS_TYPE_WRITE; + return $access === PLAN_ACCESS_TYPE::OWNER || $access === PLAN_ACCESS_TYPE::WRITE; } /** @@ -301,7 +285,7 @@ public static function remove_user(int $planid, int $userid, int $removeuserid) throw new \moodle_exception('Cannot remove yourself'); } - if (self::get_access_type($removeuserid, $planid) == self::ACCESS_TYPE_OWNER) { + if (self::get_access_type($removeuserid, $planid) === PLAN_ACCESS_TYPE::OWNER) { throw new \moodle_exception('Cannot remove owner'); } @@ -313,7 +297,7 @@ public static function remove_user(int $planid, int $userid, int $removeuserid) ); $oldaccess->planid = $newplanid; - $oldaccess->accesstype = self::ACCESS_TYPE_OWNER; + $oldaccess->accesstype = PLAN_ACCESS_TYPE::OWNER->value; $DB->update_record(self::ACCESS_TABLE, $oldaccess); diff --git a/lbplanner/services/plan/accept_invite.php b/lbplanner/services/plan/accept_invite.php index c0105850..6bce45e3 100644 --- a/lbplanner/services/plan/accept_invite.php +++ b/lbplanner/services/plan/accept_invite.php @@ -23,6 +23,8 @@ use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; +use local_lbplanner\helpers\PLAN_ACCESS_TYPE; +use local_lbplanner\helpers\PLAN_INVITE_STATE; /** * Update a invite from the plan. @@ -49,7 +51,7 @@ public static function accept_invite($inviteid, $userid) { throw new \moodle_exception('Invite not found'); } if (!$DB->record_exists(plan_helper::INVITES_TABLE, - array( 'id' => $inviteid, 'inviteeid' => $userid, 'status' => plan_helper::INVITE_PENDING))) { + array( 'id' => $inviteid, 'inviteeid' => $userid, 'status' => PLAN_INVITE_STATE::PENDING->value))) { throw new \moodle_exception('Invite already accepted or declined'); } @@ -57,7 +59,7 @@ public static function accept_invite($inviteid, $userid) { array( 'id' => $inviteid, 'inviteeid' => $userid, - 'status' => plan_helper::INVITE_PENDING, + 'status' => PLAN_INVITE_STATE::PENDING->value, ), '*', MUST_EXIST @@ -99,18 +101,18 @@ public static function accept_invite($inviteid, $userid) { MUST_EXIST ); - $invite->status = plan_helper::INVITE_ACCEPTED; + $invite->status = PLAN_INVITE_STATE::ACCEPTED->value; $DB->update_record(plan_helper::INVITES_TABLE, $invite); - $planaccess->accesstype = plan_helper::ACCESS_TYPE_READ; + $planaccess->accesstype = PLAN_ACCESS_TYPE::READ->value; $planaccess->planid = $invite->planid; $DB->update_record(plan_helper::ACCESS_TABLE, $planaccess); $invites = plan_helper::get_invites_send($userid); foreach ($invites as $invite) { - if ($invite->status == plan_helper::INVITE_PENDING) { - $invite->status = plan_helper::INVITE_EXPIRED; + if ($invite->status == PLAN_INVITE_STATE::PENDING->value) { + $invite->status = PLAN_INVITE_STATE::EXPIRED->value; $DB->update_record(plan_helper::INVITES_TABLE, $invite); } } diff --git a/lbplanner/services/plan/decline_invite.php b/lbplanner/services/plan/decline_invite.php index 67341ca5..4dc64381 100644 --- a/lbplanner/services/plan/decline_invite.php +++ b/lbplanner/services/plan/decline_invite.php @@ -23,6 +23,7 @@ use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; +use local_lbplanner\helpers\PLAN_INVITE_STATE; /** * Update a invite from the plan. @@ -49,7 +50,7 @@ public static function decline_invite($inviteid, $userid) { throw new \moodle_exception('Invite not found'); } if (!$DB->record_exists(plan_helper::INVITES_TABLE, - array('id' => $inviteid, 'inviteeid' => $userid, 'status' => plan_helper::INVITE_PENDING))) { + array('id' => $inviteid, 'inviteeid' => $userid, 'status' => PLAN_INVITE_STATE::PENDING->value))) { throw new \moodle_exception('Invite already accepted or declined'); } @@ -57,7 +58,7 @@ public static function decline_invite($inviteid, $userid) { array( 'id' => $inviteid, 'inviteeid' => $userid, - 'status' => plan_helper::INVITE_PENDING, + 'status' => PLAN_INVITE_STATE::PENDING->value, ), '*', MUST_EXIST @@ -70,7 +71,7 @@ public static function decline_invite($inviteid, $userid) { notifications_helper::TRIGGER_INVITE_DECLINED ); - $invite->status = plan_helper::INVITE_DECLINED; + $invite->status = PLAN_INVITE_STATE::DECLINED->value; $DB->update_record(plan_helper::INVITES_TABLE, $invite); diff --git a/lbplanner/services/plan/invite_user.php b/lbplanner/services/plan/invite_user.php index 722800dd..3d53f6fb 100644 --- a/lbplanner/services/plan/invite_user.php +++ b/lbplanner/services/plan/invite_user.php @@ -23,6 +23,7 @@ use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\notifications_helper; +use local_lbplanner\helpers\PLAN_INVITE_STATE; /** * Invite a user to the plan. @@ -77,7 +78,7 @@ public static function invite_user($inviterid, $inviteeid , $planid) { if ($DB->record_exists( plan_helper::INVITES_TABLE, - array('inviteeid' => $inviteeid, 'planid' => $planid, 'status' => plan_helper::INVITE_PENDING) + array('inviteeid' => $inviteeid, 'planid' => $planid, 'status' => PLAN_INVITE_STATE::PENDING->value) )) { throw new \moodle_exception('User is already invited'); } @@ -95,7 +96,7 @@ public static function invite_user($inviterid, $inviteeid , $planid) { $invite->inviterid = $inviterid; $invite->inviteeid = $inviteeid; $invite->timestamp = time(); - $invite->status = plan_helper::INVITE_PENDING; + $invite->status = PLAN_INVITE_STATE::PENDING->value; $invite->id = $DB->insert_record(plan_helper::INVITES_TABLE, $invite); diff --git a/lbplanner/services/plan/leave_plan.php b/lbplanner/services/plan/leave_plan.php index acc84fc3..1eb4552f 100644 --- a/lbplanner/services/plan/leave_plan.php +++ b/lbplanner/services/plan/leave_plan.php @@ -22,6 +22,8 @@ use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\notifications_helper; +use local_lbplanner\helpers\PLAN_ACCESS_TYPE; +use local_lbplanner\helpers\PLAN_INVITE_STATE; /** * Leave the plan of the given user. @@ -53,11 +55,11 @@ public static function leave_plan($userid, $planid) { user_helper::assert_access($userid); - if (plan_helper::get_access_type($userid, $planid) == plan_helper::ACCESS_TYPE_NONE) { + if (plan_helper::get_access_type($userid, $planid) == PLAN_ACCESS_TYPE::NONE) { throw new \moodle_exception('User is not a member of this plan'); } - if (plan_helper::get_access_type($userid, $planid) == plan_helper::ACCESS_TYPE_OWNER) { + if (plan_helper::get_access_type($userid, $planid) == PLAN_ACCESS_TYPE::OWNER) { $members = plan_helper::get_plan_members($planid); if (count($members) == 1) { @@ -70,7 +72,7 @@ public static function leave_plan($userid, $planid) { if ($member->userid == $userid) { continue; } - if ($member->accesstype == plan_helper::ACCESS_TYPE_WRITE) { + if ($member->accesstype == PLAN_ACCESS_TYPE::WRITE->value) { $writemembers[] = $member; } $allmembers[] = $member; @@ -84,7 +86,7 @@ public static function leave_plan($userid, $planid) { plan_helper::ACCESS_TABLE, array('planid' => $planid, 'userid' => $newowner), '*', MUST_EXIST ); - $newowneraccess->accesstype = plan_helper::ACCESS_TYPE_OWNER; + $newowneraccess->accesstype = PLAN_ACCESS_TYPE::OWNER->value; $DB->update_record(plan_helper::ACCESS_TABLE, $newowneraccess); } @@ -96,15 +98,15 @@ public static function leave_plan($userid, $planid) { ); $oldaccess->planid = $newplanid; - $oldaccess->accesstype = plan_helper::ACCESS_TYPE_OWNER; + $oldaccess->accesstype = PLAN_ACCESS_TYPE::OWNER->value; $DB->update_record(plan_helper::ACCESS_TABLE, $oldaccess); // Notify plan owner that user has left his plan. $invites = plan_helper::get_invites_send($userid); foreach ($invites as $invite) { - if ($invite->status == plan_helper::INVITE_PENDING) { - $invite->status = plan_helper::INVITE_EXPIRED; + if ($invite->status == PLAN_INVITE_STATE::PENDING->value) { + $invite->status = PLAN_INVITE_STATE::EXPIRED->value; $DB->update_record(plan_helper::INVITES_TABLE, $invite); } } diff --git a/lbplanner/services/plan/update_access.php b/lbplanner/services/plan/update_access.php index dc49d370..2bf88fa1 100644 --- a/lbplanner/services/plan/update_access.php +++ b/lbplanner/services/plan/update_access.php @@ -19,6 +19,7 @@ use external_api; use external_function_parameters; use external_value; +use local_lbplanner\helpers\PLAN_ACCESS_TYPE; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\user_helper; @@ -73,7 +74,9 @@ public static function update_access($userid, $planid, $accesstype, $memberid) { throw new \moodle_exception('Access denied'); } - if ($accesstype < 0 || $accesstype > 2) { + $accesstype_obj = PLAN_ACCESS_TYPE::tryFrom($accesstype); + + if ($accesstype_obj === null) { throw new \moodle_exception('Access type not valid'); } @@ -85,8 +88,8 @@ public static function update_access($userid, $planid, $accesstype, $memberid) { throw new \moodle_exception('Cannot change permissions for the plan owner'); } - if ($accesstype == plan_helper::ACCESS_TYPE_OWNER) { - throw new \moodle_exception('Cannot change permissions to owner'); + if ($accesstype_obj === PLAN_ACCESS_TYPE::OWNER) { + throw new \moodle_exception('Cannot change permission to owner'); } $access = $DB->get_record(plan_helper::ACCESS_TABLE, array('planid' => $planid, 'userid' => $memberid), '*', MUST_EXIST); diff --git a/lbplanner/services/plan/update_invite.php b/lbplanner/services/plan/update_invite.php index 3b3640c9..164dcfff 100644 --- a/lbplanner/services/plan/update_invite.php +++ b/lbplanner/services/plan/update_invite.php @@ -23,6 +23,8 @@ use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; +use local_lbplanner\helpers\PLAN_ACCESS_TYPE; +use local_lbplanner\helpers\PLAN_INVITE_STATE; /** * THIS METHOD IS NOT USED ANYMORE. JUST TO KEEP OLD CODE FOR REFERENCE. @@ -47,7 +49,9 @@ public static function update_invite($planid, $userid, $status) { user_helper::assert_access($userid); - if ($status != plan_helper::INVITE_ACCEPTED && $status != plan_helper::INVITE_DECLINED) { + $status_obj = PLAN_INVITE_STATE::tryFrom($status); + + if ($status_obj === null) { throw new \moodle_exception('Invalid status'); } @@ -60,15 +64,15 @@ public static function update_invite($planid, $userid, $status) { MUST_EXIST ); - if ($invite->status != plan_helper::INVITE_PENDING) { - throw new \moodle_exception('Invalid status'); + if ($invite->status != PLAN_INVITE_STATE::PENDING->value) { + throw new \moodle_exception('Can\'t update non-pending status'); } $invite->status = $status; $DB->update_record(plan_helper::INVITES_TABLE, $invite); - $trigger = $status == plan_helper::INVITE_ACCEPTED ? + $trigger = $status_obj === PLAN_INVITE_STATE::ACCEPTED ? notifications_helper::TRIGGER_INVITE_ACCEPTED : notifications_helper::TRIGGER_INVITE_DECLINED; @@ -76,7 +80,7 @@ public static function update_invite($planid, $userid, $status) { // TODO: Change plan access and delete old plan if inivite is accepted. - if ($status == plan_helper::INVITE_ACCEPTED) { + if ($status_obj == PLAN_INVITE_STATE::ACCEPTED) { $oldplanid = plan_helper::get_plan_id($userid); if (plan_helper::get_owner($oldplanid) == $userid) { @@ -101,7 +105,7 @@ public static function update_invite($planid, $userid, $status) { MUST_EXIST ); - $planaccess->accesstype = plan_helper::ACCESS_TYPE_READ; + $planaccess->accesstype = PLAN_ACCESS_TYPE::READ->value; $planaccess->planid = $planid; $DB->update_record(plan_helper::ACCESS_TABLE, $planaccess); diff --git a/lbplanner/services/user/delete_user.php b/lbplanner/services/user/delete_user.php index d099bf69..aea7910c 100644 --- a/lbplanner/services/user/delete_user.php +++ b/lbplanner/services/user/delete_user.php @@ -25,6 +25,8 @@ use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\course_helper; use local_lbplanner\helpers\notifications_helper; +use local_lbplanner\helpers\PLAN_ACCESS_TYPE; +use local_lbplanner\helpers\PLAN_INVITE_STATE; /** * Removes all user data stored by the lbplanner app @@ -55,7 +57,7 @@ public static function delete_user($userid) { $planid = plan_helper::get_plan_id($userid); - if (plan_helper::get_access_type($planid, $userid) == plan_helper::ACCESS_TYPE_OWNER) { + if (plan_helper::get_access_type($planid, $userid) === PLAN_ACCESS_TYPE::OWNER) { if (plan_helper::get_plan_members($planid) > 1) { self::call_external_function('local_lbplanner_plan_leave_plan', array('userid' => $userid, 'planid' => $planid)); } else { @@ -71,8 +73,8 @@ public static function delete_user($userid) { $invites = plan_helper::get_invites_send($userid); foreach ($invites as $invite) { - if ($invite->status == plan_helper::INVITE_PENDING) { - $invite->status = plan_helper::INVITE_EXPIRED; + if ($invite->status == PLAN_INVITE_STATE::PENDING->value) { + $invite->status = PLAN_INVITE_STATE::EXPIRED->value; $DB->update_record(plan_helper::INVITES_TABLE, $invite); } } diff --git a/lbplanner/services/user/register_user.php b/lbplanner/services/user/register_user.php index 59a3fbe1..27203ac7 100644 --- a/lbplanner/services/user/register_user.php +++ b/lbplanner/services/user/register_user.php @@ -23,6 +23,8 @@ use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; +use local_lbplanner\helpers\PLAN_ACCESS_TYPE; +use local_lbplanner\helpers\PLAN_EK; /** * Register a new user in the lbplanner app. @@ -62,13 +64,13 @@ public static function register_user($userid, $lang, $theme) { $plan = new \stdClass(); $plan->name = 'Plan for ' . $mdluser->firstname; - $plan->enableek = plan_helper::EK_DISABLED; + $plan->enableek = PLAN_EK::DISABLED->value; $planid = $DB->insert_record(plan_helper::TABLE, $plan); $planaccess = new \stdClass(); $planaccess->userid = $userid; - $planaccess->accesstype = plan_helper::ACCESS_TYPE_OWNER; + $planaccess->accesstype = PLAN_ACCESS_TYPE::OWNER->value; $planaccess->planid = $planid; $DB->insert_record(plan_helper::ACCESS_TABLE, $planaccess); From 22d78e3d6169688aa0c682d3fc1b0a755f82dd78 Mon Sep 17 00:00:00 2001 From: Riedler's Sockpuppet <150551914+Riedlers-sockpuppet@users.noreply.github.com> Date: Wed, 15 Nov 2023 15:49:05 +0100 Subject: [PATCH 08/92] parse return struct defs (#53) Co-authored-by: RiedleroD --- document_services.py | 51 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/document_services.py b/document_services.py index 776ce8cb..be870679 100644 --- a/document_services.py +++ b/document_services.py @@ -1,7 +1,7 @@ import json import re import sys - +from os import path def extract_function_info(file_content): function_info = [] @@ -63,9 +63,54 @@ def extract_php_functions(php_code): return parameters_function, returns_function +def parse_imports(input_str: str, symbol: str) -> str: + use_pattern = fr"use ((?:\w+\\)+){symbol};" + uses: list[str] = re.findall(use_pattern, input_str) + + namespaces = { + "local_lbplanner": "classes"# not entirely true, but good enough for now + } + fp_l: list[str] = [] + for use in uses: + p = use.split('\\')[:-1] + + namespace = namespaces.get(p[0]) + if namespace is not None: + p[0] = namespace -def parse_returns(input_str): + fp_l.append(path.join("lbplanner",*p,f"{symbol}.php")) + + if len(fp_l) > 1: + raise Exception("found import collision?") + elif len(fp_l) == 0: + raise Exception(f"Couldn't find symbol: {symbol}") + else: + return fp_l[0] + +def parse_returns(input_str: str, file_content: str): pattern = r"'(\w+)' => new external_value\((\w+), '([^']+)'" + redir_pattern = r"(\w+)::(\w+)\(\)" + + matches = re.findall(redir_pattern, input_str) + if len(matches) > 1: + raise Exception(f"Couldn't parse return values") + + if len(matches) == 1: + match = matches[0] + meth_pattern = rf"public static function {match[1]}\(\)(?: ?: ?\w+)? ?{{(?P.*?)}}" + + fp = parse_imports(file_content, match[0]) + with open(fp,"r") as f: + new_file_content = f.read() + matches = re.findall(meth_pattern,new_file_content,re.DOTALL) + if len(matches) == 0: + raise Exception(f"Couldn't find {match[0]}::{match[1]}() inside {fp}") + elif len(matches) > 1: + raise Exception(f"Found multiple definitions for {match[0]}::{match[1]}() inside {fp}") + else: + r= parse_returns(matches[0],new_file_content) + return r + matches = re.findall(pattern, input_str) output_dict = {} @@ -282,7 +327,7 @@ def parse_params(input_text): func_content = func_file.read() params_func, returns_func = extract_php_functions(func_content) - returns, returns_multiple = parse_returns(returns_func) + returns, returns_multiple = parse_returns(returns_func,func_content) incomplete_info = info From bd0362e77350d04fb30c7d50bc4fd87a9c81f965 Mon Sep 17 00:00:00 2001 From: mcquenji <60017181+mcquenji@users.noreply.github.com> Date: Wed, 15 Nov 2023 15:51:50 +0100 Subject: [PATCH 09/92] change trigger for gen_docs to LP-55 instead of LP-176 (#54) --- .github/workflows/gen_docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gen_docs.yaml b/.github/workflows/gen_docs.yaml index 866afafa..254fb8a6 100644 --- a/.github/workflows/gen_docs.yaml +++ b/.github/workflows/gen_docs.yaml @@ -3,7 +3,7 @@ name: Generate API Docs on: push: branches: - - LP-176-Backend-Refactor # This is temporary and will be replaced by `moodle` once the refactor is complete + - LP-55-Backend-Refactor # This is temporary and will be replaced by `moodle` once the refactor is complete workflow_dispatch: # For manual triggering jobs: From 14c2d6c1282a04b29e81a060c08e11a6765fef51 Mon Sep 17 00:00:00 2001 From: mcquenji <60017181+mcquenji@users.noreply.github.com> Date: Wed, 15 Nov 2023 15:54:58 +0100 Subject: [PATCH 10/92] changed branch checked out from LP-176 to LP-55 (#55) --- .github/workflows/gen_docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gen_docs.yaml b/.github/workflows/gen_docs.yaml index 254fb8a6..50d2e622 100644 --- a/.github/workflows/gen_docs.yaml +++ b/.github/workflows/gen_docs.yaml @@ -14,7 +14,7 @@ jobs: - name: Checkout Repo uses: actions/checkout@v3 with: - ref: LP-176-Backend-Refactor # This is temporary and will be replaced by `moodle` once the refactor is complete + ref: LP-55-Backend-Refactor # This is temporary and will be replaced by `moodle` once the refactor is complete path: moodle - name: Checkout docs branch From e6c24f977d44b8b7fb3981b53a5155db95d4a34e Mon Sep 17 00:00:00 2001 From: Riedler Date: Wed, 15 Nov 2023 18:37:07 +0100 Subject: [PATCH 11/92] LP-169 largely remove userid as REST parameters (Riedler edition) (#49) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * used $USER in get_all_notifications * removed $userid in update_notification (it was unused anyway? weird) * fixed typo (more or less) * fixed incorrect user property I trust people too much to tell me the correct property name 🤔 * removed $userid in delete_feedback * removed userid param from get_all_feedbacks unused again! …how? how does that even happen * removed $userid param from get_feedback another unused one * replaced userid param in submit_feedback * replaced userid param in update_feedback * removed userid from accept_invite rebased on #50 to make this work * removed userid REST param from add_deadline * removed userid REST param from clear_plan * refactored decline_invite * removed unnecessary user access check * removed userid from delete_deadline * removed plan/get_access because it duplicates a feature already handled in get_plan * refactored get_plan * refactored invite_user * refactored leave_plan * refactored remove_user * cleanup after rebase * removed userid from update_access * removed userid from update_deadline * removed userid from update_invite * removed userid and planid from update_plan * removed userid from get_invites * removed redundant planid REST parameter * added todo to delete file * codesniffer fixes * fixed inverted check for whether the invite has already been accepted or declined * removed get_access API point from services.php - I wasn't even aware a file like this existed --- lbplanner/db/services.php | 9 --- .../services/feedback/delete_feedback.php | 20 +++--- .../services/feedback/get_all_feedbacks.php | 20 +----- lbplanner/services/feedback/get_feedback.php | 13 ++-- .../services/feedback/submit_feedback.php | 20 +++--- .../services/feedback/update_feedback.php | 19 +++-- .../notifications/get_all_notifications.php | 25 +++---- .../notifications/update_notification.php | 24 +++---- lbplanner/services/plan/accept_invite.php | 65 ++++++++--------- lbplanner/services/plan/add_deadline.php | 37 +++------- lbplanner/services/plan/clear_plan.php | 33 ++------- lbplanner/services/plan/decline_invite.php | 44 +++++------- lbplanner/services/plan/delete_deadline.php | 41 ++++------- lbplanner/services/plan/get_access.php | 70 ------------------- lbplanner/services/plan/get_invites.php | 42 ++++------- lbplanner/services/plan/get_plan.php | 24 ++----- lbplanner/services/plan/invite_user.php | 59 +++++----------- lbplanner/services/plan/leave_plan.php | 52 +++++--------- lbplanner/services/plan/remove_user.php | 21 +++--- lbplanner/services/plan/update_access.php | 39 ++++------- lbplanner/services/plan/update_deadline.php | 37 +++------- lbplanner/services/plan/update_invite.php | 60 ++++++++-------- lbplanner/services/plan/update_plan.php | 33 +++------ 23 files changed, 247 insertions(+), 560 deletions(-) delete mode 100644 lbplanner/services/plan/get_access.php diff --git a/lbplanner/db/services.php b/lbplanner/db/services.php index b0e6b9a2..9f2d6b6b 100644 --- a/lbplanner/db/services.php +++ b/lbplanner/db/services.php @@ -198,15 +198,6 @@ 'capabilities' => 'local/lb_planner:student', 'ajax' => true, ), - 'local_lbplanner_plan_get_access' => array( - 'classname' => 'local_lbplanner_services\plan_get_access', - 'methodname' => 'get_access', - 'classpath' => 'local/lbplanner/services/plan/get_access.php', - 'description' => 'Get the access type to the plan', - 'type' => 'read', - 'capabilities' => 'local/lb_planner:student', - 'ajax' => true, - ), 'local_lbplanner_plan_update_access' => array( 'classname' => 'local_lbplanner_services\plan_update_access', 'methodname' => 'update_access', diff --git a/lbplanner/services/feedback/delete_feedback.php b/lbplanner/services/feedback/delete_feedback.php index a75455fb..55319811 100644 --- a/lbplanner/services/feedback/delete_feedback.php +++ b/lbplanner/services/feedback/delete_feedback.php @@ -20,7 +20,6 @@ use external_multiple_structure; use external_function_parameters; use external_value; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\feedback_helper; /** @@ -28,31 +27,28 @@ */ class feedback_delete_feedback extends external_api { public static function delete_feedback_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value(PARAM_INT, 'The id of the user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + return new external_function_parameters([ 'feedbackid' => new external_value(PARAM_INT, 'The id of the course', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - )); + ]); } - public static function delete_feedback($userid, $feedbackid) { - global $DB; + public static function delete_feedback($feedbackid) { + global $DB, $USER; self::validate_parameters( self::delete_feedback_parameters(), - array('userid' => $userid , 'feedbackid' => $feedbackid) + ['feedbackid' => $feedbackid] ); - user_helper::assert_access($userid); - - if (!$DB->record_exists(feedback_helper::LBPLANNER_FEEDBACK_TABLE, array('id' => $feedbackid))) { + if (!$DB->record_exists(feedback_helper::LBPLANNER_FEEDBACK_TABLE, ['id' => $feedbackid])) { throw new \moodle_exception('feedback_not_found'); } feedback_helper::assert_admin_access(); - $DB->delete_records(feedback_helper::LBPLANNER_FEEDBACK_TABLE, array('id' => $feedbackid)); + $DB->delete_records(feedback_helper::LBPLANNER_FEEDBACK_TABLE, ['id' => $feedbackid]); - return feedback_helper::get_all_feedbacks($userid); + return feedback_helper::get_all_feedbacks($USER->id); } public static function delete_feedback_returns() { diff --git a/lbplanner/services/feedback/get_all_feedbacks.php b/lbplanner/services/feedback/get_all_feedbacks.php index d33385a1..d91d31a0 100644 --- a/lbplanner/services/feedback/get_all_feedbacks.php +++ b/lbplanner/services/feedback/get_all_feedbacks.php @@ -19,8 +19,6 @@ use external_api; use external_function_parameters; use external_multiple_structure; -use external_value; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\feedback_helper; /** @@ -28,24 +26,12 @@ */ class feedback_get_all_feedbacks extends external_api { public static function get_all_feedbacks_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value(PARAM_INT, 'The id of the user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - )); + return new external_function_parameters([]); } - public static function get_all_feedbacks($userid) { - global $DB; - - self::validate_parameters( - self::get_all_feedbacks_parameters(), - array('userid' => $userid) - ); - - user_helper::assert_access($userid); - + public static function get_all_feedbacks(): array { feedback_helper::assert_admin_access(); - - return feedback_helper::get_all_feedbacks($userid); + return feedback_helper::get_all_feedbacks(); } public static function get_all_feedbacks_returns() { diff --git a/lbplanner/services/feedback/get_feedback.php b/lbplanner/services/feedback/get_feedback.php index a280630e..7b9700ba 100644 --- a/lbplanner/services/feedback/get_feedback.php +++ b/lbplanner/services/feedback/get_feedback.php @@ -19,7 +19,6 @@ use external_api; use external_function_parameters; use external_value; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\feedback_helper; /** @@ -27,24 +26,22 @@ */ class feedback_get_feedback extends external_api { public static function get_feedback_parameters() { - return new external_function_parameters(array( + return new external_function_parameters([ 'feedbackid' => new external_value(PARAM_INT, 'The id of the course', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'userid' => new external_value(PARAM_INT, 'The id of the user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - )); + ]); } - public static function get_feedback($feedbackid, $userid) { + public static function get_feedback($feedbackid) { global $DB; self::validate_parameters( self::get_feedback_parameters(), - array('feedbackid' => $feedbackid, 'userid' => $userid) + ['feedbackid' => $feedbackid] ); - user_helper::assert_access($userid); feedback_helper::assert_admin_access(); - if (!$DB->record_exists(feedback_helper::LBPLANNER_FEEDBACK_TABLE, array('id' => $feedbackid))) { + if (!$DB->record_exists(feedback_helper::LBPLANNER_FEEDBACK_TABLE, ['id' => $feedbackid])) { throw new \moodle_exception('feedback_not_found'); } diff --git a/lbplanner/services/feedback/submit_feedback.php b/lbplanner/services/feedback/submit_feedback.php index 15722cb9..6c9e36bd 100644 --- a/lbplanner/services/feedback/submit_feedback.php +++ b/lbplanner/services/feedback/submit_feedback.php @@ -20,7 +20,6 @@ use external_function_parameters; use external_single_structure; use external_value; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\feedback_helper; /** @@ -29,33 +28,30 @@ class feedback_submit_feedback extends external_api { public static function submit_feedback_parameters() { return new external_function_parameters( - array( - 'userid' => new external_value(PARAM_INT, 'The id of the user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + [ 'type' => new external_value(PARAM_INT, 'The type ', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), 'content' => new external_value(PARAM_TEXT, 'The content of the feedback', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), 'logfile' => new external_value(PARAM_TEXT, 'The name of the logfile', VALUE_DEFAULT, null, NULL_NOT_ALLOWED ), - ) + ] ); } - public static function submit_feedback($userid, $type, $content, $logfile) { - global $DB; + public static function submit_feedback($type, $content, $logfile) { + global $DB, $USER; self::validate_parameters( self::submit_feedback_parameters(), - array('userid' => $userid, 'type' => $type, 'content' => $content, 'logfile' => $logfile) + ['type' => $type, 'content' => $content, 'logfile' => $logfile] ); - user_helper::assert_access($userid); - - $id = $DB->insert_record(feedback_helper::LBPLANNER_FEEDBACK_TABLE, array( + $id = $DB->insert_record(feedback_helper::LBPLANNER_FEEDBACK_TABLE, [ 'content' => $content, - 'userid' => $userid, + 'userid' => $USER->id, 'type' => $type, 'status' => feedback_helper::STATUS_UNREAD, 'timestamp' => time(), 'logfile' => $logfile, - )); + ]); return feedback_helper::get_feedback($id); } diff --git a/lbplanner/services/feedback/update_feedback.php b/lbplanner/services/feedback/update_feedback.php index 256e217d..ca0c84a5 100644 --- a/lbplanner/services/feedback/update_feedback.php +++ b/lbplanner/services/feedback/update_feedback.php @@ -20,7 +20,6 @@ use external_function_parameters; use external_value; use gradereport_singleview\local\ui\feedback; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\feedback_helper; /** @@ -28,37 +27,35 @@ */ class feedback_update_feedback extends external_api { public static function update_feedback_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value(PARAM_INT, 'The id of the user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + return new external_function_parameters([ 'feedbackid' => new external_value(PARAM_INT, 'The id of the course', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), 'notes' => new external_value(PARAM_TEXT, 'The notes of the feedback', VALUE_DEFAULT, null, NULL_ALLOWED), 'status' => new external_value(PARAM_INT, 'The status of the feedback', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - )); + ]); } - public static function update_feedback($userid, $feedbackid, $notes, $status) { - global $DB; + public static function update_feedback($feedbackid, $notes, $status) { + global $DB, $USER; self::validate_parameters( self::update_feedback_parameters(), - array('userid' => $userid , 'feedbackid' => $feedbackid, 'notes' => $notes, 'status' => $status) + ['feedbackid' => $feedbackid, 'notes' => $notes, 'status' => $status] ); - user_helper::assert_access($userid); feedback_helper::assert_admin_access(); - if (!$DB->record_exists(feedback_helper::LBPLANNER_FEEDBACK_TABLE, array('id' => $feedbackid))) { + if (!$DB->record_exists(feedback_helper::LBPLANNER_FEEDBACK_TABLE, ['id' => $feedbackid])) { throw new \moodle_exception('feedback_not_found'); } - $feedback = $DB->get_record(feedback_helper::LBPLANNER_FEEDBACK_TABLE, array('id' => $feedbackid), '*', MUST_EXIST); + $feedback = $DB->get_record(feedback_helper::LBPLANNER_FEEDBACK_TABLE, ['id' => $feedbackid], '*', MUST_EXIST); $feedback->notes = $notes; if ($status > 1 || $status < 0) { throw new \moodle_exception('Invalid status'); } $feedback->status = $status; $feedback->lastmodified = time(); - $feedback->lastmodifiedby = $userid; + $feedback->lastmodifiedby = $USER->id; $DB->update_record(feedback_helper::LBPLANNER_FEEDBACK_TABLE, $feedback); diff --git a/lbplanner/services/notifications/get_all_notifications.php b/lbplanner/services/notifications/get_all_notifications.php index 06f52bde..24e8dc52 100644 --- a/lbplanner/services/notifications/get_all_notifications.php +++ b/lbplanner/services/notifications/get_all_notifications.php @@ -21,7 +21,6 @@ use external_multiple_structure; use external_single_structure; use external_value; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\notifications_helper; /** @@ -29,24 +28,18 @@ */ class notifications_get_all_notifications extends external_api { public static function get_all_notifications_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value(PARAM_INT, 'User ID', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - )); + return new external_function_parameters([]); } - public static function get_all_notifications($userid) { - global $DB; + public static function get_all_notifications() { + global $DB, $USER; - self::validate_parameters(self::get_all_notifications_parameters(), array('userid' => $userid)); + $dbnotifications = $DB->get_records(notifications_helper::TABLE, ['userid' => $USER->id]); - user_helper::assert_access($userid); - - $dbnotifications = $DB->get_records(notifications_helper::TABLE, array('userid' => $userid)); - - $notifications = array(); + $notifications = []; foreach ($dbnotifications as $dbnotification) { - $notifications[] = array( + $notifications[] = [ 'status' => $dbnotification->status, 'type' => $dbnotification->type, 'info' => $dbnotification->info, @@ -54,7 +47,7 @@ public static function get_all_notifications($userid) { 'notificationid' => $dbnotification->id, 'timestamp' => $dbnotification->timestamp, 'timestamp_read' => $dbnotification->timestamp_read, - ); + ]; } return $notifications; } @@ -62,7 +55,7 @@ public static function get_all_notifications($userid) { public static function get_all_notifications_returns() { return new external_multiple_structure( new external_single_structure( - array( + [ 'status' => new external_value(PARAM_INT, 'The status of the notification {0: unread, 1: read}'), 'type' => new external_value(PARAM_INT, 'The type of the event that triggered the notification'), 'info' => new external_value(PARAM_INT, 'Additional information about the notification'), @@ -70,7 +63,7 @@ public static function get_all_notifications_returns() { 'notificationid' => new external_value(PARAM_INT, 'The ID of the notification', NULL_NOT_ALLOWED), 'timestamp' => new external_value(PARAM_INT, 'The timestamp of the notification'), 'timestamp_read' => new external_value(PARAM_INT, 'The timestamp of the notification when it was read'), - ) + ] ) ); } diff --git a/lbplanner/services/notifications/update_notification.php b/lbplanner/services/notifications/update_notification.php index 912cb2b0..b005320e 100644 --- a/lbplanner/services/notifications/update_notification.php +++ b/lbplanner/services/notifications/update_notification.php @@ -20,7 +20,6 @@ use external_function_parameters; use external_single_structure; use external_value; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\notifications_helper; /** @@ -28,8 +27,7 @@ */ class notifications_update_notification extends external_api { public static function update_notification_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value(PARAM_INT, 'User ID', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + return new external_function_parameters([ 'status' => new external_value( PARAM_INT, 'The status of the notification {0: unread, 1: read}', @@ -38,30 +36,28 @@ public static function update_notification_parameters() { NULL_NOT_ALLOWED ), 'notificationid' => new external_value(PARAM_INT, 'The ID of the notification', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - )); + ]); } - public static function update_notification($userid, $status, $notificationid) { + public static function update_notification($status, $notificationid) { global $DB; self::validate_parameters( self::update_notification_parameters(), - array('userid' => $userid, 'status' => $status, 'notificationid' => $notificationid) + ['status' => $status, 'notificationid' => $notificationid] ); - user_helper::assert_access($userid); - - if (!$DB->record_exists(notifications_helper::TABLE, array('id' => $notificationid))) { + if (!$DB->record_exists(notifications_helper::TABLE, ['id' => $notificationid])) { throw new \moodle_exception('Notification does not exist'); } - $notification = $DB->get_record(notifications_helper::TABLE, array('id' => $notificationid), '*', MUST_EXIST); + $notification = $DB->get_record(notifications_helper::TABLE, ['id' => $notificationid], '*', MUST_EXIST); $notification->status = $status; $notification->timestamp_read = time(); $DB->update_record(notifications_helper::TABLE, $notification); - return array( + return [ 'status' => $notification->status, 'type' => $notification->type, 'info' => $notification->info, @@ -69,12 +65,12 @@ public static function update_notification($userid, $status, $notificationid) { 'notificationid' => $notification->id, 'timestamp' => $notification->timestamp, 'timestamp_read' => $notification->timestamp_read, - ); + ]; } public static function update_notification_returns() { return new external_single_structure( - array( + [ 'status' => new external_value(PARAM_INT, 'The status of the notification {0: unread, 1: read}'), 'type' => new external_value(PARAM_INT, 'The type of the event that triggered the notification'), 'info' => new external_value(PARAM_INT, 'Additional information about the notification'), @@ -82,7 +78,7 @@ public static function update_notification_returns() { 'notificationid' => new external_value(PARAM_INT, 'The ID of the notification'), 'timestamp' => new external_value(PARAM_INT, 'The timestamp of the notification'), 'timestamp_read' => new external_value(PARAM_INT, 'The timestamp of the notification'), - ) + ] ); } } diff --git a/lbplanner/services/plan/accept_invite.php b/lbplanner/services/plan/accept_invite.php index 6bce45e3..4d8ba271 100644 --- a/lbplanner/services/plan/accept_invite.php +++ b/lbplanner/services/plan/accept_invite.php @@ -20,7 +20,6 @@ use external_function_parameters; use external_single_structure; use external_value; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; use local_lbplanner\helpers\PLAN_ACCESS_TYPE; @@ -31,36 +30,32 @@ */ class plan_accept_invite extends external_api { public static function accept_invite_parameters() { - return new external_function_parameters(array( + return new external_function_parameters([ 'inviteid' => new external_value(PARAM_INT, 'The id of the plan', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'userid' => new external_value(PARAM_INT, 'The id of the invited user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED) - )); + ]); } - public static function accept_invite($inviteid, $userid) { - global $DB; + public static function accept_invite($inviteid) { + global $DB, $USER; - self::validate_parameters(self::accept_invite_parameters(), array( + self::validate_parameters(self::accept_invite_parameters(), [ 'inviteid' => $inviteid, - 'userid' => $userid, - )); + ]); - user_helper::assert_access($userid); - - if (!$DB->record_exists(plan_helper::INVITES_TABLE, array('id' => $inviteid, 'inviteeid' => $userid))) { + if (!$DB->record_exists(plan_helper::INVITES_TABLE, ['id' => $inviteid, 'inviteeid' => $USER->id])) { throw new \moodle_exception('Invite not found'); } if (!$DB->record_exists(plan_helper::INVITES_TABLE, - array( 'id' => $inviteid, 'inviteeid' => $userid, 'status' => PLAN_INVITE_STATE::PENDING->value))) { + [ 'id' => $inviteid, 'inviteeid' => $USER->id, 'status' => PLAN_INVITE_STATE::PENDING->value])) { throw new \moodle_exception('Invite already accepted or declined'); } $invite = $DB->get_record(plan_helper::INVITES_TABLE, - array( + [ 'id' => $inviteid, - 'inviteeid' => $userid, + 'inviteeid' => $USER->id, 'status' => PLAN_INVITE_STATE::PENDING->value, - ), + ], '*', MUST_EXIST ); @@ -72,31 +67,31 @@ public static function accept_invite($inviteid, $userid) { notifications_helper::TRIGGER_INVITE_ACCEPTED ); - // If the User is the User has Member in his plan, then removes it. - $oldplanid = plan_helper::get_plan_id($userid); - if (plan_helper::get_owner($oldplanid) == $userid) { + // Deletes the old plan if the user is the owner of it. + $oldplanid = plan_helper::get_plan_id($USER->id); + if (plan_helper::get_owner($oldplanid) == $USER->id) { foreach (plan_helper::get_plan_members($oldplanid) as $member) { - if ($member->userid != $userid) { - self::call_external_function('local_lbplanner_plan_remove_user', array( + if ($member->userid != $USER->id) { + self::call_external_function('local_lbplanner_plan_remove_user', [ 'planid' => $oldplanid, - 'userid' => $member->userid - )); + 'userid' => $member->userid, + ]); } } - self::call_external_function('local_lbplanner_plan_clear_plan', array( + self::call_external_function('local_lbplanner_plan_clear_plan', [ 'planid' => $oldplanid, - 'userid' => $userid - )); - $DB->delete_records(plan_helper::TABLE, array('id' => $oldplanid)); + 'userid' => $USER->id, + ]); + $DB->delete_records(plan_helper::TABLE, ['id' => $oldplanid]); } // Updates the plan access. $planaccess = $DB->get_record( plan_helper::ACCESS_TABLE, - array( + [ 'planid' => $oldplanid, - 'userid' => $userid - ), + 'userid' => $USER->id, + ], '*', MUST_EXIST ); @@ -109,7 +104,7 @@ public static function accept_invite($inviteid, $userid) { $planaccess->planid = $invite->planid; $DB->update_record(plan_helper::ACCESS_TABLE, $planaccess); - $invites = plan_helper::get_invites_send($userid); + $invites = plan_helper::get_invites_send($USER->id); foreach ($invites as $invite) { if ($invite->status == PLAN_INVITE_STATE::PENDING->value) { $invite->status = PLAN_INVITE_STATE::EXPIRED->value; @@ -117,27 +112,27 @@ public static function accept_invite($inviteid, $userid) { } } - return array( + return [ 'id' => $invite->id, 'inviterid' => $invite->inviterid, 'inviteeid' => $invite->inviteeid, 'planid' => $invite->planid, 'status' => $invite->status, 'timestamp' => $invite->timestamp, - ); + ]; } public static function accept_invite_returns() { return new external_single_structure( - array( + [ 'id' => new external_value(PARAM_INT, 'The id of the invite'), 'inviterid' => new external_value(PARAM_INT, 'The id of the owner user'), 'inviteeid' => new external_value(PARAM_INT, 'The id of the invited user'), 'planid' => new external_value(PARAM_INT, 'The id of the plan'), 'status' => new external_value(PARAM_INT, 'The Status of the invitation'), 'timestamp' => new external_value(PARAM_INT, 'The time when the invitation was send'), - ) + ] ); } } diff --git a/lbplanner/services/plan/add_deadline.php b/lbplanner/services/plan/add_deadline.php index 3dd6329c..27591b73 100644 --- a/lbplanner/services/plan/add_deadline.php +++ b/lbplanner/services/plan/add_deadline.php @@ -19,7 +19,6 @@ use external_api; use external_function_parameters; use external_value; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\plan_helper; /** @@ -27,21 +26,7 @@ */ class plan_add_deadline extends external_api { public static function add_deadline_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value( - PARAM_INT, - 'The id of the user to get the data for', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - 'planid' => new external_value( - PARAM_INT, - 'The ID of the Plan', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), + return new external_function_parameters([ 'moduleid' => new external_value( PARAM_INT, 'The ID of the Module', @@ -63,30 +48,28 @@ public static function add_deadline_parameters() { null, NULL_NOT_ALLOWED ), - )); + ]); } - public static function add_deadline($userid, $planid, $moduleid, $deadlinestart, $deadlineend) { - global $DB; + public static function add_deadline($moduleid, $deadlinestart, $deadlineend) { + global $DB, $USER; self::validate_parameters( self::add_deadline_parameters(), - array( - 'userid' => $userid, - 'planid' => $planid, + [ 'moduleid' => $moduleid, 'deadlinestart' => $deadlinestart, 'deadlineend' => $deadlineend, - ) + ] ); - user_helper::assert_access($userid); + $planid = plan_helper::get_plan_id($USER->id); - if ( !plan_helper::check_edit_permissions( $planid, $userid ) ) { + if ( !plan_helper::check_edit_permissions( $planid, $USER->id ) ) { throw new \moodle_exception('Access denied'); } - if ($DB->record_exists(plan_helper::DEADLINES_TABLE, array('moduleid' => $moduleid, 'planid' => $planid))) { + if ($DB->record_exists(plan_helper::DEADLINES_TABLE, ['moduleid' => $moduleid, 'planid' => $planid])) { throw new \moodle_exception('Deadline already exists'); } @@ -99,8 +82,6 @@ public static function add_deadline($userid, $planid, $moduleid, $deadlinestart, $DB->insert_record(plan_helper::DEADLINES_TABLE, $deadline); - $plan = $DB->get_record(plan_helper::TABLE, array('id' => $planid)); - return plan_helper::get_plan($planid); } diff --git a/lbplanner/services/plan/clear_plan.php b/lbplanner/services/plan/clear_plan.php index 30755937..9bbe49c4 100644 --- a/lbplanner/services/plan/clear_plan.php +++ b/lbplanner/services/plan/clear_plan.php @@ -18,47 +18,26 @@ use external_api; use external_function_parameters; -use external_value; use local_lbplanner\helpers\plan_helper; -use local_lbplanner\helpers\user_helper; /** * Clear the plan for the given user. */ class plan_clear_plan extends external_api { public static function clear_plan_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value( - PARAM_INT, - 'The id of the user to get the data for', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - 'planid' => new external_value( - PARAM_INT, - 'The id of the plan', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - )); + return new external_function_parameters([]); } - public static function clear_plan($userid, $planid) { - global $DB; + public static function clear_plan() { + global $DB, $USER; - self::validate_parameters(self::clear_plan_parameters(), array('userid' => $userid, 'planid' => $planid)); + $planid = plan_helper::get_plan_id($USER->id); - user_helper::assert_access($userid); - - if (!plan_helper::check_edit_permissions($planid, $userid)) { + if (!plan_helper::check_edit_permissions($planid, $USER->id)) { throw new \Exception('Access denied'); } - $DB->delete_records(plan_helper::DEADLINES_TABLE, array('planid' => $planid )); - - $plan = $DB->get_record(plan_helper::TABLE, array('id' => $planid)); + $DB->delete_records(plan_helper::DEADLINES_TABLE, ['planid' => $planid ]); return plan_helper::get_plan($planid); } diff --git a/lbplanner/services/plan/decline_invite.php b/lbplanner/services/plan/decline_invite.php index 4dc64381..e7cf14df 100644 --- a/lbplanner/services/plan/decline_invite.php +++ b/lbplanner/services/plan/decline_invite.php @@ -20,50 +20,44 @@ use external_function_parameters; use external_single_structure; use external_value; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; use local_lbplanner\helpers\PLAN_INVITE_STATE; /** - * Update a invite from the plan. + * Decline an invite from the plan. */ class plan_decline_invite extends external_api { public static function decline_invite_parameters() { - return new external_function_parameters(array( + return new external_function_parameters([ 'inviteid' => new external_value(PARAM_INT, 'The inviteid of the plan', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'userid' => new external_value(PARAM_INT, 'The id of the invited user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED) - )); + ]); } - public static function decline_invite($inviteid, $userid) { - global $DB; + public static function decline_invite($inviteid) { + global $DB, $USER; - self::validate_parameters(self::decline_invite_parameters(), array( + self::validate_parameters(self::decline_invite_parameters(), [ 'inviteid' => $inviteid, - 'userid' => $userid, - )); + ]); - user_helper::assert_access($userid); - - if (!$DB->record_exists(plan_helper::INVITES_TABLE, array('id' => $inviteid, 'inviteeid' => $userid))) { + if (!$DB->record_exists(plan_helper::INVITES_TABLE, ['id' => $inviteid, 'inviteeid' => $USER->id])) { throw new \moodle_exception('Invite not found'); } - if (!$DB->record_exists(plan_helper::INVITES_TABLE, - array('id' => $inviteid, 'inviteeid' => $userid, 'status' => PLAN_INVITE_STATE::PENDING->value))) { - throw new \moodle_exception('Invite already accepted or declined'); - } $invite = $DB->get_record(plan_helper::INVITES_TABLE, - array( + [ 'id' => $inviteid, - 'inviteeid' => $userid, - 'status' => PLAN_INVITE_STATE::PENDING->value, - ), + 'inviteeid' => $USER->id, + ], '*', MUST_EXIST ); + if ($invite->status !== PLAN_INVITE_STATE::PENDING->value) { + throw new \moodle_exception('Invite already accepted or declined'); + } + // Notify the user that invite has been declined. notifications_helper::notify_user( $invite->inviterid, @@ -75,27 +69,27 @@ public static function decline_invite($inviteid, $userid) { $DB->update_record(plan_helper::INVITES_TABLE, $invite); - return array( + return [ 'id' => $invite->id, 'inviterid' => $invite->inviterid, 'inviteeid' => $invite->inviteeid, 'planid' => $invite->planid, 'status' => $invite->status, 'timestamp' => $invite->timestamp, - ); + ]; } public static function decline_invite_returns() { return new external_single_structure( - array( + [ 'id' => new external_value(PARAM_INT, 'The id of the invite'), 'inviterid' => new external_value(PARAM_INT, 'The id of the owner user'), 'inviteeid' => new external_value(PARAM_INT, 'The id of the invited user'), 'planid' => new external_value(PARAM_INT, 'The id of the plan'), 'status' => new external_value(PARAM_INT, 'The Status of the invitation'), 'timestamp' => new external_value(PARAM_INT, 'The time when the invitation was send'), - ) + ] ); } } diff --git a/lbplanner/services/plan/delete_deadline.php b/lbplanner/services/plan/delete_deadline.php index 971bfb4d..e4898ffc 100644 --- a/lbplanner/services/plan/delete_deadline.php +++ b/lbplanner/services/plan/delete_deadline.php @@ -20,28 +20,13 @@ use external_function_parameters; use external_value; use local_lbplanner\helpers\plan_helper; -use local_lbplanner\helpers\user_helper; /** - * Delete a deadline from the plan. + * Delete a deadline from your plan */ class plan_delete_deadline extends external_api { public static function delete_deadline_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value( - PARAM_INT, - 'The id of the user to get the data for', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - 'planid' => new external_value( - PARAM_INT, - 'The ID of the Plan', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), + return new external_function_parameters([ 'moduleid' => new external_value( PARAM_INT, 'The ID of the Module', @@ -49,33 +34,31 @@ public static function delete_deadline_parameters() { null, NULL_NOT_ALLOWED ), - )); + ]); } - public static function delete_deadline($userid, $planid, $moduleid) { - global $DB; + public static function delete_deadline($moduleid) { + global $DB, $USER; self::validate_parameters( self::delete_deadline_parameters(), - array( - 'userid' => $userid, - 'planid' => $planid, + [ 'moduleid' => $moduleid, - ) + ] ); - user_helper::assert_access($userid); + $planid = plan_helper::get_plan_id($USER->id); - if (!plan_helper::check_edit_permissions($planid, $userid)) { + if (!plan_helper::check_edit_permissions($planid, $USER->id)) { throw new \Exception('Access denied'); } $DB->delete_records( plan_helper::DEADLINES_TABLE, - array( + [ 'planid' => $planid , - 'moduleid' => $moduleid - ) + 'moduleid' => $moduleid, + ] ); return plan_helper::get_plan($planid); diff --git a/lbplanner/services/plan/get_access.php b/lbplanner/services/plan/get_access.php deleted file mode 100644 index d209ca76..00000000 --- a/lbplanner/services/plan/get_access.php +++ /dev/null @@ -1,70 +0,0 @@ -. - -namespace local_lbplanner_services; - -use external_api; -use external_function_parameters; -use external_single_structure; -use external_value; -use local_lbplanner\helpers\plan_helper; -use local_lbplanner\helpers\user_helper; - -/** - * Get the access type to the plan. - */ -class plan_get_access extends external_api { - public static function get_access_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value( - PARAM_INT, - 'The id of the user to get the data for', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - 'planid' => new external_value( - PARAM_INT, - 'The id of the plan', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - )); - } - - public static function get_access($userid, $planid) { - self::validate_parameters(self::get_access_parameters(), array('userid' => $userid, 'planid' => $planid)); - - user_helper::assert_access($userid); - - return array( - 'accesstype' => plan_helper::get_access_type($userid, $planid), - 'planid' => $planid, - 'userid' => $userid, - ); - } - - public static function get_access_returns() { - return new external_single_structure( - array( - 'accesstype' => new external_value(PARAM_INT, 'The type of access the user has to the plan'), - 'planid' => new external_value(PARAM_INT, 'The id of the plan'), - 'userid' => new external_value(PARAM_INT, 'The id of the plan'), - ) - ); - } -} diff --git a/lbplanner/services/plan/get_invites.php b/lbplanner/services/plan/get_invites.php index ca2e02db..8afac08d 100644 --- a/lbplanner/services/plan/get_invites.php +++ b/lbplanner/services/plan/get_invites.php @@ -21,60 +21,44 @@ use external_single_structure; use external_multiple_structure; use external_value; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\plan_helper; /** - * Get all the invites of the given user. + * Get all the invites of the current user. */ class plan_get_invites extends external_api { public static function get_invites_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value( - PARAM_INT, - 'The id of the Owner of the plan', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - )); + return new external_function_parameters([]); } - public static function get_invites($userid) { - global $DB; + public static function get_invites() { + global $DB, $USER; - self::validate_parameters( - self::get_invites_parameters(), - array('userid' => $userid) - ); - - user_helper::assert_access($userid); - - $invitesreceived = $DB->get_records(plan_helper::INVITES_TABLE, array('inviteeid' => $userid)); - $invitessent = $DB->get_records(plan_helper::INVITES_TABLE, array('inviterid' => $userid)); + $invitesreceived = $DB->get_records(plan_helper::INVITES_TABLE, ['inviteeid' => $USER->id]); + $invitessent = $DB->get_records(plan_helper::INVITES_TABLE, ['inviterid' => $USER->id]); - $invites = array(); + $invites = []; foreach ($invitesreceived as $invite) { - $invites[] = array( + $invites[] = [ 'id' => $invite->id, 'inviterid' => $invite->inviterid, 'inviteeid' => $invite->inviteeid, 'planid' => $invite->planid, 'status' => $invite->status, 'timestamp' => $invite->timestamp, - ); + ]; } foreach ($invitessent as $invitesent) { - $invites[] = array( + $invites[] = [ 'id' => $invitesent->id, 'inviterid' => $invitesent->inviterid, 'inviteeid' => $invitesent->inviteeid, 'planid' => $invitesent->planid, 'status' => $invitesent->status, 'timestamp' => $invitesent->timestamp, - ); + ]; } return $invites; @@ -83,14 +67,14 @@ public static function get_invites($userid) { public static function get_invites_returns() { return new external_multiple_structure( new external_single_structure( - array( + [ 'id' => new external_value(PARAM_INT, 'The id of the invite'), 'inviterid' => new external_value(PARAM_INT, 'The id of the owner user'), 'inviteeid' => new external_value(PARAM_INT, 'The id of the invited user'), 'planid' => new external_value(PARAM_INT, 'The id of the plan'), 'status' => new external_value(PARAM_INT, 'The Status of the invitation'), 'timestamp' => new external_value(PARAM_INT, 'The time when the invitation was send'), - ) + ] ) ); } diff --git a/lbplanner/services/plan/get_plan.php b/lbplanner/services/plan/get_plan.php index e5aa3693..e4913ba7 100644 --- a/lbplanner/services/plan/get_plan.php +++ b/lbplanner/services/plan/get_plan.php @@ -18,36 +18,20 @@ use external_api; use external_function_parameters; -use external_value; use local_lbplanner\helpers\plan_helper; -use local_lbplanner\helpers\user_helper; /** * Get the plan of the given user. */ class plan_get_plan extends external_api { public static function get_plan_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value( - PARAM_INT, - 'The id of the user', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - )); + return new external_function_parameters([]); } - public static function get_plan($userid) { - global $DB; + public static function get_plan() { + global $DB, $USER; - self::validate_parameters(self::get_plan_parameters(), array('userid' => $userid)); - - user_helper::assert_access($userid); - - $planid = plan_helper::get_plan_id($userid); - - $plan = $DB->get_record(plan_helper::TABLE, array('id' => $planid)); + $planid = plan_helper::get_plan_id($USER->id); return plan_helper::get_plan($planid); } diff --git a/lbplanner/services/plan/invite_user.php b/lbplanner/services/plan/invite_user.php index 3d53f6fb..d2a428fd 100644 --- a/lbplanner/services/plan/invite_user.php +++ b/lbplanner/services/plan/invite_user.php @@ -21,23 +21,15 @@ use external_single_structure; use external_value; use local_lbplanner\helpers\plan_helper; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\notifications_helper; use local_lbplanner\helpers\PLAN_INVITE_STATE; /** - * Invite a user to the plan. + * Invite a user to your plan */ class plan_invite_user extends external_api { public static function invite_user_parameters() { - return new external_function_parameters(array( - 'inviterid' => new external_value( - PARAM_INT, - 'The id of the Owner of the plan', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), + return new external_function_parameters([ 'inviteeid' => new external_value( PARAM_INT, 'The id of the user who gets invited', @@ -45,30 +37,24 @@ public static function invite_user_parameters() { null, NULL_NOT_ALLOWED ), - 'planid' => new external_value( - PARAM_INT, - 'The id of the plan', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - )); + ]); } - public static function invite_user($inviterid, $inviteeid , $planid) { - global $DB; + public static function invite_user($inviteeid) { + global $DB, $USER; self::validate_parameters( self::invite_user_parameters(), - array('inviterid' => $inviterid, 'inviteeid' => $inviteeid, 'planid' => $planid) + ['inviteeid' => $inviteeid] ); - user_helper::assert_access($inviterid); - if (plan_helper::get_owner($planid) != $inviterid) { + $planid = plan_helper::get_plan_id($USER->id); + + if (plan_helper::get_owner($planid) !== $USER->id) { throw new \moodle_exception('Access denied'); } - if ($inviterid == $inviteeid) { + if ($USER->id === $inviteeid) { throw new \moodle_exception('Cannot invite yourself'); } @@ -78,55 +64,48 @@ public static function invite_user($inviterid, $inviteeid , $planid) { if ($DB->record_exists( plan_helper::INVITES_TABLE, - array('inviteeid' => $inviteeid, 'planid' => $planid, 'status' => PLAN_INVITE_STATE::PENDING->value) + ['inviteeid' => $inviteeid, 'planid' => $planid, 'status' => PLAN_INVITE_STATE::PENDING->value] )) { throw new \moodle_exception('User is already invited'); } - $invitee = user_helper::get_mdl_user_info($inviteeid); - $inviter = user_helper::get_mdl_user_info($inviterid); - - if ($invitee->address != $inviter->address) { - throw new \moodle_exception('Cannot invite user who is not in the same class'); - } - // Save the invite. $invite = new \stdClass(); $invite->planid = $planid; - $invite->inviterid = $inviterid; + $invite->inviterid = $USER->id; $invite->inviteeid = $inviteeid; $invite->timestamp = time(); $invite->status = PLAN_INVITE_STATE::PENDING->value; $invite->id = $DB->insert_record(plan_helper::INVITES_TABLE, $invite); - // Notifiy the invitee that he/she/it/they/xier/* has been invited. + // Notify the invitee that they've been invited. notifications_helper::notify_user( $inviteeid, $invite->id, notifications_helper::TRIGGER_INVITE ); - return array( + return [ 'id' => $invite->id, - 'inviterid' => $inviterid, + 'inviterid' => $USER->id, 'inviteeid' => $inviteeid, 'planid' => $planid, 'timestamp' => $invite->timestamp, - 'status' => $invite->status - ); + 'status' => $invite->status, + ]; } public static function invite_user_returns() { return new external_single_structure( - array( + [ 'id' => new external_value(PARAM_INT, 'The id of the invite'), 'inviterid' => new external_value(PARAM_INT, 'The id of the owner user'), 'inviteeid' => new external_value(PARAM_INT, 'The id of the invited user'), 'planid' => new external_value(PARAM_INT, 'The id of the plan'), 'status' => new external_value(PARAM_INT, 'The status of the invitation'), 'timestamp' => new external_value(PARAM_INT, 'The time when the invitation was send'), - ) + ] ); } } diff --git a/lbplanner/services/plan/leave_plan.php b/lbplanner/services/plan/leave_plan.php index 1eb4552f..4545cfb0 100644 --- a/lbplanner/services/plan/leave_plan.php +++ b/lbplanner/services/plan/leave_plan.php @@ -18,58 +18,40 @@ use external_api; use external_function_parameters; -use external_value; use local_lbplanner\helpers\plan_helper; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\notifications_helper; use local_lbplanner\helpers\PLAN_ACCESS_TYPE; use local_lbplanner\helpers\PLAN_INVITE_STATE; /** - * Leave the plan of the given user. + * Leave your plan + * if no other user exists in the plan, the user can't leave */ class plan_leave_plan extends external_api { public static function leave_plan_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value( - PARAM_INT, - 'The id of the user to get the data for', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - 'planid' => new external_value( - PARAM_INT, - 'The id of the plan', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - )); + return new external_function_parameters([]); } - public static function leave_plan($userid, $planid) { - global $DB; + public static function leave_plan() { + global $DB, $USER; - self::validate_parameters(self::leave_plan_parameters(), array('userid' => $userid, 'planid' => $planid)); + $planid = plan_helper::get_plan_id($USER->id); - user_helper::assert_access($userid); - - if (plan_helper::get_access_type($userid, $planid) == PLAN_ACCESS_TYPE::NONE) { + if (plan_helper::get_access_type($USER->id, $planid) === PLAN_ACCESS_TYPE::NONE) { throw new \moodle_exception('User is not a member of this plan'); } - if (plan_helper::get_access_type($userid, $planid) == PLAN_ACCESS_TYPE::OWNER) { + if (plan_helper::get_access_type($USER->id, $planid) === PLAN_ACCESS_TYPE::OWNER) { $members = plan_helper::get_plan_members($planid); if (count($members) == 1) { throw new \moodle_exception('Cannot Leave Plan: Plan must have at least one other member'); } - $writemembers = array(); - $allmembers = array(); + $writemembers = []; + $allmembers = []; foreach ($members as $member) { - if ($member->userid == $userid) { + if ($member->userid == $USER->id) { continue; } if ($member->accesstype == PLAN_ACCESS_TYPE::WRITE->value) { @@ -84,17 +66,17 @@ public static function leave_plan($userid, $planid) { } $newowneraccess = $DB->get_record( plan_helper::ACCESS_TABLE, - array('planid' => $planid, 'userid' => $newowner), '*', MUST_EXIST + ['planid' => $planid, 'userid' => $newowner], '*', MUST_EXIST ); $newowneraccess->accesstype = PLAN_ACCESS_TYPE::OWNER->value; $DB->update_record(plan_helper::ACCESS_TABLE, $newowneraccess); } - $newplanid = plan_helper::copy_plan($planid, $userid); + $newplanid = plan_helper::copy_plan($planid, $USER->id); $oldaccess = $DB->get_record( plan_helper::ACCESS_TABLE, - array('planid' => $planid, 'userid' => $userid), '*', MUST_EXIST + ['planid' => $planid, 'userid' => $USER->id], '*', MUST_EXIST ); $oldaccess->planid = $newplanid; @@ -103,7 +85,7 @@ public static function leave_plan($userid, $planid) { $DB->update_record(plan_helper::ACCESS_TABLE, $oldaccess); // Notify plan owner that user has left his plan. - $invites = plan_helper::get_invites_send($userid); + $invites = plan_helper::get_invites_send($USER->id); foreach ($invites as $invite) { if ($invite->status == PLAN_INVITE_STATE::PENDING->value) { $invite->status = PLAN_INVITE_STATE::EXPIRED->value; @@ -113,11 +95,11 @@ public static function leave_plan($userid, $planid) { notifications_helper::notify_user( plan_helper::get_owner($planid), - $userid, + $USER->id, notifications_helper::TRIGGER_PLAN_LEFT ); - return plan_helper::get_plan($planid, $userid); + return plan_helper::get_plan($planid, $USER->id); } public static function leave_plan_returns() { return plan_helper::plan_structure(); diff --git a/lbplanner/services/plan/remove_user.php b/lbplanner/services/plan/remove_user.php index 1341ad24..b323997c 100644 --- a/lbplanner/services/plan/remove_user.php +++ b/lbplanner/services/plan/remove_user.php @@ -20,31 +20,28 @@ use external_function_parameters; use external_value; use local_lbplanner\helpers\plan_helper; -use local_lbplanner\helpers\user_helper; /** - * Remove a user from the plan. + * Remove a user from your plan */ class plan_remove_user extends external_api { public static function remove_user_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value(PARAM_INT, 'The id of the user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'removeuserid' => new external_value(PARAM_INT, 'The id of the user to remove', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'planid' => new external_value(PARAM_INT, 'The id of the plan', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - )); + return new external_function_parameters([ + 'userid' => new external_value(PARAM_INT, 'The id of the user to remove', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + ]); } - public static function remove_user($userid, $removeuserid, $planid) { - global $DB; + public static function remove_user($userid, $planid) { + global $DB, $USER; self::validate_parameters( self::remove_user_parameters(), - array('userid' => $userid, 'removeuserid' => $removeuserid, 'planid' => $planid) + ['userid' => $userid] ); - user_helper::assert_access($userid); + $planid = plan_helper::get_plan_id($USER->id); - return plan_helper::remove_user($planid, $userid, $removeuserid); + return plan_helper::remove_user($planid, $USER->id, $userid); } public static function remove_user_returns() { diff --git a/lbplanner/services/plan/update_access.php b/lbplanner/services/plan/update_access.php index 2bf88fa1..2c8fe036 100644 --- a/lbplanner/services/plan/update_access.php +++ b/lbplanner/services/plan/update_access.php @@ -21,28 +21,13 @@ use external_value; use local_lbplanner\helpers\PLAN_ACCESS_TYPE; use local_lbplanner\helpers\plan_helper; -use local_lbplanner\helpers\user_helper; /** * Update the access of the plan. */ class plan_update_access extends external_api { public static function update_access_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value( - PARAM_INT, - 'The id of the user to get the data for', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - 'planid' => new external_value( - PARAM_INT, - 'The id of the plan', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), + return new external_function_parameters([ 'accesstype' => new external_value( PARAM_INT, 'The access type', @@ -57,30 +42,30 @@ public static function update_access_parameters() { null, NULL_NOT_ALLOWED ), - )); + ]); } - public static function update_access($userid, $planid, $accesstype, $memberid) { - global $DB; + public static function update_access($accesstype, $memberid) { + global $DB, $USER; self::validate_parameters( self::update_access_parameters(), - array('userid' => $userid, 'planid' => $planid, 'accesstype' => $accesstype, 'memberid' => $memberid) + ['accesstype' => $accesstype, 'memberid' => $memberid] ); - user_helper::assert_access($userid); + $planid = plan_helper::get_plan_id($USER->id); - if (plan_helper::get_owner($planid) != $userid) { + if (plan_helper::get_owner($planid) !== $USER->id) { throw new \moodle_exception('Access denied'); } - $accesstype_obj = PLAN_ACCESS_TYPE::tryFrom($accesstype); + $accesstypeobj = PLAN_ACCESS_TYPE::tryFrom($accesstype); - if ($accesstype_obj === null) { + if ($accesstypeobj === null) { throw new \moodle_exception('Access type not valid'); } - if ($userid == $memberid) { + if ($USER->id === $memberid) { throw new \moodle_exception('Cannot change own permissions'); } @@ -88,11 +73,11 @@ public static function update_access($userid, $planid, $accesstype, $memberid) { throw new \moodle_exception('Cannot change permissions for the plan owner'); } - if ($accesstype_obj === PLAN_ACCESS_TYPE::OWNER) { + if ($accesstypeobj === PLAN_ACCESS_TYPE::OWNER) { throw new \moodle_exception('Cannot change permission to owner'); } - $access = $DB->get_record(plan_helper::ACCESS_TABLE, array('planid' => $planid, 'userid' => $memberid), '*', MUST_EXIST); + $access = $DB->get_record(plan_helper::ACCESS_TABLE, ['planid' => $planid, 'userid' => $memberid], '*', MUST_EXIST); $access->accesstype = $accesstype; $DB->update_record(plan_helper::ACCESS_TABLE, $access); diff --git a/lbplanner/services/plan/update_deadline.php b/lbplanner/services/plan/update_deadline.php index c85fe7cf..298bb829 100644 --- a/lbplanner/services/plan/update_deadline.php +++ b/lbplanner/services/plan/update_deadline.php @@ -19,7 +19,6 @@ use external_api; use external_function_parameters; use external_value; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\plan_helper; /** @@ -27,21 +26,7 @@ */ class plan_update_deadline extends external_api { public static function update_deadline_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value( - PARAM_INT, - 'The id of the user to get the data for', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - 'planid' => new external_value( - PARAM_INT, - 'The ID of the Plan', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), + return new external_function_parameters([ 'moduleid' => new external_value( PARAM_INT, 'The ID of the Module', @@ -63,33 +48,31 @@ public static function update_deadline_parameters() { null, NULL_NOT_ALLOWED ), - )); + ]); } - public static function update_deadline($userid, $planid, $moduleid, $deadlinestart, $deadlineend) { - global $DB; + public static function update_deadline($moduleid, $deadlinestart, $deadlineend) { + global $DB, $USER; self::validate_parameters( self::update_deadline_parameters(), - array( - 'userid' => $userid, - 'planid' => $planid, + [ 'moduleid' => $moduleid, 'deadlinestart' => $deadlinestart, 'deadlineend' => $deadlineend, - ) + ] ); - user_helper::assert_access($userid); + $planid = plan_helper::get_plan_id($USER->id); - if (!plan_helper::check_edit_permissions($planid, $userid)) { + if (!plan_helper::check_edit_permissions($planid, $USER->id)) { throw new \moodle_exception('Access denied'); } - if (!$DB->record_exists(plan_helper::DEADLINES_TABLE, array('moduleid' => $moduleid, 'planid' => $planid))) { + if (!$DB->record_exists(plan_helper::DEADLINES_TABLE, ['moduleid' => $moduleid, 'planid' => $planid])) { throw new \moodle_exception('Deadline doesnt exists'); } - $deadline = $DB->get_record(plan_helper::DEADLINES_TABLE, array('moduleid' => $moduleid, 'planid' => $planid)); + $deadline = $DB->get_record(plan_helper::DEADLINES_TABLE, ['moduleid' => $moduleid, 'planid' => $planid]); $deadline->deadlinestart = $deadlinestart; $deadline->deadlineend = $deadlineend; diff --git a/lbplanner/services/plan/update_invite.php b/lbplanner/services/plan/update_invite.php index 164dcfff..2acbdf55 100644 --- a/lbplanner/services/plan/update_invite.php +++ b/lbplanner/services/plan/update_invite.php @@ -20,7 +20,6 @@ use external_function_parameters; use external_single_structure; use external_value; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; use local_lbplanner\helpers\PLAN_ACCESS_TYPE; @@ -28,38 +27,35 @@ /** * THIS METHOD IS NOT USED ANYMORE. JUST TO KEEP OLD CODE FOR REFERENCE. + * TODO: delete */ class plan_update_invite extends external_api { public static function update_invite_parameters() { - return new external_function_parameters(array( + return new external_function_parameters([ 'planid' => new external_value(PARAM_INT, 'The id of the plan', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'userid' => new external_value(PARAM_INT, 'The id of the invited user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), 'status' => new external_value(PARAM_INT, 'The status of the invite', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - )); + ]); } - public static function update_invite($planid, $userid, $status) { - global $DB; + public static function update_invite($planid, $status) { + global $DB, $USER; - self::validate_parameters(self::update_invite_parameters(), array( + self::validate_parameters(self::update_invite_parameters(), [ 'planid' => $planid, - 'userid' => $userid, 'status' => $status, - )); + ]); - user_helper::assert_access($userid); + $statusobj = PLAN_INVITE_STATE::tryFrom($status); - $status_obj = PLAN_INVITE_STATE::tryFrom($status); - - if ($status_obj === null) { + if ($statusobj === null) { throw new \moodle_exception('Invalid status'); } $invite = $DB->get_record(plan_helper::INVITES_TABLE, - array( + [ 'planid' => $planid, - 'inviteeid' => $userid, - ), + 'inviteeid' => $USER->id, + ], '*', MUST_EXIST ); @@ -72,35 +68,35 @@ public static function update_invite($planid, $userid, $status) { $DB->update_record(plan_helper::INVITES_TABLE, $invite); - $trigger = $status_obj === PLAN_INVITE_STATE::ACCEPTED ? + $trigger = $statusobj === PLAN_INVITE_STATE::ACCEPTED ? notifications_helper::TRIGGER_INVITE_ACCEPTED : notifications_helper::TRIGGER_INVITE_DECLINED; - notifications_helper::notify_user($invite->inviterid, $userid , $trigger); + notifications_helper::notify_user($invite->inviterid, $USER->id , $trigger); // TODO: Change plan access and delete old plan if inivite is accepted. - if ($status_obj == PLAN_INVITE_STATE::ACCEPTED) { - $oldplanid = plan_helper::get_plan_id($userid); + if ($statusobj == PLAN_INVITE_STATE::ACCEPTED) { + $oldplanid = plan_helper::get_plan_id($USER->id); - if (plan_helper::get_owner($oldplanid) == $userid) { + if (plan_helper::get_owner($oldplanid) === $USER->id) { foreach (plan_helper::get_plan_members($oldplanid) as $member) { - if ($member->userid != $userid) { + if ($member->userid !== $USER->id) { plan_leave_plan::leave_plan($member->userid, $oldplanid); } } - self::call_external_function('local_lbplanner_plan_clear_plan', array ($userid, $oldplanid)); + self::call_external_function('local_lbplanner_plan_clear_plan', [$USER->id, $oldplanid]); - $DB->delete_records(plan_helper::TABLE, array('id' => $oldplanid)); + $DB->delete_records(plan_helper::TABLE, ['id' => $oldplanid]); } $planaccess = $DB->get_record( plan_helper::ACCESS_TABLE, - array( + [ 'planid' => $oldplanid, - 'userid' => $userid - ), + 'userid' => $USER->id, + ], '*', MUST_EXIST ); @@ -110,27 +106,27 @@ public static function update_invite($planid, $userid, $status) { $DB->update_record(plan_helper::ACCESS_TABLE, $planaccess); - $DB->delete_records(plan_helper::INVITES_TABLE, array('id' => $invite->id)); + $DB->delete_records(plan_helper::INVITES_TABLE, ['id' => $invite->id]); } - return array( + return [ 'inviterid' => $invite->inviterid, 'inviteeid' => $invite->inviteeid, 'planid' => $invite->planid, 'status' => $invite->status, 'timestamp' => $invite->timestamp, - ); + ]; } public static function update_invite_returns() { return new external_single_structure( - array( + [ 'inviterid' => new external_value(PARAM_INT, 'The id of the owner user'), 'inviteeid' => new external_value(PARAM_INT, 'The id of the invited user'), 'planid' => new external_value(PARAM_INT, 'The id of the plan'), 'status' => new external_value(PARAM_INT, 'The Status of the invitation'), 'timestamp' => new external_value(PARAM_INT, 'The time when the invitation was send'), - ) + ] ); } } diff --git a/lbplanner/services/plan/update_plan.php b/lbplanner/services/plan/update_plan.php index ade69cc5..5be31118 100644 --- a/lbplanner/services/plan/update_plan.php +++ b/lbplanner/services/plan/update_plan.php @@ -20,28 +20,13 @@ use external_function_parameters; use external_value; use local_lbplanner\helpers\plan_helper; -use local_lbplanner\helpers\user_helper; /** * Update the plan of the given user. */ class plan_update_plan extends external_api { public static function update_plan_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value( - PARAM_INT, - 'The id of the user to get the data for', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - 'planid' => new external_value( - PARAM_INT, - 'The id of the plan', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), + return new external_function_parameters([ 'planname' => new external_value( PARAM_TEXT, 'The Name of the Plan', @@ -56,26 +41,24 @@ public static function update_plan_parameters() { null, NULL_NOT_ALLOWED ), - )); + ]); } - public static function update_plan($userid, $planid, $planname, $enableek) { - global $DB; + public static function update_plan($planname, $enableek) { + global $DB, $USER; self::validate_parameters( self::update_plan_parameters(), - array('userid' => $userid, 'planid' => $planid, 'planname' => $planname, 'enableek' => $enableek) + ['planname' => $planname, 'enableek' => $enableek] ); - user_helper::assert_access($userid); + $planid = plan_helper::get_plan_id($USER->id); - if (!plan_helper::check_edit_permissions($planid, $userid)) { + if (!plan_helper::check_edit_permissions($planid, $USER->id)) { throw new \Exception('Access denied'); } - $planid = plan_helper::get_plan_id($userid); - - $plan = $DB->get_record(plan_helper::TABLE, array('id' => $planid), '*', MUST_EXIST); + $plan = $DB->get_record(plan_helper::TABLE, ['id' => $planid], '*', MUST_EXIST); $plan->name = $planname; $plan->enableek = $enableek; From 0ac1ff867400787495826fefe7863f5429622752 Mon Sep 17 00:00:00 2001 From: Riedler's Sockpuppet <150551914+Riedlers-sockpuppet@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:05:33 +0100 Subject: [PATCH 12/92] LP-191 cleanup api returns (#56) * reduced API return bloat: feedback service * reduced API return bloat: notifications service * reduced API return bloat: invite subservice * reduced API return bloat: deadline subservice * reduced API return bloat: plan service * added invite helper - almost forgot. oops! * removed return from leave_plan * removed return from update_invite * deleted unused service endpoints --------- Co-authored-by: RiedleroD --- lbplanner/classes/helpers/invite_helper.php | 39 ++++++ .../classes/helpers/notifications_helper.php | 21 +++ lbplanner/classes/helpers/plan_helper.php | 6 +- .../services/feedback/delete_feedback.php | 6 +- lbplanner/services/feedback/get_feedback.php | 54 ------- .../services/feedback/submit_feedback.php | 5 +- .../services/feedback/update_feedback.php | 4 +- .../notifications/get_all_notifications.php | 14 +- .../notifications/update_notification.php | 23 +-- lbplanner/services/plan/accept_invite.php | 21 +-- lbplanner/services/plan/add_deadline.php | 6 +- lbplanner/services/plan/clear_plan.php | 4 +- lbplanner/services/plan/decline_invite.php | 21 +-- lbplanner/services/plan/delete_deadline.php | 4 +- lbplanner/services/plan/get_invites.php | 14 +- lbplanner/services/plan/invite_user.php | 22 +-- lbplanner/services/plan/leave_plan.php | 4 +- lbplanner/services/plan/remove_user.php | 4 +- lbplanner/services/plan/update_access.php | 4 +- lbplanner/services/plan/update_deadline.php | 5 +- lbplanner/services/plan/update_invite.php | 132 ------------------ lbplanner/services/plan/update_plan.php | 4 +- 22 files changed, 86 insertions(+), 331 deletions(-) create mode 100644 lbplanner/classes/helpers/invite_helper.php delete mode 100644 lbplanner/services/feedback/get_feedback.php delete mode 100644 lbplanner/services/plan/update_invite.php diff --git a/lbplanner/classes/helpers/invite_helper.php b/lbplanner/classes/helpers/invite_helper.php new file mode 100644 index 00000000..091f6adc --- /dev/null +++ b/lbplanner/classes/helpers/invite_helper.php @@ -0,0 +1,39 @@ +. + +namespace local_lbplanner\helpers; + +use external_single_structure; +use external_value; + +class invite_helper { + + /** + * @return external_single_structure The data structure of an invite. + */ + public static function structure() : external_single_structure { + return new external_single_structure( + [ + 'id' => new external_value(PARAM_INT, 'The id of the invite'), + 'inviterid' => new external_value(PARAM_INT, 'The id of the owner user'), + 'inviteeid' => new external_value(PARAM_INT, 'The id of the invited user'), + 'planid' => new external_value(PARAM_INT, 'The id of the plan'), + 'status' => new external_value(PARAM_INT, 'The Status of the invitation'), + 'timestamp' => new external_value(PARAM_INT, 'The time when the invitation was send'), + ] + ); + } +} \ No newline at end of file diff --git a/lbplanner/classes/helpers/notifications_helper.php b/lbplanner/classes/helpers/notifications_helper.php index f7a40964..a12cb2a4 100644 --- a/lbplanner/classes/helpers/notifications_helper.php +++ b/lbplanner/classes/helpers/notifications_helper.php @@ -16,6 +16,9 @@ namespace local_lbplanner\helpers; +use external_single_structure; +use external_value; + /** * Provides helper methods for notification related stuff. */ @@ -65,6 +68,24 @@ class notifications_helper { */ const TRIGGER_USER_REGISTERED = 5; + /** + * @return external_single_structure The data structure of a module. + */ + public static function structure() : external_single_structure { + return new external_single_structure( + array( + 'moduleid' => new external_value(PARAM_INT, 'The id of the module'), + 'name' => new external_value(PARAM_TEXT, 'The name of the module'), + 'courseid' => new external_value(PARAM_INT, 'The id of the course'), + 'status' => new external_value(PARAM_INT, 'The status of the module'), + 'type' => new external_value(PARAM_INT, 'The type of the module'), + 'url' => new external_value(PARAM_TEXT, 'The url of the module in moodle'), + 'grade' => new external_value(PARAM_INT, 'The grade of the module'), + 'deadline' => new external_value(PARAM_INT, 'The deadline of the module set by the teacher'), + ) + ); + } + /** * Notifies the given user about the given event, with the given info. * diff --git a/lbplanner/classes/helpers/plan_helper.php b/lbplanner/classes/helpers/plan_helper.php index d6c0cefd..76f6bdae 100644 --- a/lbplanner/classes/helpers/plan_helper.php +++ b/lbplanner/classes/helpers/plan_helper.php @@ -269,9 +269,9 @@ public static function copy_plan(int $planid, int $userid) : int { * @param integer $planid the plan id. * @param integer $userid the user id. * @param integer $removeuserid the user id to remove. - * @return array An array containing the new id of the plan + * @return int The ID of the new plan for the removed user */ - public static function remove_user(int $planid, int $userid, int $removeuserid) : array { + public static function remove_user(int $planid, int $userid, int $removeuserid) : int { global $DB; if (self::get_owner($planid) != $userid) { throw new \moodle_exception('Access denied'); @@ -301,7 +301,7 @@ public static function remove_user(int $planid, int $userid, int $removeuserid) $DB->update_record(self::ACCESS_TABLE, $oldaccess); - return self::get_plan($planid, $removeuserid); + return $newplanid; } public static function get_invites_send(int $userid):array { global $DB; diff --git a/lbplanner/services/feedback/delete_feedback.php b/lbplanner/services/feedback/delete_feedback.php index 55319811..49898fde 100644 --- a/lbplanner/services/feedback/delete_feedback.php +++ b/lbplanner/services/feedback/delete_feedback.php @@ -47,13 +47,9 @@ public static function delete_feedback($feedbackid) { feedback_helper::assert_admin_access(); $DB->delete_records(feedback_helper::LBPLANNER_FEEDBACK_TABLE, ['id' => $feedbackid]); - - return feedback_helper::get_all_feedbacks($USER->id); } public static function delete_feedback_returns() { - return new external_multiple_structure( - feedback_helper::structure(), - ); + return null; } } diff --git a/lbplanner/services/feedback/get_feedback.php b/lbplanner/services/feedback/get_feedback.php deleted file mode 100644 index 7b9700ba..00000000 --- a/lbplanner/services/feedback/get_feedback.php +++ /dev/null @@ -1,54 +0,0 @@ -. - -namespace local_lbplanner_services; - -use external_api; -use external_function_parameters; -use external_value; -use local_lbplanner\helpers\feedback_helper; - -/** - * Get feedback from the database. - */ -class feedback_get_feedback extends external_api { - public static function get_feedback_parameters() { - return new external_function_parameters([ - 'feedbackid' => new external_value(PARAM_INT, 'The id of the course', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - ]); - } - - public static function get_feedback($feedbackid) { - global $DB; - - self::validate_parameters( - self::get_feedback_parameters(), - ['feedbackid' => $feedbackid] - ); - - feedback_helper::assert_admin_access(); - - if (!$DB->record_exists(feedback_helper::LBPLANNER_FEEDBACK_TABLE, ['id' => $feedbackid])) { - throw new \moodle_exception('feedback_not_found'); - } - - return feedback_helper::get_feedback($feedbackid); - } - - public static function get_feedback_returns() { - return feedback_helper::structure(); - } -} diff --git a/lbplanner/services/feedback/submit_feedback.php b/lbplanner/services/feedback/submit_feedback.php index 6c9e36bd..fb40ca97 100644 --- a/lbplanner/services/feedback/submit_feedback.php +++ b/lbplanner/services/feedback/submit_feedback.php @@ -18,7 +18,6 @@ use external_api; use external_function_parameters; -use external_single_structure; use external_value; use local_lbplanner\helpers\feedback_helper; @@ -53,10 +52,10 @@ public static function submit_feedback($type, $content, $logfile) { 'logfile' => $logfile, ]); - return feedback_helper::get_feedback($id); + return $id; } public static function submit_feedback_returns() { - return feedback_helper::structure(); + return new external_value(PARAM_INT, "The ID of the new feedback"); } } diff --git a/lbplanner/services/feedback/update_feedback.php b/lbplanner/services/feedback/update_feedback.php index ca0c84a5..81221a5a 100644 --- a/lbplanner/services/feedback/update_feedback.php +++ b/lbplanner/services/feedback/update_feedback.php @@ -58,11 +58,9 @@ public static function update_feedback($feedbackid, $notes, $status) { $feedback->lastmodifiedby = $USER->id; $DB->update_record(feedback_helper::LBPLANNER_FEEDBACK_TABLE, $feedback); - - return $feedback; } public static function update_feedback_returns() { - return feedback_helper::structure(); + return null; } } diff --git a/lbplanner/services/notifications/get_all_notifications.php b/lbplanner/services/notifications/get_all_notifications.php index 24e8dc52..7ac3085c 100644 --- a/lbplanner/services/notifications/get_all_notifications.php +++ b/lbplanner/services/notifications/get_all_notifications.php @@ -19,8 +19,6 @@ use external_api; use external_function_parameters; use external_multiple_structure; -use external_single_structure; -use external_value; use local_lbplanner\helpers\notifications_helper; /** @@ -54,17 +52,7 @@ public static function get_all_notifications() { public static function get_all_notifications_returns() { return new external_multiple_structure( - new external_single_structure( - [ - 'status' => new external_value(PARAM_INT, 'The status of the notification {0: unread, 1: read}'), - 'type' => new external_value(PARAM_INT, 'The type of the event that triggered the notification'), - 'info' => new external_value(PARAM_INT, 'Additional information about the notification'), - 'userid' => new external_value(PARAM_INT, 'The ID of the user for whom the notification is for'), - 'notificationid' => new external_value(PARAM_INT, 'The ID of the notification', NULL_NOT_ALLOWED), - 'timestamp' => new external_value(PARAM_INT, 'The timestamp of the notification'), - 'timestamp_read' => new external_value(PARAM_INT, 'The timestamp of the notification when it was read'), - ] - ) + notifications_helper::structure() ); } } diff --git a/lbplanner/services/notifications/update_notification.php b/lbplanner/services/notifications/update_notification.php index b005320e..34db9751 100644 --- a/lbplanner/services/notifications/update_notification.php +++ b/lbplanner/services/notifications/update_notification.php @@ -18,7 +18,6 @@ use external_api; use external_function_parameters; -use external_single_structure; use external_value; use local_lbplanner\helpers\notifications_helper; @@ -56,29 +55,9 @@ public static function update_notification($status, $notificationid) { $notification->timestamp_read = time(); $DB->update_record(notifications_helper::TABLE, $notification); - - return [ - 'status' => $notification->status, - 'type' => $notification->type, - 'info' => $notification->info, - 'userid' => $notification->userid, - 'notificationid' => $notification->id, - 'timestamp' => $notification->timestamp, - 'timestamp_read' => $notification->timestamp_read, - ]; } public static function update_notification_returns() { - return new external_single_structure( - [ - 'status' => new external_value(PARAM_INT, 'The status of the notification {0: unread, 1: read}'), - 'type' => new external_value(PARAM_INT, 'The type of the event that triggered the notification'), - 'info' => new external_value(PARAM_INT, 'Additional information about the notification'), - 'userid' => new external_value(PARAM_INT, 'The ID of the user for whom the notification is for'), - 'notificationid' => new external_value(PARAM_INT, 'The ID of the notification'), - 'timestamp' => new external_value(PARAM_INT, 'The timestamp of the notification'), - 'timestamp_read' => new external_value(PARAM_INT, 'The timestamp of the notification'), - ] - ); + return null; } } diff --git a/lbplanner/services/plan/accept_invite.php b/lbplanner/services/plan/accept_invite.php index 4d8ba271..ad0e5242 100644 --- a/lbplanner/services/plan/accept_invite.php +++ b/lbplanner/services/plan/accept_invite.php @@ -18,7 +18,6 @@ use external_api; use external_function_parameters; -use external_single_structure; use external_value; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; @@ -111,28 +110,10 @@ public static function accept_invite($inviteid) { $DB->update_record(plan_helper::INVITES_TABLE, $invite); } } - - return [ - 'id' => $invite->id, - 'inviterid' => $invite->inviterid, - 'inviteeid' => $invite->inviteeid, - 'planid' => $invite->planid, - 'status' => $invite->status, - 'timestamp' => $invite->timestamp, - ]; } public static function accept_invite_returns() { - return new external_single_structure( - [ - 'id' => new external_value(PARAM_INT, 'The id of the invite'), - 'inviterid' => new external_value(PARAM_INT, 'The id of the owner user'), - 'inviteeid' => new external_value(PARAM_INT, 'The id of the invited user'), - 'planid' => new external_value(PARAM_INT, 'The id of the plan'), - 'status' => new external_value(PARAM_INT, 'The Status of the invitation'), - 'timestamp' => new external_value(PARAM_INT, 'The time when the invitation was send'), - ] - ); + return null; } } diff --git a/lbplanner/services/plan/add_deadline.php b/lbplanner/services/plan/add_deadline.php index 27591b73..8f553c35 100644 --- a/lbplanner/services/plan/add_deadline.php +++ b/lbplanner/services/plan/add_deadline.php @@ -80,12 +80,10 @@ public static function add_deadline($moduleid, $deadlinestart, $deadlineend) { $deadline->deadlinestart = $deadlinestart; $deadline->deadlineend = $deadlineend; - $DB->insert_record(plan_helper::DEADLINES_TABLE, $deadline); - - return plan_helper::get_plan($planid); + return $DB->insert_record(plan_helper::DEADLINES_TABLE, $deadline); } public static function add_deadline_returns() { - return plan_helper::plan_structure(); + return new external_value(PARAM_INT,"The ID of the newly added deadline"); } } diff --git a/lbplanner/services/plan/clear_plan.php b/lbplanner/services/plan/clear_plan.php index 9bbe49c4..e1dc5df5 100644 --- a/lbplanner/services/plan/clear_plan.php +++ b/lbplanner/services/plan/clear_plan.php @@ -38,11 +38,9 @@ public static function clear_plan() { } $DB->delete_records(plan_helper::DEADLINES_TABLE, ['planid' => $planid ]); - - return plan_helper::get_plan($planid); } public static function clear_plan_returns() { - return plan_helper::plan_structure(); + return null; } } diff --git a/lbplanner/services/plan/decline_invite.php b/lbplanner/services/plan/decline_invite.php index e7cf14df..e05bfffc 100644 --- a/lbplanner/services/plan/decline_invite.php +++ b/lbplanner/services/plan/decline_invite.php @@ -18,7 +18,6 @@ use external_api; use external_function_parameters; -use external_single_structure; use external_value; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; @@ -68,28 +67,10 @@ public static function decline_invite($inviteid) { $invite->status = PLAN_INVITE_STATE::DECLINED->value; $DB->update_record(plan_helper::INVITES_TABLE, $invite); - - return [ - 'id' => $invite->id, - 'inviterid' => $invite->inviterid, - 'inviteeid' => $invite->inviteeid, - 'planid' => $invite->planid, - 'status' => $invite->status, - 'timestamp' => $invite->timestamp, - ]; } public static function decline_invite_returns() { - return new external_single_structure( - [ - 'id' => new external_value(PARAM_INT, 'The id of the invite'), - 'inviterid' => new external_value(PARAM_INT, 'The id of the owner user'), - 'inviteeid' => new external_value(PARAM_INT, 'The id of the invited user'), - 'planid' => new external_value(PARAM_INT, 'The id of the plan'), - 'status' => new external_value(PARAM_INT, 'The Status of the invitation'), - 'timestamp' => new external_value(PARAM_INT, 'The time when the invitation was send'), - ] - ); + return null; } } diff --git a/lbplanner/services/plan/delete_deadline.php b/lbplanner/services/plan/delete_deadline.php index e4898ffc..3c6e995d 100644 --- a/lbplanner/services/plan/delete_deadline.php +++ b/lbplanner/services/plan/delete_deadline.php @@ -60,11 +60,9 @@ public static function delete_deadline($moduleid) { 'moduleid' => $moduleid, ] ); - - return plan_helper::get_plan($planid); } public static function delete_deadline_returns() { - return plan_helper::plan_structure(); + return null; } } diff --git a/lbplanner/services/plan/get_invites.php b/lbplanner/services/plan/get_invites.php index 8afac08d..7cbbcf72 100644 --- a/lbplanner/services/plan/get_invites.php +++ b/lbplanner/services/plan/get_invites.php @@ -18,9 +18,8 @@ use external_api; use external_function_parameters; -use external_single_structure; use external_multiple_structure; -use external_value; +use local_lbplanner\helpers\invite_helper; use local_lbplanner\helpers\plan_helper; /** @@ -66,16 +65,7 @@ public static function get_invites() { public static function get_invites_returns() { return new external_multiple_structure( - new external_single_structure( - [ - 'id' => new external_value(PARAM_INT, 'The id of the invite'), - 'inviterid' => new external_value(PARAM_INT, 'The id of the owner user'), - 'inviteeid' => new external_value(PARAM_INT, 'The id of the invited user'), - 'planid' => new external_value(PARAM_INT, 'The id of the plan'), - 'status' => new external_value(PARAM_INT, 'The Status of the invitation'), - 'timestamp' => new external_value(PARAM_INT, 'The time when the invitation was send'), - ] - ) + invite_helper::structure() ); } } diff --git a/lbplanner/services/plan/invite_user.php b/lbplanner/services/plan/invite_user.php index d2a428fd..4c4a497c 100644 --- a/lbplanner/services/plan/invite_user.php +++ b/lbplanner/services/plan/invite_user.php @@ -18,8 +18,8 @@ use external_api; use external_function_parameters; -use external_single_structure; use external_value; +use local_lbplanner\helpers\invite_helper; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; use local_lbplanner\helpers\PLAN_INVITE_STATE; @@ -86,26 +86,10 @@ public static function invite_user($inviteeid) { notifications_helper::TRIGGER_INVITE ); - return [ - 'id' => $invite->id, - 'inviterid' => $USER->id, - 'inviteeid' => $inviteeid, - 'planid' => $planid, - 'timestamp' => $invite->timestamp, - 'status' => $invite->status, - ]; + return $invite; } public static function invite_user_returns() { - return new external_single_structure( - [ - 'id' => new external_value(PARAM_INT, 'The id of the invite'), - 'inviterid' => new external_value(PARAM_INT, 'The id of the owner user'), - 'inviteeid' => new external_value(PARAM_INT, 'The id of the invited user'), - 'planid' => new external_value(PARAM_INT, 'The id of the plan'), - 'status' => new external_value(PARAM_INT, 'The status of the invitation'), - 'timestamp' => new external_value(PARAM_INT, 'The time when the invitation was send'), - ] - ); + return invite_helper::structure(); } } diff --git a/lbplanner/services/plan/leave_plan.php b/lbplanner/services/plan/leave_plan.php index 4545cfb0..5e2131d9 100644 --- a/lbplanner/services/plan/leave_plan.php +++ b/lbplanner/services/plan/leave_plan.php @@ -98,10 +98,8 @@ public static function leave_plan() { $USER->id, notifications_helper::TRIGGER_PLAN_LEFT ); - - return plan_helper::get_plan($planid, $USER->id); } public static function leave_plan_returns() { - return plan_helper::plan_structure(); + return null; } } diff --git a/lbplanner/services/plan/remove_user.php b/lbplanner/services/plan/remove_user.php index b323997c..4129e6b0 100644 --- a/lbplanner/services/plan/remove_user.php +++ b/lbplanner/services/plan/remove_user.php @@ -41,10 +41,10 @@ public static function remove_user($userid, $planid) { $planid = plan_helper::get_plan_id($USER->id); - return plan_helper::remove_user($planid, $USER->id, $userid); + plan_helper::remove_user($planid, $USER->id, $userid); } public static function remove_user_returns() { - return plan_helper::plan_structure(); + return null; } } diff --git a/lbplanner/services/plan/update_access.php b/lbplanner/services/plan/update_access.php index 2c8fe036..33c2b814 100644 --- a/lbplanner/services/plan/update_access.php +++ b/lbplanner/services/plan/update_access.php @@ -81,11 +81,9 @@ public static function update_access($accesstype, $memberid) { $access->accesstype = $accesstype; $DB->update_record(plan_helper::ACCESS_TABLE, $access); - - return plan_helper::get_plan($planid); } public static function update_access_returns() { - return plan_helper::plan_structure(); + return null; } } diff --git a/lbplanner/services/plan/update_deadline.php b/lbplanner/services/plan/update_deadline.php index 298bb829..43fdcff9 100644 --- a/lbplanner/services/plan/update_deadline.php +++ b/lbplanner/services/plan/update_deadline.php @@ -78,12 +78,9 @@ public static function update_deadline($moduleid, $deadlinestart, $deadlineend) $deadline->deadlineend = $deadlineend; $DB->update_record(plan_helper::DEADLINES_TABLE, $deadline); - - return plan_helper::get_plan($planid); - } public static function update_deadline_returns() { - return plan_helper::plan_structure(); + return null; } } diff --git a/lbplanner/services/plan/update_invite.php b/lbplanner/services/plan/update_invite.php deleted file mode 100644 index 2acbdf55..00000000 --- a/lbplanner/services/plan/update_invite.php +++ /dev/null @@ -1,132 +0,0 @@ -. - -namespace local_lbplanner_services; - -use external_api; -use external_function_parameters; -use external_single_structure; -use external_value; -use local_lbplanner\helpers\plan_helper; -use local_lbplanner\helpers\notifications_helper; -use local_lbplanner\helpers\PLAN_ACCESS_TYPE; -use local_lbplanner\helpers\PLAN_INVITE_STATE; - -/** - * THIS METHOD IS NOT USED ANYMORE. JUST TO KEEP OLD CODE FOR REFERENCE. - * TODO: delete - */ -class plan_update_invite extends external_api { - public static function update_invite_parameters() { - return new external_function_parameters([ - 'planid' => new external_value(PARAM_INT, 'The id of the plan', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'status' => new external_value(PARAM_INT, 'The status of the invite', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - ]); - } - - public static function update_invite($planid, $status) { - global $DB, $USER; - - self::validate_parameters(self::update_invite_parameters(), [ - 'planid' => $planid, - 'status' => $status, - ]); - - $statusobj = PLAN_INVITE_STATE::tryFrom($status); - - if ($statusobj === null) { - throw new \moodle_exception('Invalid status'); - } - - $invite = $DB->get_record(plan_helper::INVITES_TABLE, - [ - 'planid' => $planid, - 'inviteeid' => $USER->id, - ], - '*', - MUST_EXIST - ); - - if ($invite->status != PLAN_INVITE_STATE::PENDING->value) { - throw new \moodle_exception('Can\'t update non-pending status'); - } - - $invite->status = $status; - - $DB->update_record(plan_helper::INVITES_TABLE, $invite); - - $trigger = $statusobj === PLAN_INVITE_STATE::ACCEPTED ? - notifications_helper::TRIGGER_INVITE_ACCEPTED - : notifications_helper::TRIGGER_INVITE_DECLINED; - - notifications_helper::notify_user($invite->inviterid, $USER->id , $trigger); - - // TODO: Change plan access and delete old plan if inivite is accepted. - - if ($statusobj == PLAN_INVITE_STATE::ACCEPTED) { - $oldplanid = plan_helper::get_plan_id($USER->id); - - if (plan_helper::get_owner($oldplanid) === $USER->id) { - - foreach (plan_helper::get_plan_members($oldplanid) as $member) { - if ($member->userid !== $USER->id) { - plan_leave_plan::leave_plan($member->userid, $oldplanid); - } - } - self::call_external_function('local_lbplanner_plan_clear_plan', [$USER->id, $oldplanid]); - - $DB->delete_records(plan_helper::TABLE, ['id' => $oldplanid]); - } - - $planaccess = $DB->get_record( - plan_helper::ACCESS_TABLE, - [ - 'planid' => $oldplanid, - 'userid' => $USER->id, - ], - '*', - MUST_EXIST - ); - - $planaccess->accesstype = PLAN_ACCESS_TYPE::READ->value; - $planaccess->planid = $planid; - - $DB->update_record(plan_helper::ACCESS_TABLE, $planaccess); - - $DB->delete_records(plan_helper::INVITES_TABLE, ['id' => $invite->id]); - } - return [ - 'inviterid' => $invite->inviterid, - 'inviteeid' => $invite->inviteeid, - 'planid' => $invite->planid, - 'status' => $invite->status, - 'timestamp' => $invite->timestamp, - ]; - } - - - public static function update_invite_returns() { - return new external_single_structure( - [ - 'inviterid' => new external_value(PARAM_INT, 'The id of the owner user'), - 'inviteeid' => new external_value(PARAM_INT, 'The id of the invited user'), - 'planid' => new external_value(PARAM_INT, 'The id of the plan'), - 'status' => new external_value(PARAM_INT, 'The Status of the invitation'), - 'timestamp' => new external_value(PARAM_INT, 'The time when the invitation was send'), - ] - ); - } -} diff --git a/lbplanner/services/plan/update_plan.php b/lbplanner/services/plan/update_plan.php index 5be31118..a2937f90 100644 --- a/lbplanner/services/plan/update_plan.php +++ b/lbplanner/services/plan/update_plan.php @@ -63,11 +63,9 @@ public static function update_plan($planname, $enableek) { $plan->enableek = $enableek; $DB->update_record(plan_helper::TABLE, $plan); - - return plan_helper::get_plan($planid); } public static function update_plan_returns() { - return plan_helper::plan_structure(); + return null; } } From 2621879e6cd0eff807de34b009cf424fc90321cd Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 20 Nov 2023 14:55:47 +0100 Subject: [PATCH 13/92] re-add moodle CI action (#59) * added Gh actions * biete hilfe * 147 rat auf draht * nur maria * adjustments to workflow stolen from 3dc3f0510936bdacd22421701b95462c15452340, which is a tainted commit, as per usual. * untaint commit see b3968f83dda3f5d8d2de1194eb38904c6b307b24 * changed CI php version to 7.4, which is the same as in prod * renamed action to just "CI" * removed 8.1 from action php versions --------- Co-authored-by: Muhi --- .github/workflows/gha.dist.yml | 114 +++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 .github/workflows/gha.dist.yml diff --git a/.github/workflows/gha.dist.yml b/.github/workflows/gha.dist.yml new file mode 100644 index 00000000..f8913737 --- /dev/null +++ b/.github/workflows/gha.dist.yml @@ -0,0 +1,114 @@ +name: CI + +on: + pull_request: + types: + - opened + - synchronize + branches: + - LP-55-Backend-Refactor # Temporary. Will be changed to `moodle` when refactor is complete + +jobs: + Analysis: + runs-on: ubuntu-22.04 + + services: + postgres: + image: postgres:13 + env: + POSTGRES_USER: 'postgres' + POSTGRES_HOST_AUTH_METHOD: 'trust' + ports: + - 5432:5432 + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 + + mariadb: + image: mariadb:10 + env: + MYSQL_USER: 'root' + MYSQL_ALLOW_EMPTY_PASSWORD: "true" + MYSQL_CHARACTER_SET_SERVER: "utf8mb4" + MYSQL_COLLATION_SERVER: "utf8mb4_unicode_ci" + ports: + - 3306:3306 + options: --health-cmd="mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 3 + + strategy: + fail-fast: false + matrix: + php: ['7.4'] + moodle-branch: ['MOODLE_401_STABLE'] + database: [mariadb] + + steps: + - name: Check out repository code + uses: actions/checkout@v3 + with: + path: plugin + + - name: Setup PHP ${{ matrix.php }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: ${{ matrix.extensions }} + ini-values: max_input_vars=5000 + # If you are not using code coverage, keep "none". Otherwise, use "pcov" (Moodle 3.10 and up) or "xdebug". + # If you try to use code coverage with "none", it will fallback to phpdbg (which has known problems). + coverage: none + + - name: Initialise moodle-plugin-ci + run: | + composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^4 + echo $(cd ci/bin; pwd) >> $GITHUB_PATH + echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH + sudo locale-gen en_AU.UTF-8 + echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV + + - name: Install moodle-plugin-ci + run: | + moodle-plugin-ci install --plugin ./plugin/lbplanner --db-host=127.0.0.1 + env: + DB: ${{ matrix.database }} + MOODLE_BRANCH: ${{ matrix.moodle-branch }} + + - name: PHP Lint + if: ${{ always() }} + run: moodle-plugin-ci phplint + + - name: PHP Copy/Paste Detector + continue-on-error: true # This step will show errors but will not fail + if: ${{ always() }} + run: moodle-plugin-ci phpcpd + + - name: PHP Mess Detector + continue-on-error: true # This step will show errors but will not fail + if: ${{ always() }} + run: moodle-plugin-ci phpmd + + - name: Moodle Code Checker + if: ${{ always() }} + run: moodle-plugin-ci phpcs --max-warnings 0 + + - name: Moodle PHPDoc Checker + if: ${{ always() }} + run: moodle-plugin-ci phpdoc --max-warnings 0 + + - name: Validating + if: ${{ always() }} + run: moodle-plugin-ci validate + + - name: Check upgrade savepoints + if: ${{ always() }} + run: moodle-plugin-ci savepoints + + - name: Mustache Lint + if: ${{ always() }} + run: moodle-plugin-ci mustache + + - name: Grunt + if: ${{ always() }} + run: moodle-plugin-ci grunt --max-lint-warnings 0 + + - name: PHPUnit tests + if: ${{ always() }} + run: moodle-plugin-ci phpunit --fail-on-warning From 2f62cd6b41e7af0364980f53ea7943cc51c9c4a0 Mon Sep 17 00:00:00 2001 From: Muhi <49810240+mkocagoel@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:44:55 +0100 Subject: [PATCH 14/92] Lp 167 refactor db access for userinfo (#39) * added Gh actions * biete hilfe * 147 rat auf draht * nur maria * added a new way to retrieve user information including picture removed deprecated code from the user_helper get user now gets the userid from the global * reworked register_user.php added the profile picture string to user_helper * bugfixing and checking testcases * Added Return Types and better documentation * Reworking docs * Reworking docs and adding userid to deleteuser * Reworking docs and bugfixing * Reworking docs * Adding must-have docs * Checking Moodle PHPDoc Checker * Checking Moodle PHPDoc Checker fixing "Line 30: No one-line description" * changed array[] to array * Changed copyright from LB Planner to NecodeIT and package from local_lbplanner_services * Changed NecodeIT to necodeIT * Added MoodleDocs to comfort Moodle even more * comforting Moodle Docs and changing if statements to more readable ones. * comforting Moodle Docs interger to int * comforting Moodle Docs Adding comma to multiline comments --- .gitignore | 1 + .../classes/helpers/notifications_helper.php | 4 +- lbplanner/classes/helpers/user_helper.php | 113 +++++++-------- lbplanner/services/modules/get_module.php | 2 +- lbplanner/services/user/delete_user.php | 93 ++++++++----- lbplanner/services/user/get_all_users.php | 67 ++++++--- lbplanner/services/user/get_user.php | 129 +++++++++++------- lbplanner/services/user/register_user.php | 121 ++++++++++------ lbplanner/services/user/update_user.php | 124 ++++++++++------- 9 files changed, 391 insertions(+), 263 deletions(-) diff --git a/.gitignore b/.gitignore index f7c27e56..ebed54a9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ moodle *.zip lbplanner.dart/test/env.dart +example diff --git a/lbplanner/classes/helpers/notifications_helper.php b/lbplanner/classes/helpers/notifications_helper.php index a12cb2a4..82cd48c5 100644 --- a/lbplanner/classes/helpers/notifications_helper.php +++ b/lbplanner/classes/helpers/notifications_helper.php @@ -26,7 +26,7 @@ class notifications_helper { /** * Name of the notifications table. */ - const TABLE = 'local_lbplanner_notification'; + const LBPLANNER_NOTIFICATION_TABLE = 'local_lbplanner_notification'; /** * Enum value for a read notification. @@ -105,7 +105,7 @@ public static function notify_user( int $userid, int $info, int $type ): int { $notification->timestamp = time(); $notification->timestamp_read = null; - $id = $DB->insert_record(self::TABLE, $notification); + $id = $DB->insert_record(self::LBPLANNER_NOTIFICATION_TABLE, $notification); return $id; } diff --git a/lbplanner/classes/helpers/user_helper.php b/lbplanner/classes/helpers/user_helper.php index 01b2dee8..f8732397 100644 --- a/lbplanner/classes/helpers/user_helper.php +++ b/lbplanner/classes/helpers/user_helper.php @@ -16,15 +16,19 @@ namespace local_lbplanner\helpers; +use coding_exception; use context_system; -use moodle1_converter; -use moodle_database; -use moodle_url; -use moodleform; +use dml_exception; +use moodle_exception; use stdClass; +use user_picture; +use core_user; /** * Provides helper methods for user related stuff. + * @package local_lbplanner\helpers + * @copyright LB PLANNER + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class user_helper { @@ -55,26 +59,15 @@ class user_helper { self::CAPABILITY_ADMIN => 1, self::CAPABILITY_MANAGER => 2, self::CAPABILITY_TEACHER => 4, - self::CAPABILITY_STUDENT => 8 + self::CAPABILITY_STUDENT => 8, ]; /** * Name of the user database */ - const TABLE = 'local_lbplanner_users'; + const LB_PLANNER_USER_TABLE = 'local_lbplanner_users'; /** - * The table where moodle stores the user data. - */ - const MOODLE_TABLE = 'user'; - - /** - * The table where moodle stores the user context data. - */ - const MOODLE_CONTEXT_TABLE = 'context'; - - /** - * @deprecated Use user_helper::assert_access() instead * Checks if the current user has access to the given user id. * * @param int $userid The id of the user to check access for. @@ -85,51 +78,32 @@ public static function check_access(int $userid):bool { return $USER->id == $userid; } - /** - * Retrieves the user with the given id. - * ```php - * $mdluser->username // The username of the user. - * $mdluser->firstname // The firstname of the user. - * $mdluser->lastname // The lastname of the user. - * $mdluser->profileimageurl // The profile image url of the user. - * ``` - * - * @param integer $userid The id of the user to retrieve. - * @return stdClass The user with the given id. - */ - public static function get_mdl_user_info(int $userid):stdClass { - global $DB; - $user = $DB->get_record(self::MOODLE_TABLE, array('id' => $userid), '*', MUST_EXIST); - $contextid = $DB->get_record( - self::MOODLE_CONTEXT_TABLE, - array('depth' => 2, 'contextlevel' => 30, 'instanceid' => $userid), - '*', - IGNORE_MISSING - ); - $mdluser = new stdClass(); - $mdluser->username = $user->username; - $mdluser->firstname = $user->firstname; - $mdluser->lastname = $user->lastname; - $mdluser->profileimageurl = strval(moodle_url::make_pluginfile_url($contextid->id, 'user', 'icon', null, '/boost_union/', 'f1.png')); - $mdluser->vintage = $user->address; - - return $mdluser; - } - /** * Checks if the current user has access to the given user id. * Throws an exception if the current user does not have access. * * @param int $userid The id of the user to check access for. * @return void + * @throws moodle_exception */ - public static function assert_access(int $userid) { + public static function assert_access(int $userid): void { global $USER; if ($USER->id != $userid) { - throw new \moodle_exception('Access denied'); + throw new moodle_exception('Access denied'); } } + /** + * Checks if the given user is an admin. + * @param int $userid The id of the user to check. + * @return bool True if the given user is an admin, false otherwise. + * @throws coding_exception + * @throws dml_exception + */ + public static function is_admin(int $userid): bool { + $context = context_system::instance(); + return has_capability(self::CAPABILITY_ADMIN, $context, $userid, false); + } /** * Gives back a bitmask which represents the capabilities of the given user. * 0 = no capabilities @@ -152,9 +126,10 @@ public static function assert_access(int $userid) { * * @param int $userid The id of the user to check access for. * @return int The capabilities of the given user. + * @throws coding_exception + * @throws dml_exception */ public static function get_user_capability_bitmask(int $userid) : int { - global $DB; $capabilities = 0; $context = context_system::instance(); if (has_capability(self::CAPABILITY_ADMIN, $context, $userid, false)) { @@ -172,14 +147,15 @@ public static function get_user_capability_bitmask(int $userid) : int { return $capabilities; } /** - * Checks if the given user exists in the database. + * Checks if the given user exists in the LB_PLANNER_USER database. * - * @param integer $userid The id of the user to check. - * @return boolean True if the user exists, false otherwise. + * @param int $userid The id of the user to check. + * @return bool True if the user exists, false otherwise. + * @throws dml_exception */ public static function check_user_exists(int $userid): bool { global $DB; - return $DB->record_exists(self::TABLE, array('userid' => $userid)); + return $DB->record_exists(self::LB_PLANNER_USER_TABLE, ['userid' => $userid]); } /** @@ -192,24 +168,39 @@ public static function check_user_exists(int $userid): bool { * $user->language // The language the user has set for the app. * ``` * - * @param integer $userid The id of the user to retrieve. + * @param int $userid The id of the user to retrieve. * @return stdClass The user with the given id. + * @throws dml_exception */ public static function get_user(int $userid): stdClass { global $DB; - return $DB->get_record(self::TABLE, array('userid' => $userid), '*', MUST_EXIST); + return $DB->get_record(self::LB_PLANNER_USER_TABLE, ['userid' => $userid], '*', MUST_EXIST); } /** * Retrieves the full name of the user with the given id. + * @deprecated not in use * - * @param integer $userid The id of the user to retrieve the full name for. * @return string The full name of the user with the given id. */ - public static function get_complete_name(int $userid): string { - $user = self::get_mdl_user_info($userid); + public static function get_complete_name(): string { + global $USER; + return $USER->firstname . ' ' . $USER->lastname; + } - return $user->firstname . ' ' . $user->lastname; + /** + * This Function is used to get the user picture of a user. + * @param int $userid The id of the user to retrieve the picture for. + * @throws coding_exception + * @throws dml_exception + * @return string The url of the user picture. + */ + public static function get_mdl_user_picture(int $userid): string { + global $PAGE; + $mdluser = core_user::get_user($userid, '*', MUST_EXIST); + $userpicture = new user_picture($mdluser); + $userpicture->size = 1; // Size f1. + return $userpicture->get_url($PAGE)->out(false); } } diff --git a/lbplanner/services/modules/get_module.php b/lbplanner/services/modules/get_module.php index 4f66f036..d225e5f9 100644 --- a/lbplanner/services/modules/get_module.php +++ b/lbplanner/services/modules/get_module.php @@ -41,7 +41,7 @@ public static function get_module($moduleid, $userid) { user_helper::assert_access($userid); - if (!$DB->record_exists(modules_helper::ASSIGN_TABLE, array('id' => $moduleid))) { + if (!$DB->record_exists(modules_helper::MDL_ASSIGN_TABLE, array('id' => $moduleid))) { throw new \moodle_exception('Module not found'); } diff --git a/lbplanner/services/user/delete_user.php b/lbplanner/services/user/delete_user.php index aea7910c..29269912 100644 --- a/lbplanner/services/user/delete_user.php +++ b/lbplanner/services/user/delete_user.php @@ -16,7 +16,7 @@ namespace local_lbplanner_services; -use core_competency\plan; +use dml_exception; use external_api; use external_function_parameters; use external_single_structure; @@ -25,50 +25,69 @@ use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\course_helper; use local_lbplanner\helpers\notifications_helper; -use local_lbplanner\helpers\PLAN_ACCESS_TYPE; -use local_lbplanner\helpers\PLAN_INVITE_STATE; +use moodle_exception; /** - * Removes all user data stored by the lbplanner app + * Removes all user data stored by the lbplanner app. + * + * Admins can pass a userid to delete the user with the given id + * @package local_lbplanner + * @copyright 2023 necodeIT + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class user_delete_user extends external_api { - public static function delete_user_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value( + /** + * Parameters for delete_user + * @return external_function_parameters + */ + public static function delete_user_parameters(): external_function_parameters { + global $USER; + return new external_function_parameters( + ['userid' => new external_value( PARAM_INT, - 'The id of the user to get the data for', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - )); + 'The id of the user to delete', + VALUE_DEFAULT, + $USER->id, + NULL_NOT_ALLOWED, + )] + ); } + /** + * Removes all user data stored by the lbplanner app + * @param int $userid (optional) the id of the user to delete + * @throws dml_exception + * @throws moodle_exception + */ public static function delete_user($userid) { - global $DB; - self::validate_parameters(self::delete_user_parameters(), array('userid' => $userid)); + global $DB, $USER; + + self::validate_parameters(self::delete_user_parameters(), ['userid' => $userid]); - user_helper::assert_access($userid); + if (!user_helper::is_admin($USER->id)) { + user_helper::assert_access($userid); + } // Check if User is in user table. - if (!$DB->record_exists(user_helper::TABLE, array('userid' => $userid))) { - throw new \moodle_exception('Access denied'); + if (!$DB->record_exists(user_helper::LB_PLANNER_USER_TABLE, ['userid' => $userid])) { + throw new moodle_exception('User is not registered in LB Planner'); } $planid = plan_helper::get_plan_id($userid); - - if (plan_helper::get_access_type($planid, $userid) === PLAN_ACCESS_TYPE::OWNER) { - if (plan_helper::get_plan_members($planid) > 1) { - self::call_external_function('local_lbplanner_plan_leave_plan', array('userid' => $userid, 'planid' => $planid)); - } else { - // Deleting Plan. - $DB->delete_records(plan_helper::DEADLINES_TABLE, array('planid' => $planid)); - $DB->delete_records(plan_helper::TABLE, array('id' => $planid)); - } + // Check if User is in a plan. If yes, leave the plan first then delete the plan. + // If the user is the only member of the plan, delete the plan. + if ( + !(count(plan_helper::get_plan_members($planid)) == 1 ) + && + !(plan_helper::get_access_type($planid, $userid) == plan_helper::ACCESS_TYPE_OWNER)) { + self::call_external_function('local_lbplanner_plan_leave_plan', ['userid' => $userid, 'planid' => $planid]); } + $DB->delete_records(plan_helper::DEADLINES_TABLE, ['planid' => $planid]); + $DB->delete_records(plan_helper::TABLE, ['id' => $planid]); + // Delete all Notifications. - if ($DB->record_exists(notifications_helper::TABLE, array('userid' => $userid))) { - $DB->delete_records(notifications_helper::TABLE, array('userid' => $userid)); + if ($DB->record_exists(notifications_helper::LBPLANNER_NOTIFICATION_TABLE, ['userid' => $userid])) { + $DB->delete_records(notifications_helper::LBPLANNER_NOTIFICATION_TABLE, ['userid' => $userid]); } $invites = plan_helper::get_invites_send($userid); @@ -79,19 +98,19 @@ public static function delete_user($userid) { } } // Deleting associating with the plan. - $DB->delete_records(plan_helper::ACCESS_TABLE, array('userid' => $userid)); + $DB->delete_records(plan_helper::ACCESS_TABLE, ['userid' => $userid]); // Deleting all Courses associated with the User. - $DB->delete_records(course_helper::LBPLANNER_COURSE_TABLE, array('userid' => $userid)); + $DB->delete_records(course_helper::LBPLANNER_COURSE_TABLE, ['userid' => $userid]); // Deleting User from User table. - $DB->delete_records(user_helper::TABLE, array('userid' => $userid)); - - return array('message' => 'User deleted successfully'); + $DB->delete_records(user_helper::LB_PLANNER_USER_TABLE, ['userid' => $userid]); } + /** + * Returns the structure of the data returned by the delete_user function + * @return external_multiple_structure + */ public static function delete_user_returns() { - return new external_single_structure( - array('message' => new external_value(PARAM_TEXT, 'The message to return to the user')) - ); + return null; } } diff --git a/lbplanner/services/user/get_all_users.php b/lbplanner/services/user/get_all_users.php index 6308f87b..6fdd9a2a 100644 --- a/lbplanner/services/user/get_all_users.php +++ b/lbplanner/services/user/get_all_users.php @@ -16,62 +16,89 @@ namespace local_lbplanner_services; +use core_user; +use dml_exception; use external_api; use external_function_parameters; use external_multiple_structure; use external_single_structure; use external_value; +use invalid_parameter_exception; use local_lbplanner\helpers\user_helper; +use moodle_exception; /** * Gets all users registered by the lbplanner app. + * + * @package local_lbplanner + * @copyright 2023 necodeIT + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class user_get_all_users extends external_api { - public static function get_all_users_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value(PARAM_INT, 'The id of the user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - )); + /** + * Parameters for get_all_users + * @return external_function_parameters + */ + public static function get_all_users_parameters(): external_function_parameters { + return new external_function_parameters([ + 'vintage' => new external_value(PARAM_TEXT, 'The vintage to filter the users by', VALUE_DEFAULT, null), + ]); } - public static function get_all_users($userid) { - global $DB; + /** + * Gives back all users registered by the lbplanner app. + * @param string $vintage (optional) gives back all users with the given vintage + * @throws moodle_exception + * @throws dml_exception + * @throws invalid_parameter_exception + */ + public static function get_all_users(string $vintage): array { + global $DB, $USER; - self::validate_parameters(self::get_all_users_parameters(), array('userid' => $userid)); + self::validate_parameters(self::get_all_users_parameters(), ['vintage' => $vintage]); // Check if token is allowed to access this function. - user_helper::assert_access($userid); + user_helper::assert_access($USER->id); - $users = $DB->get_records(user_helper::TABLE); + $users = $DB->get_records(user_helper::LB_PLANNER_USER_TABLE); - $result = array(); + $result = []; foreach ($users as $user) { - $mdluser = user_helper::get_mdl_user_info($user->userid); - $result[] = array( + $mdluser = core_user::get_user($user->userid, '*', MUST_EXIST); + $result[] = [ 'userid' => $user->userid, 'username' => $mdluser->username, 'firstname' => $mdluser->firstname, 'lastname' => $mdluser->lastname, - 'profileimageurl' => $mdluser->profileimageurl, - 'vintage' => $mdluser->vintage, - ); + 'profileimageurl' => user_helper::get_mdl_user_picture($mdluser->id), + 'vintage' => $mdluser->address, + ]; + } + if ($vintage != null) { + $result = array_filter($result, function ($user) use ($vintage) { + return $user['vintage'] == $vintage; + }); } - return $result; } - public static function get_all_users_returns() { + /** + * Returns the structure of the data returned by the get_all_users function + * @return external_multiple_structure + */ + public static function get_all_users_returns(): external_multiple_structure { return new external_multiple_structure( new external_single_structure( - array( + [ 'userid' => new external_value(PARAM_INT, 'The id of the user'), 'username' => new external_value(PARAM_TEXT, 'The username of the user'), 'firstname' => new external_value(PARAM_TEXT, 'The firstname of the user'), 'lastname' => new external_value(PARAM_TEXT, 'The lastname of the user'), 'profileimageurl' => new external_value(PARAM_URL, 'The url of the profile image'), - 'vintage' => new external_value(PARAM_TEXT, 'The vintage of the user') - ) + 'vintage' => new external_value(PARAM_TEXT, 'The vintage of the user'), + ] ) ); } diff --git a/lbplanner/services/user/get_user.php b/lbplanner/services/user/get_user.php index d6737c02..4849810d 100644 --- a/lbplanner/services/user/get_user.php +++ b/lbplanner/services/user/get_user.php @@ -16,80 +16,105 @@ namespace local_lbplanner_services; -use block_recentlyaccesseditems\external; -use core_privacy\local\request\subsystem\plugin_provider; +use coding_exception; +use dml_exception; use external_api; use external_function_parameters; use external_single_structure; -use external_multiple_structure; use external_value; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\user_helper; +use core_user; +use moodle_exception; /** * Get the data for a user. + * + * Get the data for a user. param userid (optional) gives back the user data with the given ID + * @package local_lbplanner + * @copyright 2023 necodeIT + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class user_get_user extends external_api { - public static function get_user_parameters() { - return new external_function_parameters(array( + /** + * Parameters for get_user + * @return external_function_parameters + */ + public static function get_user_parameters(): external_function_parameters { + global $USER; + return new external_function_parameters([ 'userid' => new external_value( PARAM_INT, - 'The id of the user to get the data for', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED + 'The id of the user to get the data for. If not provided it will be inferred via the token', + VALUE_DEFAULT, + $USER->id, + NULL_NOT_ALLOWED, ), - )); + ]); } - public static function get_user($userid) { - global $USER; - self::validate_parameters(self::get_user_parameters(), array('userid' => $userid)); + /** + * Gives back the data of a user. + * Default: The user who calls this function + * @param int $userid (optional) gives back the data of the given user + * @throws coding_exception + * @throws dml_exception + * @throws moodle_exception + * @return array The data of the user + */ + public static function get_user(int $userid): array { + global $USER, $CFG; + include_once("$CFG->dirroot/user/lib.php"); + self::validate_parameters(self::get_user_parameters(), ['userid' => $userid]); + // Checks if the user is enrolled in LB Planner. if (!user_helper::check_user_exists($userid)) { - throw new \moodle_exception('User does not exist'); + throw new moodle_exception('User does not exist'); } - $user = user_helper::get_user($userid); - - $mdluser = user_helper::get_mdl_user_info($user->userid); - + $lbplanneruser = user_helper::get_user($userid); // Check if the user is allowed to get the data for this userid. - if ($userid == $USER->id) { - - return array( - 'userid' => $user->userid, - 'username' => $mdluser->username, - 'firstname' => $mdluser->firstname, - 'lastname' => $mdluser->lastname, + if (user_helper::check_access($userid)) { + $mdluser = (user_get_user_details($USER)); + return [ + 'userid' => $USER->id, + 'username' => $USER->username, + 'firstname' => $USER->firstname, + 'lastname' => $USER->lastname, 'capabilities' => user_helper::get_user_capability_bitmask($userid), - 'theme' => $user->theme, - 'lang' => $user->language, - 'profileimageurl' => $mdluser->profileimageurl, + 'theme' => $lbplanneruser->theme, + 'lang' => $lbplanneruser->language, + 'profileimageurl' => $mdluser['profileimageurl'], 'planid' => plan_helper::get_plan_id($userid), - 'colorblindness' => $user->colorblindness, - 'displaytaskcount' => $user->displaytaskcount, - 'vintage' => $mdluser->vintage, - ); + 'colorblindness' => $lbplanneruser->colorblindness, + 'displaytaskcount' => $lbplanneruser->displaytaskcount, + 'vintage' => $USER->address, + ]; + } else { + $mdluser = core_user::get_user($userid, '*', MUST_EXIST); + return [ + 'userid' => $mdluser->id, + 'username' => $mdluser->username, + 'firstname' => $mdluser->firstname, + 'lastname' => $mdluser->lastname, + 'capabilities' => null, + 'theme' => null, + 'lang' => null, + 'profileimageurl' => user_helper::get_mdl_user_picture($userid), + 'planid' => null, + 'colorblindness' => null, + 'displaytaskcount' => null, + 'vintage' => $mdluser->address, + ]; } - return array( - 'userid' => $user->userid, - 'username' => $user->username, - 'firstname' => $mdluser->firstname, - 'lastname' => $mdluser->lastname, - 'capabilities' => null, - 'theme' => null, - 'lang' => null, - 'profileimageurl' => $mdluser->profileimageurl, - 'planid' => null, - 'colorblindness' => null, - 'displaytaskcount' => null, - 'vintage' => $mdluser->vintage, - ); } - public static function get_user_returns() { + /** + * Returns the data of a user. + * @return external_single_structure + */ + public static function get_user_returns(): external_single_structure { return new external_single_structure( - array( + [ 'userid' => new external_value(PARAM_INT, 'The id of the user'), 'username' => new external_value(PARAM_TEXT, 'The username of the user'), 'firstname' => new external_value(PARAM_TEXT, 'The firstname of the user'), @@ -99,10 +124,10 @@ public static function get_user_returns() { 'profileimageurl' => new external_value(PARAM_URL, 'The url of the profile image'), 'planid' => new external_value(PARAM_INT, 'The id of the plan the user is assigned to'), 'colorblindness' => new external_value(PARAM_TEXT, 'The colorblindness of the user'), - 'displaytaskcount' => new external_value(PARAM_INT, 'The displaytaskcount of the user'), - 'capabilities' => new external_value(PARAM_INT, 'The capability'), - 'vintage' => new external_value(PARAM_TEXT, 'The vintage of the user') - ) + 'displaytaskcount' => new external_value(PARAM_INT, 'If the user has the taskcount-enabled 1-yes 0-no'), + 'capabilities' => new external_value(PARAM_INT, 'The capabilities of the user represented as a bitmask value'), + 'vintage' => new external_value(PARAM_TEXT, 'The vintage of the user'), + ] ); } } diff --git a/lbplanner/services/user/register_user.php b/lbplanner/services/user/register_user.php index 27203ac7..92d222e1 100644 --- a/lbplanner/services/user/register_user.php +++ b/lbplanner/services/user/register_user.php @@ -16,59 +16,95 @@ namespace local_lbplanner_services; +use dml_exception; use external_api; use external_function_parameters; use external_single_structure; use external_value; +use invalid_parameter_exception; +use local_lbplanner\helpers\PLAN_ACCESS_TYPE; +use local_lbplanner\helpers\PLAN_EK; use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; -use local_lbplanner\helpers\PLAN_ACCESS_TYPE; -use local_lbplanner\helpers\PLAN_EK; +use moodle_exception; +use stdClass; /** * Register a new user in the lbplanner app. + * + * @package local_lbplanner + * @copyright 2023 necodeIT + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class user_register_user extends external_api { - public static function register_user_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value(PARAM_INT, 'The id of the user to register', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'lang' => new external_value(PARAM_TEXT, 'The language the user has selected', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'theme' => new external_value(PARAM_TEXT, 'The theme the user has selected', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - )); + /** + * Parameters for register_user + * @return external_function_parameters + */ + public static function register_user_parameters(): external_function_parameters { + return new external_function_parameters([ + 'lang' => new external_value( + PARAM_TEXT, + 'The language the user has selected', + VALUE_DEFAULT, + 'en', + NULL_NOT_ALLOWED + ), + 'theme' => new external_value( + PARAM_TEXT, + 'The theme the user has selected', + VALUE_DEFAULT, + 'Light', + NULL_NOT_ALLOWED), + 'ekenabled' => new external_value( + PARAM_INT, + 'If the user wants to have EK-Enabled', + VALUE_DEFAULT, + 0, + NULL_NOT_ALLOWED, + ) + ]); } - public static function register_user($userid, $lang, $theme) { - global $DB; + /** + * Registers the given user to the lbplanner DB + * @param string $lang language the user choose + * @param string $theme The theme the user has selected + * @throws dml_exception + * @throws moodle_exception + * @throws invalid_parameter_exception + */ + public static function register_user(string $lang, string $theme): array { + global $DB, $USER; self::validate_parameters( self::register_user_parameters(), - array('userid' => $userid, 'lang' => $lang, 'theme' => $theme) + ['lang' => $lang, 'theme' => $theme] ); + $userid = $USER->id; user_helper::assert_access($userid); if (user_helper::check_user_exists($userid)) { - throw new \moodle_exception('User already registered'); + throw new moodle_exception('User already registered'); } - $user = new \stdClass(); - $user->userid = $userid; - $user->language = $lang; - $user->theme = $theme; - $user->colorblindness = "none"; + $lbplanneruser = new stdClass(); + $lbplanneruser->userid = $userid; + $lbplanneruser->language = $lang; + $lbplanneruser->theme = $theme; + $lbplanneruser->colorblindness = "none"; + $lbplanneruser->displaytaskcount = 1; - $DB->insert_record(user_helper::TABLE, $user); - - $mdluser = user_helper::get_mdl_user_info($userid); - - $plan = new \stdClass(); - $plan->name = 'Plan for ' . $mdluser->firstname; - $plan->enableek = PLAN_EK::DISABLED->value; + $DB->insert_record(user_helper::LB_PLANNER_USER_TABLE, $lbplanneruser); + $plan = new stdClass(); + $plan->name = 'Plan for ' . $USER->username; + $plan->enableek = plan_helper::EK_ENABLED; $planid = $DB->insert_record(plan_helper::TABLE, $plan); - $planaccess = new \stdClass(); + $planaccess = new stdClass(); $planaccess->userid = $userid; $planaccess->accesstype = PLAN_ACCESS_TYPE::OWNER->value; $planaccess->planid = $planid; @@ -77,34 +113,39 @@ public static function register_user($userid, $lang, $theme) { notifications_helper::notify_user($userid, -1, notifications_helper::TRIGGER_USER_REGISTERED); - return array( - 'userid' => $user->userid, - 'username' => $mdluser->username, - 'firstname' => $mdluser->firstname, - 'lastname' => $mdluser->lastname, + return [ + 'userid' => $lbplanneruser->userid, + 'username' => $USER->username, + 'firstname' => $USER->firstname, + 'lastname' => $USER->lastname, 'capabilities' => user_helper::get_user_capability_bitmask($userid), - 'theme' => $user->theme, - 'lang' => $user->language, - 'profileimageurl' => $mdluser->profileimageurl, + 'theme' => $lbplanneruser->theme, + 'lang' => $lbplanneruser->language, + 'profileimageurl' => user_helper::get_mdl_user_picture($userid), 'planid' => $planid, - 'colorblindness' => $user->colorblindness, - ); + 'colorblindness' => $lbplanneruser->colorblindness, + 'displaytaskcount' => $lbplanneruser->displaytaskcount, + ]; } - - public static function register_user_returns() { + /** + * Returns the data of a user. + * @return external_single_structure + */ + public static function register_user_returns(): external_single_structure { return new external_single_structure( - array( + [ 'userid' => new external_value(PARAM_INT, 'The id of the user'), 'username' => new external_value(PARAM_TEXT, 'The username of the user'), 'firstname' => new external_value(PARAM_TEXT, 'The firstname of the user'), 'lastname' => new external_value(PARAM_TEXT, 'The lastname of the user'), - 'capabilities' => new external_value(PARAM_INT, 'The capability'), + 'capabilities' => new external_value(PARAM_INT, 'The capabilities of the user represented as a bitmask value'), 'theme' => new external_value(PARAM_TEXT, 'The theme the user has selected'), 'lang' => new external_value(PARAM_TEXT, 'The language the user has selected'), 'profileimageurl' => new external_value(PARAM_URL, 'The url of the profile image'), 'planid' => new external_value(PARAM_INT, 'The id of the plan the user is assigned to'), 'colorblindness' => new external_value(PARAM_TEXT, 'The colorblindness of the user'), - ) + 'displaytaskcount' => new external_value(PARAM_INT, 'If the user has the taskcount-enabled 1-yes 0-no'), + ] ); } } diff --git a/lbplanner/services/user/update_user.php b/lbplanner/services/user/update_user.php index 9b681f46..9abc4676 100644 --- a/lbplanner/services/user/update_user.php +++ b/lbplanner/services/user/update_user.php @@ -16,103 +16,127 @@ namespace local_lbplanner_services; +use dml_exception; use external_api; use external_function_parameters; use external_single_structure; use external_value; +use invalid_parameter_exception; use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\plan_helper; +use moodle_exception; /** * Update the data for a user. + * + * @package local_lbplanner + * @copyright 2023 necodeIT + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class user_update_user extends external_api { - public static function update_user_parameters() { - return new external_function_parameters(array( - 'userid' => new external_value(PARAM_INT, 'The id of the user to register', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'lang' => new external_value(PARAM_TEXT, 'The language the user has selected', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'theme' => new external_value(PARAM_TEXT, 'The theme the user has selected', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + /** + * Parameters for update_user + * @return external_function_parameters + */ + public static function update_user_parameters(): external_function_parameters { + return new external_function_parameters([ + 'lang' => new external_value(PARAM_TEXT, 'The language the user has selected', VALUE_DEFAULT, null), + 'theme' => new external_value(PARAM_TEXT, 'The theme the user has selected', VALUE_DEFAULT, null), 'colorblindness' => new external_value( PARAM_TEXT, 'The colorblindness the user has selected', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED), + VALUE_DEFAULT, + null), 'displaytaskcount' => new external_value( PARAM_INT, - 'The displaytaskcount the user has selected', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED), - )); + 'If the user has the taskcount-enabled 1-yes 0-no', + VALUE_DEFAULT, + null), + ]); } - public static function update_user($userid, $lang, $theme, $colorblindness, $displaytaskcount) { - global $DB; + /** + * Updates the given user in the lbplanner DB + * @param string $lang language the user choose + * @param string $theme The theme the user has selected + * @param string $colorblindness The colorblindness the user has selected + * @param int $displaytaskcount The displaytaskcount the user has selected + * @return array The updated user + * @throws moodle_exception + * @throws dml_exception + * @throws invalid_parameter_exception + */ + public static function update_user($lang, $theme, $colorblindness, $displaytaskcount): array { + global $DB, $USER; self::validate_parameters( self::update_user_parameters(), - array( - 'userid' => $userid, + [ 'lang' => $lang, 'theme' => $theme, 'colorblindness' => $colorblindness, - 'displaytaskcount' => $displaytaskcount - ) + 'displaytaskcount' => $displaytaskcount, + ] ); - + $userid = $USER->id; user_helper::assert_access($userid); + // Look if User-Id is in the DB. if (!user_helper::check_user_exists($userid)) { - throw new \moodle_exception('User does not exist'); + throw new moodle_exception('User does not exist'); } - - // Look if User-Id is in the DB. - $user = user_helper::get_user($userid); + if ($lang !== null) { + $user->language = $lang; + } + if ($colorblindness !== null) { + $user->colorblindness = $colorblindness; + } + if ($theme !== null) { + $user->theme = $theme; + } + if ($displaytaskcount !== null) { + $user->displaytaskcount = $displaytaskcount; + } - $user->language = $lang; - $user->theme = $theme; - $user->colorblindness = $colorblindness; - $user->displaytaskcount = $displaytaskcount; - - $DB->update_record(user_helper::TABLE, $user, false); - - $mdluser = user_helper::get_mdl_user_info($userid); + $DB->update_record(user_helper::LB_PLANNER_USER_TABLE, $user); - return array( + return [ 'userid' => $userid, - 'lang' => $lang, - 'theme' => $theme, + 'lang' => $user->language, + 'theme' => $user->theme, 'capabilities' => user_helper::get_user_capability_bitmask($userid), - 'username' => $mdluser->username, - 'firstname' => $mdluser->firstname, - 'lastname' => $mdluser->lastname, - 'profileimageurl' => $mdluser->profileimageurl, + 'username' => $USER->username, + 'firstname' => $USER->firstname, + 'lastname' => $USER->lastname, + 'profileimageurl' => user_helper::get_mdl_user_picture($userid), 'planid' => plan_helper::get_plan_id($userid), - 'colorblindness' => $colorblindness, - 'displaytaskcount' => $displaytaskcount, - 'vintage' => $mdluser->vintage, + 'colorblindness' => $user->colorblindness, + 'displaytaskcount' => $user->displaytaskcount, + 'vintage' => $USER->address, - ); + ]; } - - public static function update_user_returns() { + /** + * Returns the data of a user. + * @return external_single_structure + */ + public static function update_user_returns(): external_single_structure { return new external_single_structure( - array( + [ 'userid' => new external_value(PARAM_INT, 'The id of the user'), 'username' => new external_value(PARAM_TEXT, 'The username of the user'), 'firstname' => new external_value(PARAM_TEXT, 'The firstname of the user'), 'lastname' => new external_value(PARAM_TEXT, 'The lastname of the user'), - 'capabilities' => new external_value(PARAM_INT, 'The role of the user'), + 'capabilities' => new external_value(PARAM_INT, 'The capabilities of the user represented as a bitmask value'), 'theme' => new external_value(PARAM_TEXT, 'The theme the user has selected'), 'lang' => new external_value(PARAM_TEXT, 'The language the user has selected'), 'profileimageurl' => new external_value(PARAM_URL, 'The url of the profile image'), 'planid' => new external_value(PARAM_INT, 'The id of the plan the user is assigned to'), 'colorblindness' => new external_value(PARAM_TEXT, 'The colorblindness the user has selected'), - 'displaytaskcount' => new external_value(PARAM_INT, 'The displaytaskcount the user has selected'), - 'vintage' => new external_value(PARAM_TEXT, 'The vintage of the user') - ) + 'displaytaskcount' => new external_value(PARAM_INT, 'If the user has the taskcount-enabled 1-yes 0-no'), + 'vintage' => new external_value(PARAM_TEXT, 'The vintage of the user'), + ] ); } } From 90954a1dd54a2ed489554270a655e16fe65b3e0b Mon Sep 17 00:00:00 2001 From: Muhi <49810240+mkocagoel@users.noreply.github.com> Date: Wed, 22 Nov 2023 16:37:27 +0100 Subject: [PATCH 15/92] LP-184 refactor courses webservices (#61) * reworked courses and removed unnecessary code * updated gitignore * Added Docs for color format * Removed unnecessary function get_course.php * Trying moodle codeblocks * comforting Moodle Docs and changing if statements to more readable ones. * ecodeIT to necodeIT --- .gitignore | 1 + lbplanner/classes/helpers/course_helper.php | 113 +++++------------- .../services/courses/get_all_courses.php | 94 +++++++-------- lbplanner/services/courses/get_course.php | 74 ------------ lbplanner/services/courses/update_course.php | 91 ++++++++------ 5 files changed, 124 insertions(+), 249 deletions(-) delete mode 100644 lbplanner/services/courses/get_course.php diff --git a/.gitignore b/.gitignore index ebed54a9..b1203584 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ moodle *.zip lbplanner.dart/test/env.dart example +.idea \ No newline at end of file diff --git a/lbplanner/classes/helpers/course_helper.php b/lbplanner/classes/helpers/course_helper.php index 78927bcf..f6792e0d 100644 --- a/lbplanner/classes/helpers/course_helper.php +++ b/lbplanner/classes/helpers/course_helper.php @@ -16,35 +16,22 @@ namespace local_lbplanner\helpers; +use context_course; +use dml_exception; use stdClass; +/** + * Helper class for courses + * + * @package local_lbplanner_helpers + * @copyright 2023 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ class course_helper { - - - /** - * Name of the Enrol Table - */ - const ENROL_TABLE = 'enrol'; - - /** - * Name of the User Enroll Table - */ - const USER_ENROL_TABLE = 'user_enrolments'; - - /** - * Name of the Course Table - */ - const COURSE_TABLE = 'course'; - - /** - * Name of the Category Table - */ - const CATEGORY_TABLE = 'course_categories'; - const LBPLANNER_COURSE_TABLE = 'local_lbplanner_courses'; - const COLORS = array( + const COLORS = [ "#f50057", "#536dfe", "#f9a826", @@ -60,33 +47,17 @@ class course_helper { "#376ECA", "#8B37CA", "#CA37B9", - ); - + ]; const DISABLED_COURSE = 0; const ENABLED_COURSE = 1; /** - * Get all the courses of the user - * @param int userid The id of the user - * - * @return array of EnrollIds - */ - public static function get_enrollments(int $userid) { - global $DB; - $enrollments = array(); - $records = $DB->get_records(self::USER_ENROL_TABLE, array ('userid' => $userid)); - foreach ($records as $record) { - if (in_array($record->enrolid, $enrollments) === false) { - $enrollments[] = $record->enrolid; - } - } - return $enrollments; - } - - /** - * Get the current year + * Get the current school year from the config + * Definition of a school year: 2020/2021 + * Check in config_helper.php for more info how the date is set for defaultactiveyear * - * @return string the current year the last 2 digits (20(20)) + * @return string the current year the last 2 digits (20/20) + * @throws dml_exception */ public static function get_current_year() : string { if (strpos(get_config('local_lbplanner', 'activeyear'), '/' ) !== false) { @@ -95,37 +66,16 @@ public static function get_current_year() : string { return get_config('local_lbplanner', 'defaultactiveyear'); } - /** - * Get the current category id - * - * @return int id of the current category - */ - public static function get_current_category() : int { - global $DB; - - return $DB->get_record_sql( - 'SELECT id FROM ' . self::CATEGORY_TABLE . ' WHERE name LIKE "%' . self::get_current_year() . '%"' - ); - } - /** - * Get course from mdl DB - * - * @param int $courseid id of the course - * @return stdClass course from moodle - */ - public static function get_mdl_course($courseid) : stdClass { - global $DB; - return $DB->get_record(self::COURSE_TABLE, array('id' => $courseid)); - } /** * Get course from lbpanner DB * * @param int $courseid id of the course in lbplanner * @return stdClass course from lbplanner + * @throws dml_exception */ - public static function get_lbplanner_course($courseid, $userid) : stdClass { + public static function get_lbplanner_course(int $courseid, $userid) : stdClass { global $DB; - return $DB->get_record(self::LBPLANNER_COURSE_TABLE, array('courseid' => $courseid, 'userid' => $userid)); + return $DB->get_record(self::LBPLANNER_COURSE_TABLE, ['courseid' => $courseid, 'userid' => $userid]); } /** @@ -135,41 +85,32 @@ public static function get_lbplanner_course($courseid, $userid) : stdClass { * @param int $userid user id * @return bool true if the user is enrolled */ - public static function check_access($courseid, $userid) : bool { - global $DB; - $enrolmentids = $DB->get_records(self::ENROL_TABLE, array('courseid' => $courseid), '', '*'); - foreach ($enrolmentids as $enrolmentid) { - if ($DB->record_exists(self::USER_ENROL_TABLE, array('enrolid' => $enrolmentid->id, 'userid' => $userid))) { - return true; - } - } - return false; + public static function check_access(int $courseid, int $userid) : bool { + $context = context_course::instance($courseid); + return is_enrolled($context, $userid, '', true); } /** * gets the fullname from a course * * @param int $courseid the course id * @return string the fullname of the course + * @throws dml_exception */ - public static function get_fullname($courseid) { - global $DB; - return $DB->get_record(self::COURSE_TABLE, array('id' => $courseid), '*', MUST_EXIST)->fullname; + public static function get_fullname(int $courseid): string { + return get_course($courseid)->fullname; } /** * Check if the course is from the current year * * @param int $courseid the course id * @return bool true if the course is from the current year + * @throws dml_exception */ - public static function check_current_year($courseid) { + public static function check_current_year(int $courseid): bool { if (strpos(self::get_fullname($courseid), self::get_current_year()) !== false) { return true; } else { return false; } } - public static function get_courseid($enrolmentid) { - global $DB; - return $DB->get_record(self::ENROL_TABLE, array('id' => $enrolmentid), '*', MUST_EXIST)->courseid; - } } diff --git a/lbplanner/services/courses/get_all_courses.php b/lbplanner/services/courses/get_all_courses.php index d50fcf58..fa5f44fc 100644 --- a/lbplanner/services/courses/get_all_courses.php +++ b/lbplanner/services/courses/get_all_courses.php @@ -23,97 +23,91 @@ use external_multiple_structure; use external_single_structure; use external_value; -use invalid_parameter_exception; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\course_helper; use moodle_exception; /** * Get all the courses of the current year. + * + * Retrievs all the courses of the current school year. + * @package local_lbplanner + * @copyright 2023 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class courses_get_all_courses extends external_api { + + /** + * Has no Parameters + * @return external_function_parameters + */ public static function get_all_courses_parameters(): external_function_parameters { - return new external_function_parameters(array( - 'userid' => new external_value( - PARAM_INT, - 'The id of the user to get the courses for', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - )); + return new external_function_parameters([]); } /** + * Get all the courses of the current year. * @throws coding_exception * @throws dml_exception * @throws moodle_exception - * @throws invalid_parameter_exception */ - public static function get_all_courses($userid): array { - global $DB; + public static function get_all_courses(): array { + global $DB, $USER; - self::validate_parameters(self::get_all_courses_parameters(), array('userid' => $userid)); - - user_helper::assert_access($userid); + $userid = $USER->id; $courses = enrol_get_my_courses(); // Remove Duplicates. $courses = array_unique($courses, SORT_REGULAR); - // Check this out: https://www.youtube.com/watch?v=z3Pzfi476HI . - $catgirls = array(); + $catgirls = []; foreach ($courses as $course) { $courseid = $course->id; $name = $course->fullname; - $shortname = substr($course->shortname, 0, 5); - + $shortname = $course->shortname; + // Check if the shortname contains a space. if (strpos($shortname, ' ') !== false) { $shortname = substr($shortname, 0, strpos($shortname, ' ')); } - - if (!course_helper::check_current_year($courseid)) { - continue; + // Check if the course is from the current year. + if (course_helper::check_current_year($courseid)) { + continue; } - if ($DB->record_exists( - course_helper::LBPLANNER_COURSE_TABLE, array('courseid' => $courseid, 'userid' => $userid) - )) { - $fetchedcourse = $DB->get_record( - course_helper::LBPLANNER_COURSE_TABLE, array('courseid' => $courseid, 'userid' => $userid), - '*', - MUST_EXIST - ); - $fetchedcourse->name = $name; - $catgirls[] = (object) $fetchedcourse; + // Check if the course is already in the LB Planner database. + if ($DB->record_exists(course_helper::LBPLANNER_COURSE_TABLE, ['courseid' => $courseid, 'userid' => $userid])) { + $fetchedcourse = course_helper::get_lbplanner_course($courseid, $userid); } else { - $catgirl = (object) array( - 'courseid' => $courseid, - 'color' => course_helper::COLORS[array_rand(course_helper::COLORS)], - 'shortname' => strtoupper($shortname), - 'enabled' => course_helper::DISABLED_COURSE, - 'userid' => $userid, - ); - $DB->insert_record(course_helper::LBPLANNER_COURSE_TABLE, $catgirl); - $catgirl->name = $name; - $catgirls[] = $catgirl; + // IF not create an Object to be put into the LB Planner database. + $fetchedcourse = (object) [ + 'courseid' => $courseid, + 'color' => course_helper::COLORS[array_rand(course_helper::COLORS)], + 'shortname' => strtoupper($shortname), + 'enabled' => course_helper::DISABLED_COURSE, + 'userid' => $userid, + ]; + $DB->insert_record(course_helper::LBPLANNER_COURSE_TABLE, $fetchedcourse); } - + // Add name to fetched Course. + $fetchedcourse->name = $name; + $catgirls[] = $fetchedcourse; } return $catgirls; } + /** + * Returns description of method result value + * @return external_multiple_structure description of method result value + */ public static function get_all_courses_returns(): external_multiple_structure { return new external_multiple_structure( new external_single_structure( - array( + [ 'courseid' => new external_value(PARAM_INT, 'The id of the course'), - 'color' => new external_value(PARAM_TEXT, 'The color of the course'), + 'color' => new external_value(PARAM_TEXT, 'The color of the course in HEX'), 'name' => new external_value(PARAM_TEXT, 'The name of the course'), 'shortname' => new external_value(PARAM_TEXT, 'The shortname of the course'), - 'enabled' => new external_value(PARAM_BOOL, 'Whether the course is enabled or not'), - 'userid' => new external_value(PARAM_INT, 'The id of the user'), - ) + 'enabled' => new external_value(PARAM_BOOL, 'Whether the course is enabled or not'), + ] ) ); } diff --git a/lbplanner/services/courses/get_course.php b/lbplanner/services/courses/get_course.php deleted file mode 100644 index e59d98fc..00000000 --- a/lbplanner/services/courses/get_course.php +++ /dev/null @@ -1,74 +0,0 @@ -. - -namespace local_lbplanner_services; - -use external_api; -use external_function_parameters; -use external_single_structure; -use external_value; -use local_lbplanner\helpers\user_helper; -use local_lbplanner\helpers\course_helper; - -/** - * Get the data for a course. - */ -class courses_get_course extends external_api { - public static function get_course_parameters() { - return new external_function_parameters(array( - 'courseid' => new external_value(PARAM_INT, 'The id of the course', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'userid' => new external_value(PARAM_INT, 'The id of the user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - )); - } - - public static function get_course($courseid, $userid) { - global $DB; - - self::validate_parameters(self::get_course_parameters(), array('courseid' => $courseid, 'userid' => $userid)); - - if (!$DB->record_exists('course', array('id' => $courseid))) { - throw new \moodle_exception('Course not found'); - } - - user_helper::assert_access($userid); - - if (!course_helper::check_access($courseid, $userid)) { - throw new \moodle_exception('Not Enrolled in course'); - } - - $course = $DB->get_record( - course_helper::LBPLANNER_COURSE_TABLE, - array('courseid' => $courseid, 'userid' => $userid), - '*', - MUST_EXIST - ); - $course->name = course_helper::get_fullname($course->courseid); - return $course; - } - - public static function get_course_returns() { - return new external_single_structure( - array( - 'courseid' => new external_value(PARAM_INT, 'The id of the course'), - 'color' => new external_value(PARAM_TEXT, 'The color of the course'), - 'name' => new external_value(PARAM_TEXT, 'The name of the course'), - 'shortname' => new external_value(PARAM_TEXT, 'The shortname of the course'), - 'enabled' => new external_value(PARAM_BOOL, 'Whether the course is enabled or not'), - 'userid' => new external_value(PARAM_INT, 'The id of the user'), - ) - ); - } -} diff --git a/lbplanner/services/courses/update_course.php b/lbplanner/services/courses/update_course.php index 21c2dcf2..c784c144 100644 --- a/lbplanner/services/courses/update_course.php +++ b/lbplanner/services/courses/update_course.php @@ -16,77 +16,90 @@ namespace local_lbplanner_services; +use dml_exception; use external_api; use external_function_parameters; -use external_single_structure; use external_value; -use local_lbplanner\helpers\user_helper; +use invalid_parameter_exception; use local_lbplanner\helpers\course_helper; +use moodle_exception; /** * Update the data for a course. + * + * Updates the data for a specific course. + * @package local_lbplanner + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2023 necodeIT */ class courses_update_course extends external_api { - public static function update_course_parameters() { - return new external_function_parameters(array( + /** + * Parameters for update_course. + * @return external_function_parameters + */ + public static function update_course_parameters(): external_function_parameters { + return new external_function_parameters([ 'courseid' => new external_value(PARAM_INT, 'The id of the course', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'color' => new external_value(PARAM_TEXT, 'The color of the course', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'shortname' => new external_value(PARAM_TEXT, 'The shortname of the course', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + 'color' => new external_value(PARAM_TEXT, 'The color of the course in HEX', VALUE_DEFAULT, null), + 'shortname' => new external_value(PARAM_TEXT, 'The shortname of the course', VALUE_DEFAULT, null), 'enabled' => new external_value( PARAM_BOOL, 'Whether the course is enabled or not', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - 'userid' => new external_value(PARAM_INT, 'The id of the user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - )); + VALUE_DEFAULT, + null + ) + ]); } - public static function update_course($courseid, $color, $shortname, $enabled, $userid) { - global $DB; + /** + * Update the User-data for a course. + * @param int $courseid The id of the course + * @param string $color The color of the course + * @param string $shortname The shortname of the course + * @param bool $enabled Whether the course is enabled or not + * @return void + * @throws dml_exception + * @throws invalid_parameter_exception + * @throws moodle_exception + */ + public static function update_course( $courseid, $color, $shortname, $enabled): void { + global $DB , $USER; self::validate_parameters( self::update_course_parameters(), - array( + [ 'courseid' => $courseid, 'color' => $color, 'shortname' => $shortname, 'enabled' => $enabled, - 'userid' => $userid - ) + ] ); - user_helper::assert_access($userid); - - if (!course_helper::check_access($courseid, $userid)) { - throw new \moodle_exception('Access denied'); + if (strlen($shortname) > 5) { + throw new moodle_exception('Shortname is too long'); } - $course = course_helper::get_lbplanner_course($courseid, $userid); - if (strlen($shortname) > 5) { - throw new \moodle_exception('Shortname is too long'); + $course = course_helper::get_lbplanner_course($courseid, $USER->id); + + if ($color !== null) { + $course->color = $color; + } + if ($shortname !== null) { + $course->shortname = $shortname; + } + if ($enabled !== null) { + $course->enabled = $enabled; } - $course->color = $color; - $course->shortname = $shortname; - $course->enabled = $enabled; $DB->update_record(course_helper::LBPLANNER_COURSE_TABLE, $course); - $course->name = course_helper::get_fullname($course->courseid); - return $course; } + /** + * Returns nothing. + * @return null + */ public static function update_course_returns() { - return new external_single_structure( - array( - 'courseid' => new external_value(PARAM_INT, 'The id of the course'), - 'color' => new external_value(PARAM_TEXT, 'The color of the course'), - 'name' => new external_value(PARAM_TEXT, 'The name of the course'), - 'shortname' => new external_value(PARAM_TEXT, 'The shortname of the course'), - 'enabled' => new external_value(PARAM_BOOL, 'Whether the course is enabled or not'), - 'userid' => new external_value(PARAM_INT, 'The id of the user'), - ) - ); + return null; } } From 124729ced3fb512c78eda35a3ea835c828df57a1 Mon Sep 17 00:00:00 2001 From: Muhi <49810240+mkocagoel@users.noreply.github.com> Date: Tue, 28 Nov 2023 15:55:31 +0100 Subject: [PATCH 16/92] fixed shortname too long (#67) Courses where able to input a too long shortname. DB doesnt like that --- lbplanner/services/courses/get_all_courses.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lbplanner/services/courses/get_all_courses.php b/lbplanner/services/courses/get_all_courses.php index fa5f44fc..66dae9be 100644 --- a/lbplanner/services/courses/get_all_courses.php +++ b/lbplanner/services/courses/get_all_courses.php @@ -69,6 +69,9 @@ public static function get_all_courses(): array { if (strpos($shortname, ' ') !== false) { $shortname = substr($shortname, 0, strpos($shortname, ' ')); } + if (strlen($shortname) >= 5) { + $shortname = substr($shortname, 0, 5); + } // Check if the course is from the current year. if (course_helper::check_current_year($courseid)) { continue; From 2b0004430d696c02ce72d1ce4726f6aaa3a33dfc Mon Sep 17 00:00:00 2001 From: Riedler Date: Tue, 5 Dec 2023 12:39:25 +0000 Subject: [PATCH 17/92] LP-203: rework enums (#65) * reworked enums * removed two more `->value` I forgot --- lbplanner/classes/helpers/plan_helper.php | 42 ++++++++++++++-------- lbplanner/classes/polyfill/enum.php | 25 +++++++++++++ lbplanner/services/plan/accept_invite.php | 12 +++---- lbplanner/services/plan/decline_invite.php | 4 +-- lbplanner/services/plan/invite_user.php | 4 +-- lbplanner/services/plan/leave_plan.php | 10 +++--- lbplanner/services/user/delete_user.php | 4 +-- lbplanner/services/user/register_user.php | 4 +-- 8 files changed, 71 insertions(+), 34 deletions(-) create mode 100644 lbplanner/classes/polyfill/enum.php diff --git a/lbplanner/classes/helpers/plan_helper.php b/lbplanner/classes/helpers/plan_helper.php index 76f6bdae..f0eb8c39 100644 --- a/lbplanner/classes/helpers/plan_helper.php +++ b/lbplanner/classes/helpers/plan_helper.php @@ -19,33 +19,45 @@ use external_single_structure; use external_value; use external_multiple_structure; +use local_lbplanner\polyfill\enum; + +// TODO: revert to native enums once we migrate to php8 /** * Levels of access that a user can have for a plan */ -enum PLAN_ACCESS_TYPE: int { - case OWNER = 0; - case WRITE = 1; - case READ = 2; - case NONE = -1; +class PLAN_ACCESS_TYPE extends Enum { + const OWNER = 0; + const WRITE = 1; + const READ = 2; + const NONE = -1; + public static function get_classname(): string { + return __CLASS__; + } } /** * Whether EK modules are enabled inside the planner */ -enum PLAN_EK: int { - case DISABLED = 0; - case ENABLED = 1; +class PLAN_EK extends Enum { + const DISABLED = 0; + const ENABLED = 1; + public static function get_classname(): string { + return __CLASS__; + } } /** * States an invite can be in */ -enum PLAN_INVITE_STATE: int { - case PENDING = 0; - case ACCEPTED = 1; - case DECLINED = 2; - case EXPIRED = 3; +class PLAN_INVITE_STATE extends Enum { + const PENDING = 0; + const ACCEPTED = 1; + const DECLINED = 2; + const EXPIRED = 3; + public static function get_classname(): string { + return __CLASS__; + } } /** @@ -95,7 +107,7 @@ public static function get_owner(int $planid):int { $owner = $DB->get_field( self::ACCESS_TABLE, - 'userid', array('planid' => $planid, 'accesstype' => PLAN_ACCESS_TYPE::OWNER->value) + 'userid', array('planid' => $planid, 'accesstype' => PLAN_ACCESS_TYPE::OWNER) ); return $owner; @@ -297,7 +309,7 @@ public static function remove_user(int $planid, int $userid, int $removeuserid) ); $oldaccess->planid = $newplanid; - $oldaccess->accesstype = PLAN_ACCESS_TYPE::OWNER->value; + $oldaccess->accesstype = PLAN_ACCESS_TYPE::OWNER; $DB->update_record(self::ACCESS_TABLE, $oldaccess); diff --git a/lbplanner/classes/polyfill/enum.php b/lbplanner/classes/polyfill/enum.php new file mode 100644 index 00000000..aafb21d8 --- /dev/null +++ b/lbplanner/classes/polyfill/enum.php @@ -0,0 +1,25 @@ +. + +namespace local_lbplanner\polyfill; + +abstract class Enum { + public static function tryFrom(mixed $value): ?mixed { + $cases = get_class_vars(static::get_classname()); + return in_array($value,$cases,true) ? $value : null; + } + public abstract static function get_classname(): string; +} \ No newline at end of file diff --git a/lbplanner/services/plan/accept_invite.php b/lbplanner/services/plan/accept_invite.php index ad0e5242..60b2c6d3 100644 --- a/lbplanner/services/plan/accept_invite.php +++ b/lbplanner/services/plan/accept_invite.php @@ -45,7 +45,7 @@ public static function accept_invite($inviteid) { throw new \moodle_exception('Invite not found'); } if (!$DB->record_exists(plan_helper::INVITES_TABLE, - [ 'id' => $inviteid, 'inviteeid' => $USER->id, 'status' => PLAN_INVITE_STATE::PENDING->value])) { + [ 'id' => $inviteid, 'inviteeid' => $USER->id, 'status' => PLAN_INVITE_STATE::PENDING])) { throw new \moodle_exception('Invite already accepted or declined'); } @@ -53,7 +53,7 @@ public static function accept_invite($inviteid) { [ 'id' => $inviteid, 'inviteeid' => $USER->id, - 'status' => PLAN_INVITE_STATE::PENDING->value, + 'status' => PLAN_INVITE_STATE::PENDING, ], '*', MUST_EXIST @@ -95,18 +95,18 @@ public static function accept_invite($inviteid) { MUST_EXIST ); - $invite->status = PLAN_INVITE_STATE::ACCEPTED->value; + $invite->status = PLAN_INVITE_STATE::ACCEPTED; $DB->update_record(plan_helper::INVITES_TABLE, $invite); - $planaccess->accesstype = PLAN_ACCESS_TYPE::READ->value; + $planaccess->accesstype = PLAN_ACCESS_TYPE::READ; $planaccess->planid = $invite->planid; $DB->update_record(plan_helper::ACCESS_TABLE, $planaccess); $invites = plan_helper::get_invites_send($USER->id); foreach ($invites as $invite) { - if ($invite->status == PLAN_INVITE_STATE::PENDING->value) { - $invite->status = PLAN_INVITE_STATE::EXPIRED->value; + if ($invite->status == PLAN_INVITE_STATE::PENDING) { + $invite->status = PLAN_INVITE_STATE::EXPIRED; $DB->update_record(plan_helper::INVITES_TABLE, $invite); } } diff --git a/lbplanner/services/plan/decline_invite.php b/lbplanner/services/plan/decline_invite.php index e05bfffc..d5b550d9 100644 --- a/lbplanner/services/plan/decline_invite.php +++ b/lbplanner/services/plan/decline_invite.php @@ -53,7 +53,7 @@ public static function decline_invite($inviteid) { MUST_EXIST ); - if ($invite->status !== PLAN_INVITE_STATE::PENDING->value) { + if ($invite->status !== PLAN_INVITE_STATE::PENDING) { throw new \moodle_exception('Invite already accepted or declined'); } @@ -64,7 +64,7 @@ public static function decline_invite($inviteid) { notifications_helper::TRIGGER_INVITE_DECLINED ); - $invite->status = PLAN_INVITE_STATE::DECLINED->value; + $invite->status = PLAN_INVITE_STATE::DECLINED; $DB->update_record(plan_helper::INVITES_TABLE, $invite); } diff --git a/lbplanner/services/plan/invite_user.php b/lbplanner/services/plan/invite_user.php index 4c4a497c..f4aa3bbc 100644 --- a/lbplanner/services/plan/invite_user.php +++ b/lbplanner/services/plan/invite_user.php @@ -64,7 +64,7 @@ public static function invite_user($inviteeid) { if ($DB->record_exists( plan_helper::INVITES_TABLE, - ['inviteeid' => $inviteeid, 'planid' => $planid, 'status' => PLAN_INVITE_STATE::PENDING->value] + ['inviteeid' => $inviteeid, 'planid' => $planid, 'status' => PLAN_INVITE_STATE::PENDING] )) { throw new \moodle_exception('User is already invited'); } @@ -75,7 +75,7 @@ public static function invite_user($inviteeid) { $invite->inviterid = $USER->id; $invite->inviteeid = $inviteeid; $invite->timestamp = time(); - $invite->status = PLAN_INVITE_STATE::PENDING->value; + $invite->status = PLAN_INVITE_STATE::PENDING; $invite->id = $DB->insert_record(plan_helper::INVITES_TABLE, $invite); diff --git a/lbplanner/services/plan/leave_plan.php b/lbplanner/services/plan/leave_plan.php index 5e2131d9..9adaf28f 100644 --- a/lbplanner/services/plan/leave_plan.php +++ b/lbplanner/services/plan/leave_plan.php @@ -54,7 +54,7 @@ public static function leave_plan() { if ($member->userid == $USER->id) { continue; } - if ($member->accesstype == PLAN_ACCESS_TYPE::WRITE->value) { + if ($member->accesstype == PLAN_ACCESS_TYPE::WRITE) { $writemembers[] = $member; } $allmembers[] = $member; @@ -68,7 +68,7 @@ public static function leave_plan() { plan_helper::ACCESS_TABLE, ['planid' => $planid, 'userid' => $newowner], '*', MUST_EXIST ); - $newowneraccess->accesstype = PLAN_ACCESS_TYPE::OWNER->value; + $newowneraccess->accesstype = PLAN_ACCESS_TYPE::OWNER; $DB->update_record(plan_helper::ACCESS_TABLE, $newowneraccess); } @@ -80,15 +80,15 @@ public static function leave_plan() { ); $oldaccess->planid = $newplanid; - $oldaccess->accesstype = PLAN_ACCESS_TYPE::OWNER->value; + $oldaccess->accesstype = PLAN_ACCESS_TYPE::OWNER; $DB->update_record(plan_helper::ACCESS_TABLE, $oldaccess); // Notify plan owner that user has left his plan. $invites = plan_helper::get_invites_send($USER->id); foreach ($invites as $invite) { - if ($invite->status == PLAN_INVITE_STATE::PENDING->value) { - $invite->status = PLAN_INVITE_STATE::EXPIRED->value; + if ($invite->status == PLAN_INVITE_STATE::PENDING) { + $invite->status = PLAN_INVITE_STATE::EXPIRED; $DB->update_record(plan_helper::INVITES_TABLE, $invite); } } diff --git a/lbplanner/services/user/delete_user.php b/lbplanner/services/user/delete_user.php index 29269912..422a4a68 100644 --- a/lbplanner/services/user/delete_user.php +++ b/lbplanner/services/user/delete_user.php @@ -92,8 +92,8 @@ public static function delete_user($userid) { $invites = plan_helper::get_invites_send($userid); foreach ($invites as $invite) { - if ($invite->status == PLAN_INVITE_STATE::PENDING->value) { - $invite->status = PLAN_INVITE_STATE::EXPIRED->value; + if ($invite->status == PLAN_INVITE_STATE::PENDING) { + $invite->status = PLAN_INVITE_STATE::EXPIRED; $DB->update_record(plan_helper::INVITES_TABLE, $invite); } } diff --git a/lbplanner/services/user/register_user.php b/lbplanner/services/user/register_user.php index 92d222e1..27860ac7 100644 --- a/lbplanner/services/user/register_user.php +++ b/lbplanner/services/user/register_user.php @@ -100,13 +100,13 @@ public static function register_user(string $lang, string $theme): array { $DB->insert_record(user_helper::LB_PLANNER_USER_TABLE, $lbplanneruser); $plan = new stdClass(); $plan->name = 'Plan for ' . $USER->username; - $plan->enableek = plan_helper::EK_ENABLED; + $plan->enableek = PLAN_EK::ENABLED; $planid = $DB->insert_record(plan_helper::TABLE, $plan); $planaccess = new stdClass(); $planaccess->userid = $userid; - $planaccess->accesstype = PLAN_ACCESS_TYPE::OWNER->value; + $planaccess->accesstype = PLAN_ACCESS_TYPE::OWNER; $planaccess->planid = $planid; $DB->insert_record(plan_helper::ACCESS_TABLE, $planaccess); From a95a2e7e1065fbb52de480388b453483fd1d8c78 Mon Sep 17 00:00:00 2001 From: Riedler Date: Tue, 5 Dec 2023 13:21:08 +0000 Subject: [PATCH 18/92] implemented polyfill Enum::from and added some code docs (#69) --- lbplanner/classes/polyfill/enum.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lbplanner/classes/polyfill/enum.php b/lbplanner/classes/polyfill/enum.php index aafb21d8..8b6d9c01 100644 --- a/lbplanner/classes/polyfill/enum.php +++ b/lbplanner/classes/polyfill/enum.php @@ -16,10 +16,32 @@ namespace local_lbplanner\polyfill; +use ValueError; + abstract class Enum { + /** + * tries to match the passed value to one of the enum values + * @param $value the value to be matched + * @return either the matching enum value or null if not found + */ public static function tryFrom(mixed $value): ?mixed { $cases = get_class_vars(static::get_classname()); return in_array($value,$cases,true) ? $value : null; } + /** + * tries to match the passed value to one of the enum values + * @param $value the value to be matched + * @return the matching enum value + * @throws ValueError if not found + */ + public static function from(mixed $value): mixed { + $cases = get_class_vars(static::get_classname()); + + if(!in_array($value,$cases,true)){ + throw new ValueError("value {$value} cannot be represented as a value in enum ".static::get_classname()); + } + + return $value; + } public abstract static function get_classname(): string; } \ No newline at end of file From 65474cbb4083b65c7a322c5bab1f30428c95db86 Mon Sep 17 00:00:00 2001 From: mcquenji <60017181+mcquenji@users.noreply.github.com> Date: Tue, 12 Dec 2023 13:58:45 +0100 Subject: [PATCH 19/92] removed functions that have been deleted from services.php --- lbplanner/db/services.php | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/lbplanner/db/services.php b/lbplanner/db/services.php index 9f2d6b6b..21abf676 100644 --- a/lbplanner/db/services.php +++ b/lbplanner/db/services.php @@ -54,15 +54,6 @@ 'capabilities' => 'local/lb_planner:student', 'ajax' => true, ), - 'local_lbplanner_courses_get_course' => array( - 'classname' => 'local_lbplanner_services\courses_get_course', - 'methodname' => 'get_course', - 'classpath' => 'local/lbplanner/services/courses/get_course.php', - 'description' => 'Get the data for a course', - 'type' => 'read', - 'capabilities' => 'local/lb_planner:student', - 'ajax' => true, - ), 'local_lbplanner_courses_get_all_courses' => array( 'classname' => 'local_lbplanner_services\courses_get_all_courses', 'methodname' => 'get_all_courses', @@ -243,15 +234,6 @@ 'capabilities' => 'local/lb_planner:student', 'ajax' => true, ), - 'local_lbplanner_feedback_get_feedback' => array( - 'classname' => 'local_lbplanner_services\feedback_get_feedback', - 'methodname' => 'get_feedback', - 'classpath' => 'local/lbplanner/services/feedback/get_feedback.php', - 'description' => 'Get the feedback of the given id', - 'type' => 'read', - 'capabilities' => 'local/lb_planner:admin, local/lb_planner:manager', - 'ajax' => true, - ), 'local_lbplanner_feedback_get_all_feedbacks' => array( 'classname' => 'local_lbplanner_services\feedback_get_all_feedbacks', 'methodname' => 'get_all_feedbacks', @@ -316,7 +298,6 @@ 'local_lbplanner_user_register_user', 'local_lbplanner_user_update_user', 'local_lbplanner_courses_get_all_courses', - 'local_lbplanner_courses_get_course', 'local_lbplanner_courses_update_course', 'local_lbplanner_modules_get_all_course_modules', 'local_lbplanner_modules_get_all_modules', @@ -339,7 +320,6 @@ 'local_lbplanner_feedback_submit_feedback', 'local_lbplanner_feedback_delete_feedback', 'local_lbplanner_feedback_get_all_feedbacks', - 'local_lbplanner_feedback_get_feedback', 'local_lbplanner_feedback_update_feedback', 'local_lbplanner_plan_accept_invite', 'local_lbplanner_plan_decline_invite', From 305d14ed4efdd109bb942816dbdcfc51522d8913 Mon Sep 17 00:00:00 2001 From: Riedler Date: Wed, 7 Feb 2024 14:23:22 +0100 Subject: [PATCH 20/92] combined update_deadline and add_deadline into set_deadline (#70) * combined update_deadline and add_deadline into set_deadline * corrected some docstrings * fixed minor spelling mistake --- lbplanner/services/plan/add_deadline.php | 89 ------------------- .../{update_deadline.php => set_deadline.php} | 41 +++++---- 2 files changed, 26 insertions(+), 104 deletions(-) delete mode 100644 lbplanner/services/plan/add_deadline.php rename lbplanner/services/plan/{update_deadline.php => set_deadline.php} (62%) diff --git a/lbplanner/services/plan/add_deadline.php b/lbplanner/services/plan/add_deadline.php deleted file mode 100644 index 8f553c35..00000000 --- a/lbplanner/services/plan/add_deadline.php +++ /dev/null @@ -1,89 +0,0 @@ -. - -namespace local_lbplanner_services; - -use external_api; -use external_function_parameters; -use external_value; -use local_lbplanner\helpers\plan_helper; - -/** - * Add a deadline to the plan. - */ -class plan_add_deadline extends external_api { - public static function add_deadline_parameters() { - return new external_function_parameters([ - 'moduleid' => new external_value( - PARAM_INT, - 'The ID of the Module', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - 'deadlinestart' => new external_value( - PARAM_INT, - 'The Start of the Module', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - 'deadlineend' => new external_value( - PARAM_INT, - 'The End of the Module', - VALUE_REQUIRED, - null, - NULL_NOT_ALLOWED - ), - ]); - } - - public static function add_deadline($moduleid, $deadlinestart, $deadlineend) { - global $DB, $USER; - - self::validate_parameters( - self::add_deadline_parameters(), - [ - 'moduleid' => $moduleid, - 'deadlinestart' => $deadlinestart, - 'deadlineend' => $deadlineend, - ] - ); - - $planid = plan_helper::get_plan_id($USER->id); - - if ( !plan_helper::check_edit_permissions( $planid, $USER->id ) ) { - throw new \moodle_exception('Access denied'); - } - - if ($DB->record_exists(plan_helper::DEADLINES_TABLE, ['moduleid' => $moduleid, 'planid' => $planid])) { - throw new \moodle_exception('Deadline already exists'); - } - - $deadline = new \stdClass(); - - $deadline->planid = $planid; - $deadline->moduleid = $moduleid; - $deadline->deadlinestart = $deadlinestart; - $deadline->deadlineend = $deadlineend; - - return $DB->insert_record(plan_helper::DEADLINES_TABLE, $deadline); - } - - public static function add_deadline_returns() { - return new external_value(PARAM_INT,"The ID of the newly added deadline"); - } -} diff --git a/lbplanner/services/plan/update_deadline.php b/lbplanner/services/plan/set_deadline.php similarity index 62% rename from lbplanner/services/plan/update_deadline.php rename to lbplanner/services/plan/set_deadline.php index 43fdcff9..fcb77b2f 100644 --- a/lbplanner/services/plan/update_deadline.php +++ b/lbplanner/services/plan/set_deadline.php @@ -22,28 +22,28 @@ use local_lbplanner\helpers\plan_helper; /** - * Update a deadline from the plan. + * Set the deadline for a module */ -class plan_update_deadline extends external_api { - public static function update_deadline_parameters() { +class plan_set_deadline extends external_api { + public static function set_deadline_parameters() { return new external_function_parameters([ 'moduleid' => new external_value( PARAM_INT, - 'The ID of the Module', + 'The ID of the module the deadline is for', VALUE_REQUIRED, null, NULL_NOT_ALLOWED ), 'deadlinestart' => new external_value( PARAM_INT, - 'The start of the Module', + 'The start of the deadline', VALUE_REQUIRED, null, NULL_NOT_ALLOWED ), 'deadlineend' => new external_value( PARAM_INT, - 'The End of the Module', + 'The end of the deadline', VALUE_REQUIRED, null, NULL_NOT_ALLOWED @@ -51,11 +51,11 @@ public static function update_deadline_parameters() { ]); } - public static function update_deadline($moduleid, $deadlinestart, $deadlineend) { + public static function set_deadline($moduleid, $deadlinestart, $deadlineend) { global $DB, $USER; self::validate_parameters( - self::update_deadline_parameters(), + self::set_deadline_parameters(), [ 'moduleid' => $moduleid, 'deadlinestart' => $deadlinestart, @@ -69,18 +69,29 @@ public static function update_deadline($moduleid, $deadlinestart, $deadlineend) throw new \moodle_exception('Access denied'); } + // if a deadline already exists, if (!$DB->record_exists(plan_helper::DEADLINES_TABLE, ['moduleid' => $moduleid, 'planid' => $planid])) { - throw new \moodle_exception('Deadline doesnt exists'); - } - $deadline = $DB->get_record(plan_helper::DEADLINES_TABLE, ['moduleid' => $moduleid, 'planid' => $planid]); + // update the existing deadline + $deadline = $DB->get_record(plan_helper::DEADLINES_TABLE, ['moduleid' => $moduleid, 'planid' => $planid]); + + $deadline->deadlinestart = $deadlinestart; + $deadline->deadlineend = $deadlineend; - $deadline->deadlinestart = $deadlinestart; - $deadline->deadlineend = $deadlineend; + $DB->update_record(plan_helper::DEADLINES_TABLE, $deadline); + } else { + // otherwise insert a new one + $deadline = new \stdClass(); - $DB->update_record(plan_helper::DEADLINES_TABLE, $deadline); + $deadline->planid = $planid; + $deadline->moduleid = $moduleid; + $deadline->deadlinestart = $deadlinestart; + $deadline->deadlineend = $deadlineend; + + $DB->insert_record(plan_helper::DEADLINES_TABLE, $deadline); + } } - public static function update_deadline_returns() { + public static function set_deadline_returns() { return null; } } From 1a23d83788a8779804536a75dca647fcc2e1e30d Mon Sep 17 00:00:00 2001 From: Riedler Date: Wed, 7 Feb 2024 14:33:51 +0100 Subject: [PATCH 21/92] LP-195 api docs (#63) * updated feedback API docs * improved docs in notification service * updated API docs for invite subservice * updated API docs for deadline subservice * updated API docs for the rest of the plan service * api docs corrections * changes to enum for upcoming changes to api docs * added another helper just to list enum cases inside the API docs * added capability to format Enum class to string * restructured modules helper with new Enum polyfills * restructured notification helper with Enums & fixed API docs * replaced duplicate code with better newer implementation * specified that the shortened module name is max. 5 chars --- lbplanner/classes/helpers/invite_helper.php | 12 +- lbplanner/classes/helpers/modules_helper.php | 158 +++++++----------- .../classes/helpers/notifications_helper.php | 84 ++++------ lbplanner/classes/helpers/plan_helper.php | 37 ++-- lbplanner/classes/polyfill/enum.php | 65 +++++-- lbplanner/db/services.php | 19 +-- .../services/feedback/delete_feedback.php | 2 +- .../services/feedback/submit_feedback.php | 6 +- .../services/feedback/update_feedback.php | 6 +- .../notifications/update_notification.php | 4 +- lbplanner/services/plan/accept_invite.php | 7 +- lbplanner/services/plan/decline_invite.php | 5 +- lbplanner/services/plan/delete_deadline.php | 4 +- lbplanner/services/plan/invite_user.php | 5 +- lbplanner/services/plan/leave_plan.php | 3 +- lbplanner/services/plan/remove_user.php | 2 +- lbplanner/services/plan/update_access.php | 4 +- lbplanner/services/plan/update_plan.php | 4 +- lbplanner/services/user/register_user.php | 3 +- 19 files changed, 198 insertions(+), 232 deletions(-) diff --git a/lbplanner/classes/helpers/invite_helper.php b/lbplanner/classes/helpers/invite_helper.php index 091f6adc..7a5a9cbc 100644 --- a/lbplanner/classes/helpers/invite_helper.php +++ b/lbplanner/classes/helpers/invite_helper.php @@ -27,12 +27,12 @@ class invite_helper { public static function structure() : external_single_structure { return new external_single_structure( [ - 'id' => new external_value(PARAM_INT, 'The id of the invite'), - 'inviterid' => new external_value(PARAM_INT, 'The id of the owner user'), - 'inviteeid' => new external_value(PARAM_INT, 'The id of the invited user'), - 'planid' => new external_value(PARAM_INT, 'The id of the plan'), - 'status' => new external_value(PARAM_INT, 'The Status of the invitation'), - 'timestamp' => new external_value(PARAM_INT, 'The time when the invitation was send'), + 'id' => new external_value(PARAM_INT, 'invite ID'), + 'inviterid' => new external_value(PARAM_INT, 'ID of the user who issued the invitation'), + 'inviteeid' => new external_value(PARAM_INT, 'ID of the user who got invited'), + 'planid' => new external_value(PARAM_INT, 'plan ID'), + 'status' => new external_value(PARAM_INT, 'status of the invitation'), + 'timestamp' => new external_value(PARAM_INT, 'time when the invitation was send'), ] ); } diff --git a/lbplanner/classes/helpers/modules_helper.php b/lbplanner/classes/helpers/modules_helper.php index 99cb0278..2be78601 100644 --- a/lbplanner/classes/helpers/modules_helper.php +++ b/lbplanner/classes/helpers/modules_helper.php @@ -22,6 +22,43 @@ use external_value; use moodle_url; +use local_lbplanner\polyfill\Enum; + + +// TODO: revert to native enums once we migrate to php8 + +/** + * Stati a module can be in + */ +class MODULE_STATUS extends Enum { + const DONE = 0; + const UPLOADED = 1; + const LATE = 2; + const PENDING = 3; +} + +/** + * Grades a module can receive + */ +class MODULE_GRADE extends Enum { + const EKV = 0; + const EK = 1; + const GKV = 2; + const GK = 3; + const RIP = 4; +} + +/** + * Module Types + */ +class MODULE_TYPE extends Enum { + const GK = 0; + const EK = 1; + const TEST = 2; + const M = 3; + const NONE = 4; +} + /** * Contains helper functions for working with modules. */ @@ -62,77 +99,6 @@ class modules_helper { */ const SUBMISSION_STATUS_SUBMITTED = 'submitted'; - /** - * Enum value for grade 'Nicht erfüllt'. - */ - const GRADE_RIP = 4; - - /** - * Enum value for grade 'GK überwiegend'. - */ - const GRADE_GK = 3; - - /** - * Enum value for grade 'GK vollständig'. - */ - const GRADE_GKV = 2; - - - /** - * Enum value for grade 'EK überwiegend'. - */ - const GRADE_EK = 1; - - /** - * Enum value for grade 'EK vollständig'. - */ - const GRADE_EKV = 0; - - /** - * Enum value for completed module. - */ - const STATUS_DONE = 0; - - /** - * Enum value for uploaded module. - */ - const STATUS_UPLOADED = 1; - - /** - * Enum value for not completed module. - */ - const STATUS_LATE = 2; - - /** - * Enum value for pending module. - */ - const STATUS_PENDING = 3; - - /** - * Enum value for modules of type 'GK'. - */ - const TYPE_GK = 0; - - /** - * Enum value for modules of type 'EK'. - */ - const TYPE_EK = 1; - - /** - * Enum value for modules of type 'TEST'. - */ - const TYPE_TEST = 2; - - /** - * Enum value for modules of type 'M'. - */ - const TYPE_M = 3; - - /** - * Enum value for non - */ - const TYPE_NONE = 4; - /** * The return structure of a module. * @@ -141,13 +107,13 @@ class modules_helper { public static function structure() : external_single_structure { return new external_single_structure( array( - 'moduleid' => new external_value(PARAM_INT, 'The id of the module'), - 'name' => new external_value(PARAM_TEXT, 'The name of the module'), - 'courseid' => new external_value(PARAM_INT, 'The id of the course'), - 'status' => new external_value(PARAM_INT, 'The status of the module'), - 'type' => new external_value(PARAM_INT, 'The type of the module'), - 'url' => new external_value(PARAM_TEXT, 'The url of the module in moodle'), - 'grade' => new external_value(PARAM_INT, 'The grade of the module'), + 'moduleid' => new external_value(PARAM_INT, 'Module ID'), + 'name' => new external_value(PARAM_TEXT, 'Shortened module name (max. 5 chars)'), + 'courseid' => new external_value(PARAM_INT, 'Course ID'), + 'status' => new external_value(PARAM_INT, 'Module status '.MODULE_STATUS::format()), + 'type' => new external_value(PARAM_INT, 'Module type '.MODULE_TYPE::format()), + 'url' => new external_value(PARAM_TEXT, 'URL to moodle page for module'), + 'grade' => new external_value(PARAM_INT, 'The grade of the module '.MODULE_GRADE::format()), 'deadline' => new external_value(PARAM_INT, 'The deadline of the module set by the teacher'), ) ); @@ -164,7 +130,7 @@ public static function structure() : external_single_structure { */ public static function determin_uinified_grade(int $grade, int $maxgrade, int $mingrade, int $gradepass) : int { if ($grade < $gradepass) { - return self::GRADE_RIP; + return MODULE_GRADE::RIP; } $maxgrade = $maxgrade - $mingrade; @@ -172,15 +138,15 @@ public static function determin_uinified_grade(int $grade, int $maxgrade, int $m $p = $grade / $maxgrade; if ($p >= 0.9) { - return self::GRADE_EKV; + return MODULE_GRADE::EKV; } else if ($p >= 0.8) { - return self::GRADE_EK; + return MODULE_GRADE::EK; } else if ($p >= 0.7) { - return self::GRADE_GKV; + return MODULE_GRADE::GKV; } else if ($p >= 0.4) { - return self::GRADE_GK; + return MODULE_GRADE::GK; } else { - return self::GRADE_RIP; + return MODULE_GRADE::RIP; } } @@ -194,13 +160,13 @@ public static function determin_uinified_grade(int $grade, int $maxgrade, int $m */ public static function map_status(bool $submitted, bool $done, bool $late) : int { if ($done) { - return self::STATUS_DONE; + return MODULE_STATUS::DONE; } else if ($submitted) { - return self::STATUS_UPLOADED; + return MODULE_STATUS::UPLOADED; } else if ($late) { - return self::STATUS_LATE; + return MODULE_STATUS::LATE; } else { - return self::STATUS_PENDING; + return MODULE_STATUS::PENDING; } } @@ -216,25 +182,25 @@ public static function determin_type(string $modulename) : int { // Return TYPE_TEST if the name contains 'test' or 'sa'. if (strpos($modulename, '[TEST]') !== false || strpos($modulename, '[SA]') !== false) { - return self::TYPE_TEST; + return MODULE_TYPE::TEST; } // Return TYPE_GK if the name contains 'GK'. if (strpos($modulename, '[GK]') !== false) { - return self::TYPE_GK; + return MODULE_TYPE::GK; } if (strpos($modulename, '[EK]') !== false) { - return self::TYPE_EK; + return MODULE_TYPE::EK; } // Return TYPE_EK if the name contains 'M'. if (strpos($modulename, '[M]') !== false) { - return self::TYPE_M; + return MODULE_TYPE::M; } // Return TYPE_NONE elswise. - return self::TYPE_NONE; + return MODULE_TYPE::NONE; } /** @@ -272,7 +238,7 @@ public static function get_module(int $moduleid, int $userid) : array { // Determine module type. $type = self::determin_type($module->name); - if ($type == self::TYPE_NONE) { + if ($type == MODULE_TYPE::NONE) { return array(); } // Check if there are any submissions or feedbacks for this module. @@ -310,7 +276,7 @@ public static function get_module(int $moduleid, int $userid) : array { $moduleboundaries->gradepass ); - $done = $grade != self::GRADE_RIP; + $done = $grade != MODULE_GRADE::RIP; } } // Check if the module is late. @@ -354,7 +320,7 @@ public static function get_all_course_modules(int $courseid, int $userid, bool $ $modules = array(); foreach ($mdlmodules as $mdlmodule) { - if (!$ekenabled && self::determin_type($mdlmodule->name) == self::TYPE_EK) { + if (!$ekenabled && self::determin_type($mdlmodule->name) == MODULE_TYPE::EK) { continue; } $module = self::get_module($mdlmodule->id, $userid); diff --git a/lbplanner/classes/helpers/notifications_helper.php b/lbplanner/classes/helpers/notifications_helper.php index 82cd48c5..0427eb60 100644 --- a/lbplanner/classes/helpers/notifications_helper.php +++ b/lbplanner/classes/helpers/notifications_helper.php @@ -19,6 +19,27 @@ use external_single_structure; use external_value; +// TODO: revert to native enums once we migrate to php8 + +use local_lbplanner\polyfill\Enum; + +/** + * Stati a notification can be in + */ +class NOTIF_STATUS extends Enum { + const UNREAD = 0; + const READ = 1; +} + +class NOTIF_TRIGGER extends Enum { + const INVITE = 0; + const INVITE_ACCEPTED = 1; + const INVITE_DECLINED = 2; + const PLAN_LEFT = 3; + const PLAN_REMOVED = 4; + const USER_REGISTERED = 5; +} + /** * Provides helper methods for notification related stuff. */ @@ -28,62 +49,19 @@ class notifications_helper { */ const LBPLANNER_NOTIFICATION_TABLE = 'local_lbplanner_notification'; - /** - * Enum value for a read notification. - */ - const STATUS_READ = 1; - - /** - * Enum value for a unread notification. - */ - const STATUS_UNREAD = 0; - - /** - * Enum value for a notification triggered by an invitation. - */ - const TRIGGER_INVITE = 0; - - /** - * Enum value for a notification triggered by an acceptation of an invitation. - */ - const TRIGGER_INVITE_ACCEPTED = 1; - - /** - * Enum value for a notification triggered by a rejection of an invitation. - */ - const TRIGGER_INVITE_DECLINED = 2; - - /** - * Enum value for a notification triggered by a user leaving a plan. - */ - const TRIGGER_PLAN_LEFT = 3; - - /** - * Enum value for a notification triggered by a user being removed from a plan. - */ - const TRIGGER_PLAN_REMOVED = 4; - - /** - * Enum value for a notification triggered by a new user. - */ - const TRIGGER_USER_REGISTERED = 5; - /** * @return external_single_structure The data structure of a module. */ public static function structure() : external_single_structure { - return new external_single_structure( - array( - 'moduleid' => new external_value(PARAM_INT, 'The id of the module'), - 'name' => new external_value(PARAM_TEXT, 'The name of the module'), - 'courseid' => new external_value(PARAM_INT, 'The id of the course'), - 'status' => new external_value(PARAM_INT, 'The status of the module'), - 'type' => new external_value(PARAM_INT, 'The type of the module'), - 'url' => new external_value(PARAM_TEXT, 'The url of the module in moodle'), - 'grade' => new external_value(PARAM_INT, 'The grade of the module'), - 'deadline' => new external_value(PARAM_INT, 'The deadline of the module set by the teacher'), - ) - ); + return new external_single_structure([ + 'status' => new external_value(PARAM_INT, 'The status of the notification '.NOTIF_STATUS::format()), + 'type' => new external_value(PARAM_INT, 'The type of the event that triggered the notification '.NOTIF_TRIGGER::format()), + 'info' => new external_value(PARAM_INT, 'Additional information about the notification'), + 'userid' => new external_value(PARAM_INT, 'The ID of the user for whom the notification is for'), + 'notificationid' => new external_value(PARAM_INT, 'The ID of the notification', NULL_NOT_ALLOWED), + 'timestamp' => new external_value(PARAM_INT, 'The timestamp of the notification'), + 'timestamp_read' => new external_value(PARAM_INT, 'The timestamp of the notification when it was read'), + ]); } /** @@ -101,7 +79,7 @@ public static function notify_user( int $userid, int $info, int $type ): int { $notification->userid = $userid; $notification->info = $info; $notification->type = $type; - $notification->status = self::STATUS_UNREAD; + $notification->status = NOTIF_STATUS::UNREAD; $notification->timestamp = time(); $notification->timestamp_read = null; diff --git a/lbplanner/classes/helpers/plan_helper.php b/lbplanner/classes/helpers/plan_helper.php index f0eb8c39..2f8675a8 100644 --- a/lbplanner/classes/helpers/plan_helper.php +++ b/lbplanner/classes/helpers/plan_helper.php @@ -19,7 +19,7 @@ use external_single_structure; use external_value; use external_multiple_structure; -use local_lbplanner\polyfill\enum; +use local_lbplanner\polyfill\Enum; // TODO: revert to native enums once we migrate to php8 @@ -31,9 +31,6 @@ class PLAN_ACCESS_TYPE extends Enum { const WRITE = 1; const READ = 2; const NONE = -1; - public static function get_classname(): string { - return __CLASS__; - } } /** @@ -42,9 +39,6 @@ public static function get_classname(): string { class PLAN_EK extends Enum { const DISABLED = 0; const ENABLED = 1; - public static function get_classname(): string { - return __CLASS__; - } } /** @@ -55,9 +49,6 @@ class PLAN_INVITE_STATE extends Enum { const ACCEPTED = 1; const DECLINED = 2; const EXPIRED = 3; - public static function get_classname(): string { - return __CLASS__; - } } /** @@ -130,9 +121,9 @@ public static function get_plan_id(int $userid):int { * * @param int $planid The id of the plan. * @param int $userid The id of the user. - * @return PLAN_ACCESS_TYPE The access type of the given user for the given plan. + * @return int The access type of the given user for the given plan. */ - public static function get_access_type(int $userid, int $planid): PLAN_ACCESS_TYPE { + public static function get_access_type(int $userid, int $planid): int { global $DB; $field = $DB->get_field( @@ -176,7 +167,6 @@ public static function get_deadlines(int $planid): array { foreach ($dbdeadlines as $dbdeadline) { $deadlines[] = array( - 'planid' => $dbdeadline->planid, 'deadlinestart' => $dbdeadline->deadlinestart, 'deadlineend' => $dbdeadline->deadlineend, 'moduleid' => $dbdeadline->moduleid, @@ -222,16 +212,15 @@ public static function get_plan(int $planid) : array { public static function plan_structure() : external_single_structure { return new external_single_structure( array( - 'name' => new external_value(PARAM_TEXT, 'The name of the plan'), - 'planid' => new external_value(PARAM_INT, 'The id of the plan'), - 'enableek' => new external_value(PARAM_BOOL, 'If the plan is enabled for ek'), + 'name' => new external_value(PARAM_TEXT, 'Name of the plan'), + 'planid' => new external_value(PARAM_INT, 'ID of the plan'), + 'enableek' => new external_value(PARAM_BOOL, 'Whether EK is enabled'), 'deadlines' => new external_multiple_structure( new external_single_structure( array( - 'planid' => new external_value(PARAM_INT, 'The id of the user'), - 'moduleid' => new external_value(PARAM_INT, 'The id of the user'), - 'deadlinestart' => new external_value(PARAM_INT, 'The id of the user'), - 'deadlineend' => new external_value(PARAM_INT, 'The id of the user'), + 'moduleid' => new external_value(PARAM_INT, 'ID of the module'), + 'deadlinestart' => new external_value(PARAM_INT, 'Start of the deadline as an UNIX timestamp'), + 'deadlineend' => new external_value(PARAM_INT, 'End of the deadline as an UNIX timestamp'), ) ) ), @@ -239,7 +228,7 @@ public static function plan_structure() : external_single_structure { new external_single_structure( array( 'userid' => new external_value(PARAM_INT, 'The id of the user'), - 'accesstype' => new external_value(PARAM_INT, 'The role of the user'), + 'accesstype' => new external_value(PARAM_INT, 'The role of the user '.PLAN_ACCESS_TYPE::format()), ) ) ), @@ -267,11 +256,9 @@ public static function copy_plan(int $planid, int $userid) : int { $newplanid = $DB->insert_record(self::TABLE, $plan); - // Had to do it with insert and then update because the Variable didnt change in the Loop. - // I don't know why. It just works, so dont touch it 🚧. foreach ($deadlines as $deadline) { - $id = $DB->insert_record(self::DEADLINES_TABLE, $deadline); - $DB->update_record(self::DEADLINES_TABLE, array('id' => $id, 'planid' => $newplanid)); + $deadline['planid'] = $newplanid; + $DB->insert_record(self::DEADLINES_TABLE, $deadline); } return $newplanid; } diff --git a/lbplanner/classes/polyfill/enum.php b/lbplanner/classes/polyfill/enum.php index 8b6d9c01..7bb1d15e 100644 --- a/lbplanner/classes/polyfill/enum.php +++ b/lbplanner/classes/polyfill/enum.php @@ -16,32 +16,71 @@ namespace local_lbplanner\polyfill; +use ReflectionClass; use ValueError; abstract class Enum { /** * tries to match the passed value to one of the enum values - * @param $value the value to be matched - * @return either the matching enum value or null if not found + * @param mixed $value the value to be matched + * @return mixed either the matching enum value or null if not found */ - public static function tryFrom(mixed $value): ?mixed { - $cases = get_class_vars(static::get_classname()); - return in_array($value,$cases,true) ? $value : null; + public static function tryFrom(mixed $value): mixed { + $cases = static::cases(); + foreach($cases as $case){ + if($case->value === $value) + return $value; + } + return null; } /** * tries to match the passed value to one of the enum values - * @param $value the value to be matched - * @return the matching enum value + * @param mixed $value the value to be matched + * @return mixed the matching enum value * @throws ValueError if not found */ public static function from(mixed $value): mixed { - $cases = get_class_vars(static::get_classname()); - - if(!in_array($value,$cases,true)){ - throw new ValueError("value {$value} cannot be represented as a value in enum ".static::get_classname()); + $cases = static::cases(); + foreach($cases as $case){ + if($case->value === $value) + return $value; } - return $value; + throw new ValueError("value {$value} cannot be represented as a value in enum ".static::class); + } + /** + * @return EnumCase[] array of cases inside this enum + */ + public static function cases(): array { + $reflection = new ReflectionClass(static::class); + $cases = []; + foreach($reflection->getConstants() as $name=>$val){ + array_push($cases,new EnumCase($name,$val)); + } + return $cases; + } + /** + * Formats all possible enum values into a string + * Example: + * (31=>RED,32=>GREEN,33=>YELLOW) + * @return string the resulting string + */ + public static function format(): string { + $result = "["; + $cases = static::cases(); + foreach($cases as $case) { + $result .= "{$case->value}=>{$case->name},"; + } + $result[-1] = ']'; + return $result; + } +} + +class EnumCase { + public string $name; + public mixed $value; + public function __construct($name,$value){ + $this->name = $name; + $this->value = $value; } - public abstract static function get_classname(): string; } \ No newline at end of file diff --git a/lbplanner/db/services.php b/lbplanner/db/services.php index 21abf676..59266a47 100644 --- a/lbplanner/db/services.php +++ b/lbplanner/db/services.php @@ -153,15 +153,6 @@ 'capabilities' => 'local/lb_planner:student', 'ajax' => true, ), - 'local_lbplanner_plan_add_deadline' => array( - 'classname' => 'local_lbplanner_services\plan_add_deadline', - 'methodname' => 'add_deadline', - 'classpath' => 'local/lbplanner/services/plan/add_deadline.php', - 'description' => 'Add a deadline to the plan', - 'type' => 'write', - 'capabilities' => 'local/lb_planner:student', - 'ajax' => true, - ), 'local_lbplanner_plan_delete_deadline' => array( 'classname' => 'local_lbplanner_services\plan_delete_deadline', 'methodname' => 'delete_deadline', @@ -180,11 +171,11 @@ 'capabilities' => 'local/lb_planner:student', 'ajax' => true, ), - 'local_lbplanner_plan_update_deadline' => array( - 'classname' => 'local_lbplanner_services\plan_update_deadline', - 'methodname' => 'update_deadline', - 'classpath' => 'local/lbplanner/services/plan/update_deadline.php', - 'description' => 'Update a deadline from the plan', + 'local_lbplanner_plan_set_deadline' => array( + 'classname' => 'local_lbplanner_services\plan_set_deadline', + 'methodname' => 'set_deadline', + 'classpath' => 'local/lbplanner/services/plan/set_deadline.php', + 'description' => 'Set a deadline from the plan', 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, diff --git a/lbplanner/services/feedback/delete_feedback.php b/lbplanner/services/feedback/delete_feedback.php index 49898fde..ac42f5a1 100644 --- a/lbplanner/services/feedback/delete_feedback.php +++ b/lbplanner/services/feedback/delete_feedback.php @@ -28,7 +28,7 @@ class feedback_delete_feedback extends external_api { public static function delete_feedback_parameters() { return new external_function_parameters([ - 'feedbackid' => new external_value(PARAM_INT, 'The id of the course', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + 'feedbackid' => new external_value(PARAM_INT, 'ID of the feedback to delete', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), ]); } diff --git a/lbplanner/services/feedback/submit_feedback.php b/lbplanner/services/feedback/submit_feedback.php index fb40ca97..47b6cdd2 100644 --- a/lbplanner/services/feedback/submit_feedback.php +++ b/lbplanner/services/feedback/submit_feedback.php @@ -28,9 +28,9 @@ class feedback_submit_feedback extends external_api { public static function submit_feedback_parameters() { return new external_function_parameters( [ - 'type' => new external_value(PARAM_INT, 'The type ', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'content' => new external_value(PARAM_TEXT, 'The content of the feedback', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'logfile' => new external_value(PARAM_TEXT, 'The name of the logfile', VALUE_DEFAULT, null, NULL_NOT_ALLOWED ), + 'type' => new external_value(PARAM_INT, 'type of Feedback (bug, typo, feature, other)', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + 'content' => new external_value(PARAM_TEXT, 'feedback contents', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + 'logfile' => new external_value(PARAM_TEXT, 'file name of the associated log file', VALUE_DEFAULT, null, NULL_NOT_ALLOWED ), ] ); } diff --git a/lbplanner/services/feedback/update_feedback.php b/lbplanner/services/feedback/update_feedback.php index 81221a5a..dd7a9168 100644 --- a/lbplanner/services/feedback/update_feedback.php +++ b/lbplanner/services/feedback/update_feedback.php @@ -28,9 +28,9 @@ class feedback_update_feedback extends external_api { public static function update_feedback_parameters() { return new external_function_parameters([ - 'feedbackid' => new external_value(PARAM_INT, 'The id of the course', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'notes' => new external_value(PARAM_TEXT, 'The notes of the feedback', VALUE_DEFAULT, null, NULL_ALLOWED), - 'status' => new external_value(PARAM_INT, 'The status of the feedback', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + 'feedbackid' => new external_value(PARAM_INT, 'ID of the feedback to be updated', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + 'notes' => new external_value(PARAM_TEXT, 'updated notes', VALUE_DEFAULT, null, NULL_ALLOWED), + 'status' => new external_value(PARAM_INT, 'updated status', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), ]); } diff --git a/lbplanner/services/notifications/update_notification.php b/lbplanner/services/notifications/update_notification.php index 34db9751..106f830e 100644 --- a/lbplanner/services/notifications/update_notification.php +++ b/lbplanner/services/notifications/update_notification.php @@ -29,12 +29,12 @@ public static function update_notification_parameters() { return new external_function_parameters([ 'status' => new external_value( PARAM_INT, - 'The status of the notification {0: unread, 1: read}', + 'notification status {0: unread, 1: read}', VALUE_REQUIRED, null, NULL_NOT_ALLOWED ), - 'notificationid' => new external_value(PARAM_INT, 'The ID of the notification', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + 'notificationid' => new external_value(PARAM_INT, 'ID of the notification to be updated', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), ]); } diff --git a/lbplanner/services/plan/accept_invite.php b/lbplanner/services/plan/accept_invite.php index 60b2c6d3..4540a4cd 100644 --- a/lbplanner/services/plan/accept_invite.php +++ b/lbplanner/services/plan/accept_invite.php @@ -23,14 +23,15 @@ use local_lbplanner\helpers\notifications_helper; use local_lbplanner\helpers\PLAN_ACCESS_TYPE; use local_lbplanner\helpers\PLAN_INVITE_STATE; +use local_lbplanner\helpers\NOTIF_TRIGGER; /** - * Update a invite from the plan. + * Accept an invite to the plan. */ class plan_accept_invite extends external_api { public static function accept_invite_parameters() { return new external_function_parameters([ - 'inviteid' => new external_value(PARAM_INT, 'The id of the plan', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + 'inviteid' => new external_value(PARAM_INT, 'the ID of the invite to be accepted', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), ]); } @@ -63,7 +64,7 @@ public static function accept_invite($inviteid) { notifications_helper::notify_user( $invite->inviterid, $invite->id, - notifications_helper::TRIGGER_INVITE_ACCEPTED + NOTIF_TRIGGER::INVITE_ACCEPTED ); // Deletes the old plan if the user is the owner of it. diff --git a/lbplanner/services/plan/decline_invite.php b/lbplanner/services/plan/decline_invite.php index d5b550d9..8f787b07 100644 --- a/lbplanner/services/plan/decline_invite.php +++ b/lbplanner/services/plan/decline_invite.php @@ -19,6 +19,7 @@ use external_api; use external_function_parameters; use external_value; +use local_lbplanner\helpers\NOTIF_TRIGGER; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; use local_lbplanner\helpers\PLAN_INVITE_STATE; @@ -29,7 +30,7 @@ class plan_decline_invite extends external_api { public static function decline_invite_parameters() { return new external_function_parameters([ - 'inviteid' => new external_value(PARAM_INT, 'The inviteid of the plan', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + 'inviteid' => new external_value(PARAM_INT, 'the ID of the invite to be declined', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), ]); } @@ -61,7 +62,7 @@ public static function decline_invite($inviteid) { notifications_helper::notify_user( $invite->inviterid, $invite->id, - notifications_helper::TRIGGER_INVITE_DECLINED + NOTIF_TRIGGER::INVITE_DECLINED ); $invite->status = PLAN_INVITE_STATE::DECLINED; diff --git a/lbplanner/services/plan/delete_deadline.php b/lbplanner/services/plan/delete_deadline.php index 3c6e995d..94b4db70 100644 --- a/lbplanner/services/plan/delete_deadline.php +++ b/lbplanner/services/plan/delete_deadline.php @@ -29,7 +29,7 @@ public static function delete_deadline_parameters() { return new external_function_parameters([ 'moduleid' => new external_value( PARAM_INT, - 'The ID of the Module', + 'ID of the Module', VALUE_REQUIRED, null, NULL_NOT_ALLOWED @@ -56,7 +56,7 @@ public static function delete_deadline($moduleid) { $DB->delete_records( plan_helper::DEADLINES_TABLE, [ - 'planid' => $planid , + 'planid' => $planid, 'moduleid' => $moduleid, ] ); diff --git a/lbplanner/services/plan/invite_user.php b/lbplanner/services/plan/invite_user.php index f4aa3bbc..065c5398 100644 --- a/lbplanner/services/plan/invite_user.php +++ b/lbplanner/services/plan/invite_user.php @@ -20,6 +20,7 @@ use external_function_parameters; use external_value; use local_lbplanner\helpers\invite_helper; +use local_lbplanner\helpers\NOTIF_TRIGGER; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; use local_lbplanner\helpers\PLAN_INVITE_STATE; @@ -32,7 +33,7 @@ public static function invite_user_parameters() { return new external_function_parameters([ 'inviteeid' => new external_value( PARAM_INT, - 'The id of the user who gets invited', + 'ID of the user who gets invited', VALUE_REQUIRED, null, NULL_NOT_ALLOWED @@ -83,7 +84,7 @@ public static function invite_user($inviteeid) { notifications_helper::notify_user( $inviteeid, $invite->id, - notifications_helper::TRIGGER_INVITE + NOTIF_TRIGGER::INVITE ); return $invite; diff --git a/lbplanner/services/plan/leave_plan.php b/lbplanner/services/plan/leave_plan.php index 9adaf28f..9253ee8a 100644 --- a/lbplanner/services/plan/leave_plan.php +++ b/lbplanner/services/plan/leave_plan.php @@ -18,6 +18,7 @@ use external_api; use external_function_parameters; +use local_lbplanner\helpers\NOTIF_TRIGGER; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; use local_lbplanner\helpers\PLAN_ACCESS_TYPE; @@ -96,7 +97,7 @@ public static function leave_plan() { notifications_helper::notify_user( plan_helper::get_owner($planid), $USER->id, - notifications_helper::TRIGGER_PLAN_LEFT + NOTIF_TRIGGER::PLAN_LEFT ); } public static function leave_plan_returns() { diff --git a/lbplanner/services/plan/remove_user.php b/lbplanner/services/plan/remove_user.php index 4129e6b0..c18a751c 100644 --- a/lbplanner/services/plan/remove_user.php +++ b/lbplanner/services/plan/remove_user.php @@ -27,7 +27,7 @@ class plan_remove_user extends external_api { public static function remove_user_parameters() { return new external_function_parameters([ - 'userid' => new external_value(PARAM_INT, 'The id of the user to remove', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + 'userid' => new external_value(PARAM_INT, 'ID of the user to remove', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), ]); } diff --git a/lbplanner/services/plan/update_access.php b/lbplanner/services/plan/update_access.php index 33c2b814..5c8eea72 100644 --- a/lbplanner/services/plan/update_access.php +++ b/lbplanner/services/plan/update_access.php @@ -30,14 +30,14 @@ public static function update_access_parameters() { return new external_function_parameters([ 'accesstype' => new external_value( PARAM_INT, - 'The access type', + 'New access type', VALUE_REQUIRED, null, NULL_NOT_ALLOWED ), 'memberid' => new external_value( PARAM_INT, - 'The id of the member', + 'ID of the member to have their access changed', VALUE_REQUIRED, null, NULL_NOT_ALLOWED diff --git a/lbplanner/services/plan/update_plan.php b/lbplanner/services/plan/update_plan.php index a2937f90..63418e1f 100644 --- a/lbplanner/services/plan/update_plan.php +++ b/lbplanner/services/plan/update_plan.php @@ -29,14 +29,14 @@ public static function update_plan_parameters() { return new external_function_parameters([ 'planname' => new external_value( PARAM_TEXT, - 'The Name of the Plan', + 'Name of the Plan', VALUE_REQUIRED, null, NULL_NOT_ALLOWED ), 'enableek' => new external_value( PARAM_BOOL, - 'If the plan is enabled for ek', + 'Whether EK is enabled for the plan', VALUE_REQUIRED, null, NULL_NOT_ALLOWED diff --git a/lbplanner/services/user/register_user.php b/lbplanner/services/user/register_user.php index 27860ac7..ed405792 100644 --- a/lbplanner/services/user/register_user.php +++ b/lbplanner/services/user/register_user.php @@ -22,6 +22,7 @@ use external_single_structure; use external_value; use invalid_parameter_exception; +use local_lbplanner\helpers\NOTIF_TRIGGER; use local_lbplanner\helpers\PLAN_ACCESS_TYPE; use local_lbplanner\helpers\PLAN_EK; use local_lbplanner\helpers\user_helper; @@ -111,7 +112,7 @@ public static function register_user(string $lang, string $theme): array { $DB->insert_record(plan_helper::ACCESS_TABLE, $planaccess); - notifications_helper::notify_user($userid, -1, notifications_helper::TRIGGER_USER_REGISTERED); + notifications_helper::notify_user($userid, -1, NOTIF_TRIGGER::USER_REGISTERED); return [ 'userid' => $lbplanneruser->userid, From ec456269cae1096056a093b972a98286dc7652d3 Mon Sep 17 00:00:00 2001 From: Riedler Date: Fri, 9 Feb 2024 14:15:37 +0100 Subject: [PATCH 22/92] LP-208: fix remaining CI errors (#72) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit may god have mercy upon us all * updated feedback API docs * improved docs in notification service * updated API docs for invite subservice * updated API docs for deadline subservice * updated API docs for the rest of the plan service * api docs corrections * changes to enum for upcoming changes to api docs * added another helper just to list enum cases inside the API docs * added capability to format Enum class to string * restructured modules helper with new Enum polyfills * restructured notification helper with Enums & fixed API docs * replaced duplicate code with better newer implementation * banished tab indents (oops) * replaced all array(…) with […] * hopefully convince github CI to run * appeased the moodle linter gods * added moodle internal checks where needed * removed some unnecessary variable declarations * some smaller formatting fixes * added blocks to previously inline code branches * renamed Enum::tryFrom to Enum::try_from * added more space around ifs, as per the bitch called moodle code checker's request * increase max linter warnings to 1 to allow my enum polyfill to exist * various minor code comment fixes for phpdoc linter * testing correct phpdoc package tag * added crude phpdoc-compliant-ish class docstrings to helper classes * docstringed modules helper * docstringed notifications helper * docstringed plan helper * various smaller fixes * helpers: replaced param types with shortforms * docstring enum polyfill * docstringed plan helper * docstringed course helper * docstringed feedback_helper * some smaller docstring fixes * added file-level docstring to settings.php * completed docstrings of service files * fixed some incorrect docblocks * fixed phpdoc errors in db submodule * Revert to normal CI This reverts commit fe9a5f4b0e57d62a5f70a3d7ec9183f932b6326f. * fixed CI regression from merge * fixed docblocks in services/modules * fixed docblocks in services/plan * fixed docblocks in services/feedback * fixed docblocks in services/config * fixed docblocks in services/notifications * fixed remaining CI errors --- .github/workflows/gha.dist.yml | 2 +- lbplanner/classes/helpers/config_helper.php | 12 ++ lbplanner/classes/helpers/course_helper.php | 20 ++- lbplanner/classes/helpers/feedback_helper.php | 32 +++- lbplanner/classes/helpers/invite_helper.php | 13 +- lbplanner/classes/helpers/modules_helper.php | 113 ++++++++++---- .../classes/helpers/notifications_helper.php | 54 ++++++- lbplanner/classes/helpers/plan_helper.php | 126 ++++++++++----- lbplanner/classes/helpers/user_helper.php | 6 +- lbplanner/classes/polyfill/enum.php | 147 ++++++++++-------- lbplanner/db/access.php | 30 ++-- lbplanner/db/install.php | 14 +- lbplanner/db/services.php | 146 ++++++++--------- lbplanner/db/upgrade.php | 17 +- lbplanner/lang/en/local_lbplanner.php | 9 +- lbplanner/services/config/get_version.php | 36 +++-- .../services/courses/get_all_courses.php | 4 +- lbplanner/services/courses/update_course.php | 6 +- .../services/feedback/delete_feedback.php | 24 ++- .../services/feedback/get_all_feedbacks.php | 22 ++- .../services/feedback/submit_feedback.php | 54 ++++++- .../services/feedback/update_feedback.php | 32 +++- .../modules/get_all_course_modules.php | 33 +++- .../services/modules/get_all_modules.php | 37 +++-- lbplanner/services/modules/get_module.php | 35 ++++- .../notifications/get_all_notifications.php | 26 +++- .../notifications/update_notification.php | 31 +++- lbplanner/services/plan/accept_invite.php | 25 ++- lbplanner/services/plan/clear_plan.php | 21 ++- lbplanner/services/plan/decline_invite.php | 25 ++- lbplanner/services/plan/delete_deadline.php | 24 ++- lbplanner/services/plan/get_invites.php | 24 ++- lbplanner/services/plan/get_plan.php | 25 ++- lbplanner/services/plan/invite_user.php | 28 +++- lbplanner/services/plan/leave_plan.php | 24 ++- lbplanner/services/plan/remove_user.php | 23 ++- lbplanner/services/plan/set_deadline.php | 38 ++++- lbplanner/services/plan/update_access.php | 30 +++- lbplanner/services/plan/update_plan.php | 27 +++- lbplanner/services/user/delete_user.php | 8 +- lbplanner/services/user/get_all_users.php | 7 +- lbplanner/services/user/get_user.php | 8 +- lbplanner/services/user/register_user.php | 9 +- lbplanner/services/user/update_user.php | 7 +- lbplanner/settings.php | 7 + lbplanner/version.php | 7 + 46 files changed, 1104 insertions(+), 344 deletions(-) diff --git a/.github/workflows/gha.dist.yml b/.github/workflows/gha.dist.yml index f8913737..821e97b1 100644 --- a/.github/workflows/gha.dist.yml +++ b/.github/workflows/gha.dist.yml @@ -87,7 +87,7 @@ jobs: - name: Moodle Code Checker if: ${{ always() }} - run: moodle-plugin-ci phpcs --max-warnings 0 + run: moodle-plugin-ci phpcs --max-warnings 1 - name: Moodle PHPDoc Checker if: ${{ always() }} diff --git a/lbplanner/classes/helpers/config_helper.php b/lbplanner/classes/helpers/config_helper.php index e64fd382..7261a3c7 100644 --- a/lbplanner/classes/helpers/config_helper.php +++ b/lbplanner/classes/helpers/config_helper.php @@ -16,9 +16,21 @@ namespace local_lbplanner\helpers; +/** + * Helper class for config + * + * @package local_lbplanner + * @subpackage helpers + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ class config_helper { + /** + * Sets the current active year + */ public static function set_default_active_year() { $currentmonth = idate('m'); + // TODO: At least one of these comments ↓ is clearly wrong. Muhi's thing to fix. if ($currentmonth >= 8 && $currentmonth <= 12) { // Adding the default active year, when the plugin is installed for the first time. set_config( diff --git a/lbplanner/classes/helpers/course_helper.php b/lbplanner/classes/helpers/course_helper.php index f6792e0d..b2219af2 100644 --- a/lbplanner/classes/helpers/course_helper.php +++ b/lbplanner/classes/helpers/course_helper.php @@ -23,14 +23,21 @@ /** * Helper class for courses * - * @package local_lbplanner_helpers - * @copyright 2023 NecodeIT + * @package local_lbplanner + * @subpackage helpers + * @copyright 2024 NecodeIT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class course_helper { + /** + * The course table used by the LP + */ const LBPLANNER_COURSE_TABLE = 'local_lbplanner_courses'; + /** + * A list of nice colors to choose from :) + */ const COLORS = [ "#f50057", "#536dfe", @@ -48,7 +55,13 @@ class course_helper { "#8B37CA", "#CA37B9", ]; + /** + * constant that represents a disabled course + */ const DISABLED_COURSE = 0; + /** + * constant that represents an enabled course + */ const ENABLED_COURSE = 1; /** @@ -70,10 +83,11 @@ public static function get_current_year() : string { * Get course from lbpanner DB * * @param int $courseid id of the course in lbplanner + * @param int $userid id of the user * @return stdClass course from lbplanner * @throws dml_exception */ - public static function get_lbplanner_course(int $courseid, $userid) : stdClass { + public static function get_lbplanner_course(int $courseid, int $userid) : stdClass { global $DB; return $DB->get_record(self::LBPLANNER_COURSE_TABLE, ['courseid' => $courseid, 'userid' => $userid]); } diff --git a/lbplanner/classes/helpers/feedback_helper.php b/lbplanner/classes/helpers/feedback_helper.php index ceaa739c..0473277d 100644 --- a/lbplanner/classes/helpers/feedback_helper.php +++ b/lbplanner/classes/helpers/feedback_helper.php @@ -22,13 +22,32 @@ use stdClass; use local_lbplanner\helpers\user_helper; +// TODO: use enums. + +/** + * Helper class for feedback + * + * @package local_lbplanner + * @subpackage helpers + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ class feedback_helper { + /** + * Unread Feedback + */ const STATUS_UNREAD = 0; + /** + * Read Feedback + */ const STATUS_READ = 1; + /** + * The name of the table which is used by LP to store feedback in + */ const LBPLANNER_FEEDBACK_TABLE = 'local_lbplanner_feedback'; /** @@ -38,7 +57,7 @@ class feedback_helper { */ public static function structure() : external_single_structure { return new external_single_structure( - array( + [ 'content' => new external_value(PARAM_TEXT, 'Content of the feedback'), 'userid' => new external_value(PARAM_INT, 'The id of the user'), 'type' => new external_value(PARAM_INT, 'The Type of the feedback'), @@ -49,13 +68,13 @@ public static function structure() : external_single_structure { 'lastmodified' => new external_value(PARAM_INT, 'The time when the feedback was last modified'), 'lastmodifiedby' => new external_value(PARAM_INT, 'The id of the user who last modified the feedback'), 'logfile' => new external_value(PARAM_TEXT, 'The logs of the feedback'), - ) + ] ); } /** * Gives back the feedback of the given feedbackid * - * @param integer $feedbackid The id of the feedback + * @param int $feedbackid The id of the feedback * @return stdClass The feedback */ public static function get_feedback(int $feedbackid) : stdClass { @@ -65,8 +84,7 @@ public static function get_feedback(int $feedbackid) : stdClass { /** * Checks if the user has access to feedback * - * @param integer $userid The id of the user - * @return void Throws an exception if the user has no access + * @throws \moodle_exception when the user has no access */ public static function assert_admin_access() { if (!has_capability(user_helper::CAPABILITY_ADMIN, \context_system::instance()) && @@ -75,6 +93,10 @@ public static function assert_admin_access() { } } + /** + * Returns all feedback records. + * @return array all feedback records + */ public static function get_all_feedbacks() : array { global $DB; return $DB->get_records(self::LBPLANNER_FEEDBACK_TABLE); diff --git a/lbplanner/classes/helpers/invite_helper.php b/lbplanner/classes/helpers/invite_helper.php index 7a5a9cbc..a90c8e41 100644 --- a/lbplanner/classes/helpers/invite_helper.php +++ b/lbplanner/classes/helpers/invite_helper.php @@ -19,9 +19,18 @@ use external_single_structure; use external_value; +/** + * Helper class for plan invites + * + * @package local_lbplanner + * @subpackage helpers + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ class invite_helper { - /** + /** + * Returns the data structure of an invite. * @return external_single_structure The data structure of an invite. */ public static function structure() : external_single_structure { @@ -36,4 +45,4 @@ public static function structure() : external_single_structure { ] ); } -} \ No newline at end of file +} diff --git a/lbplanner/classes/helpers/modules_helper.php b/lbplanner/classes/helpers/modules_helper.php index 2be78601..be7120c6 100644 --- a/lbplanner/classes/helpers/modules_helper.php +++ b/lbplanner/classes/helpers/modules_helper.php @@ -13,9 +13,19 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * Collection of helper classes for handling modules + * + * @package local_lbplanner + * @subpackage helpers + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ namespace local_lbplanner\helpers; +defined('MOODLE_INTERNAL') || die(); + use block_accessreview\external\get_module_data; use external_function_parameters; use external_single_structure; @@ -25,15 +35,27 @@ use local_lbplanner\polyfill\Enum; -// TODO: revert to native enums once we migrate to php8 +// TODO: revert to native enums once we migrate to php8. /** * Stati a module can be in */ class MODULE_STATUS extends Enum { + /** + * Finished module. + */ const DONE = 0; + /** + * Uploaded module. + */ const UPLOADED = 1; + /** + * Overdue module. + */ const LATE = 2; + /** + * Todo module. + */ const PENDING = 3; } @@ -41,10 +63,25 @@ class MODULE_STATUS extends Enum { * Grades a module can receive */ class MODULE_GRADE extends Enum { + /** + * Erweiterte Kompetenz vollständig. + */ const EKV = 0; + /** + * Erweiterte Kompetenz überwiegend. + */ const EK = 1; + /** + * Grundlegende Kompetenz vollständig. + */ const GKV = 2; + /** + * Grundlegende Kompetenz überwiegend. + */ const GK = 3; + /** + * Negative grade. + */ const RIP = 4; } @@ -52,10 +89,25 @@ class MODULE_GRADE extends Enum { * Module Types */ class MODULE_TYPE extends Enum { + /** + * Grundlegende Kompetenz. + */ const GK = 0; + /** + * Erweiterte Kompetenz. + */ const EK = 1; + /** + * Test i.e. exam. + */ const TEST = 2; + /** + * TODO: ??? + */ const M = 3; + /** + * TODO: ??? + */ const NONE = 4; } @@ -106,7 +158,7 @@ class modules_helper { */ public static function structure() : external_single_structure { return new external_single_structure( - array( + [ 'moduleid' => new external_value(PARAM_INT, 'Module ID'), 'name' => new external_value(PARAM_TEXT, 'Shortened module name (max. 5 chars)'), 'courseid' => new external_value(PARAM_INT, 'Course ID'), @@ -115,17 +167,17 @@ public static function structure() : external_single_structure { 'url' => new external_value(PARAM_TEXT, 'URL to moodle page for module'), 'grade' => new external_value(PARAM_INT, 'The grade of the module '.MODULE_GRADE::format()), 'deadline' => new external_value(PARAM_INT, 'The deadline of the module set by the teacher'), - ) + ] ); } /** * Determins the enum value for a grade. * - * @param integer $grade The grade of the module. - * @param integer $maxgrade The max. grade of the module. - * @param integer $mingrade The min. grade of the module. - * @param integer $gradepass The grade to pass the module. + * @param int $grade The grade of the module. + * @param int $maxgrade The max. grade of the module. + * @param int $mingrade The min. grade of the module. + * @param int $gradepass The grade to pass the module. * @return integer The enum value for the grade. */ public static function determin_uinified_grade(int $grade, int $maxgrade, int $mingrade, int $gradepass) : int { @@ -153,9 +205,9 @@ public static function determin_uinified_grade(int $grade, int $maxgrade, int $m /** * Maps the given info to a module status. * - * @param boolean $submitted Whether the module is submitted. - * @param boolean $done Whether the module is completed. - * @param boolean $late Whether the module is late. + * @param bool $submitted Whether the module is submitted. + * @param bool $done Whether the module is completed. + * @param bool $late Whether the module is late. * @return integer The enum value for the module status. */ public static function map_status(bool $submitted, bool $done, bool $late) : int { @@ -206,8 +258,8 @@ public static function determin_type(string $modulename) : int { /** * Returns the url of the module. * - * @param integer $moduleid The id of the module. - * @param integer $courseid The id of the course. + * @param int $moduleid The id of the module. + * @param int $courseid The id of the course. * @return string The url of the module. */ public static function get_module_url(int $moduleid, int $courseid) : string { @@ -215,7 +267,7 @@ public static function get_module_url(int $moduleid, int $courseid) : string { $view = $DB->get_record( self::COURSE_MODULES_TABLE, - array('course' => $courseid, 'instance' => $moduleid, 'module' => 1) + ['course' => $courseid, 'instance' => $moduleid, 'module' => 1] ); return strval(new moodle_url('/mod/assign/view.php?id='.$view->id)); @@ -224,8 +276,8 @@ public static function get_module_url(int $moduleid, int $courseid) : string { /** * Retrieves a module of the given id for the given user. * - * @param integer $moduleid The id of the module. - * @param integer $userid The id of the user. + * @param int $moduleid The id of the module. + * @param int $userid The id of the user. * @return array The module. */ public static function get_module(int $moduleid, int $userid) : array { @@ -233,22 +285,22 @@ public static function get_module(int $moduleid, int $userid) : array { date_default_timezone_set('UTC'); // Get module data. - $module = $DB->get_record(self::ASSIGN_TABLE, array('id' => $moduleid)); + $module = $DB->get_record(self::ASSIGN_TABLE, ['id' => $moduleid]); // Determine module type. $type = self::determin_type($module->name); if ($type == MODULE_TYPE::NONE) { - return array(); + return []; } // Check if there are any submissions or feedbacks for this module. $submitted = false; - if ($DB->record_exists(self::SUBMISSIONS_TABLE, array('assignment' => $moduleid, 'userid' => $userid))) { + if ($DB->record_exists(self::SUBMISSIONS_TABLE, ['assignment' => $moduleid, 'userid' => $userid])) { $submission = $DB->get_record( self::SUBMISSIONS_TABLE, - array('assignment' => $moduleid, 'userid' => $userid) + ['assignment' => $moduleid, 'userid' => $userid] ); $submitted = strval($submission->status) == self::SUBMISSION_STATUS_SUBMITTED; @@ -257,12 +309,12 @@ public static function get_module(int $moduleid, int $userid) : array { $done = false; $grade = null; - if ($DB->record_exists(self::GRADES_TABLE, array('assignment' => $moduleid, 'userid' => $userid))) { - $moduleboundaries = $DB->get_record(self::GRADE_ITEMS_TABLE, array('iteminstance' => $moduleid)); + if ($DB->record_exists(self::GRADES_TABLE, ['assignment' => $moduleid, 'userid' => $userid])) { + $moduleboundaries = $DB->get_record(self::GRADE_ITEMS_TABLE, ['iteminstance' => $moduleid]); $mdlgrades = $DB->get_records( self::GRADES_TABLE, - array('assignment' => $moduleid, 'userid' => $userid) + ['assignment' => $moduleid, 'userid' => $userid] ); $mdlgrade = end($mdlgrades); @@ -284,8 +336,8 @@ public static function get_module(int $moduleid, int $userid) : array { $late = false; $planid = plan_helper::get_plan_id($userid); - if ($DB->record_exists(plan_helper::DEADLINES_TABLE, array('planid' => $planid, 'moduleid' => $moduleid))) { - $deadline = $DB->get_record(plan_helper::DEADLINES_TABLE, array('planid' => $planid, 'moduleid' => $moduleid)); + if ($DB->record_exists(plan_helper::DEADLINES_TABLE, ['planid' => $planid, 'moduleid' => $moduleid])) { + $deadline = $DB->get_record(plan_helper::DEADLINES_TABLE, ['planid' => $planid, 'moduleid' => $moduleid]); $late = intval(date("Ymd", $deadline->deadlineend)) < intval(date("Ymd")) && !$done; } @@ -293,7 +345,7 @@ public static function get_module(int $moduleid, int $userid) : array { // Return the appropriate data. - return array( + return [ 'moduleid' => $moduleid, 'name' => $module->name, 'courseid' => $module->course, @@ -302,22 +354,23 @@ public static function get_module(int $moduleid, int $userid) : array { 'url' => self::get_module_url($moduleid, $module->course), 'grade' => $grade, 'deadline' => $module->duedate > 0 ? $module->duedate : null, - ); + ]; } /** * Reteruns all modules for the given course id. * - * @param integer $courseid The id of the course. - * @param integer $userid The id of the user. + * @param int $courseid The id of the course. + * @param int $userid The id of the user. + * @param bool $ekenabled Whether EK modules should be included. * @return array The modules. */ public static function get_all_course_modules(int $courseid, int $userid, bool $ekenabled) : array { global $DB; - $mdlmodules = $DB->get_records(self::ASSIGN_TABLE, array('course' => $courseid)); + $mdlmodules = $DB->get_records(self::ASSIGN_TABLE, ['course' => $courseid]); - $modules = array(); + $modules = []; foreach ($mdlmodules as $mdlmodule) { if (!$ekenabled && self::determin_type($mdlmodule->name) == MODULE_TYPE::EK) { diff --git a/lbplanner/classes/helpers/notifications_helper.php b/lbplanner/classes/helpers/notifications_helper.php index 0427eb60..b81a9ec7 100644 --- a/lbplanner/classes/helpers/notifications_helper.php +++ b/lbplanner/classes/helpers/notifications_helper.php @@ -13,13 +13,23 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * Provides helper classes for notification related stuff + * + * @package local_lbplanner + * @subpackage helpers + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ namespace local_lbplanner\helpers; +defined('MOODLE_INTERNAL') || die(); + use external_single_structure; use external_value; -// TODO: revert to native enums once we migrate to php8 +// TODO: revert to native enums once we migrate to php8. use local_lbplanner\polyfill\Enum; @@ -27,21 +37,48 @@ * Stati a notification can be in */ class NOTIF_STATUS extends Enum { + /** + * unread notification + */ const UNREAD = 0; + /** + * read notification + */ const READ = 1; } +/** + * Possible triggers for sending a notification + */ class NOTIF_TRIGGER extends Enum { + /** + * Invitation sent + */ const INVITE = 0; + /** + * Invitation accepted + */ const INVITE_ACCEPTED = 1; + /** + * Invitation declined + */ const INVITE_DECLINED = 2; + /** + * User left the plan + */ const PLAN_LEFT = 3; + /** + * User got removed from the plan + */ const PLAN_REMOVED = 4; + /** + * User registered + */ const USER_REGISTERED = 5; } /** - * Provides helper methods for notification related stuff. + * Provides helper methods for notification related stuff */ class notifications_helper { /** @@ -50,12 +87,15 @@ class notifications_helper { const LBPLANNER_NOTIFICATION_TABLE = 'local_lbplanner_notification'; /** - * @return external_single_structure The data structure of a module. + * Returns the data structure of a notification + * + * @return external_single_structure The data structure of a notification. */ public static function structure() : external_single_structure { return new external_single_structure([ 'status' => new external_value(PARAM_INT, 'The status of the notification '.NOTIF_STATUS::format()), - 'type' => new external_value(PARAM_INT, 'The type of the event that triggered the notification '.NOTIF_TRIGGER::format()), + 'type' => + new external_value(PARAM_INT, 'The type of the event that triggered the notification '.NOTIF_TRIGGER::format()), 'info' => new external_value(PARAM_INT, 'Additional information about the notification'), 'userid' => new external_value(PARAM_INT, 'The ID of the user for whom the notification is for'), 'notificationid' => new external_value(PARAM_INT, 'The ID of the notification', NULL_NOT_ALLOWED), @@ -67,9 +107,9 @@ public static function structure() : external_single_structure { /** * Notifies the given user about the given event, with the given info. * - * @param integer $userid The user to notify. - * @param integer $info Additional information as stringified json. - * @param integer $type The type of notification. + * @param int $userid The user to notify. + * @param int $info Additional information as stringified json. + * @param int $type The type of notification. * @return integer The id of the notification. */ public static function notify_user( int $userid, int $info, int $type ): int { diff --git a/lbplanner/classes/helpers/plan_helper.php b/lbplanner/classes/helpers/plan_helper.php index 2f8675a8..4970a1f5 100644 --- a/lbplanner/classes/helpers/plan_helper.php +++ b/lbplanner/classes/helpers/plan_helper.php @@ -13,23 +13,45 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * Provides helper classes for any tables related with the planning function of the app + * + * @package local_lbplanner + * @subpackage helpers + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ namespace local_lbplanner\helpers; +defined('MOODLE_INTERNAL') || die(); + use external_single_structure; use external_value; use external_multiple_structure; use local_lbplanner\polyfill\Enum; -// TODO: revert to native enums once we migrate to php8 +// TODO: revert to native enums once we migrate to php8. /** * Levels of access that a user can have for a plan */ class PLAN_ACCESS_TYPE extends Enum { + /** + * owning the plan + */ const OWNER = 0; + /** + * allowed to modify the plan + */ const WRITE = 1; + /** + * allowed to look at the plan + */ const READ = 2; + /** + * disallowed + */ const NONE = -1; } @@ -37,7 +59,13 @@ class PLAN_ACCESS_TYPE extends Enum { * Whether EK modules are enabled inside the planner */ class PLAN_EK extends Enum { + /** + * EK hidden + */ const DISABLED = 0; + /** + * EK visible + */ const ENABLED = 1; } @@ -45,14 +73,26 @@ class PLAN_EK extends Enum { * States an invite can be in */ class PLAN_INVITE_STATE extends Enum { + /** + * pending invite + */ const PENDING = 0; + /** + * accepted invite + */ const ACCEPTED = 1; + /** + * declined invite + */ const DECLINED = 2; + /** + * expired invite + */ const EXPIRED = 3; } /** - * Provides helper methods for any tables related with the planning function of the app. + * Provides helper methods for any tables related with the planning function of the app */ class plan_helper { /** @@ -78,19 +118,19 @@ class plan_helper { /** * Returns a list of user id's that are members of the plan. * - * @param integer $planid The id of the plan. + * @param int $planid The id of the plan. * @return array An array of user id's. */ public static function get_plan_members(int $planid):array { global $DB; - $members = $DB->get_records(self::ACCESS_TABLE, array('planid' => $planid)); + $members = $DB->get_records(self::ACCESS_TABLE, ['planid' => $planid]); return $members; } /** * Returns the user id of the owner of the plan. * - * @param integer $planid The id of the plan. + * @param int $planid The id of the plan. * @return integer The user id of the owner. */ public static function get_owner(int $planid):int { @@ -98,7 +138,7 @@ public static function get_owner(int $planid):int { $owner = $DB->get_field( self::ACCESS_TABLE, - 'userid', array('planid' => $planid, 'accesstype' => PLAN_ACCESS_TYPE::OWNER) + 'userid', ['planid' => $planid, 'accesstype' => PLAN_ACCESS_TYPE::OWNER] ); return $owner; @@ -107,20 +147,20 @@ public static function get_owner(int $planid):int { /** * Returns the id of the plan that the given user is a member of. * - * @param integer $userid The id of the user. + * @param int $userid The id of the user. * @return integer The id of the plan the given user is a member of. */ public static function get_plan_id(int $userid):int { global $DB; - $planid = $DB->get_field(self::ACCESS_TABLE, 'planid', array('userid' => $userid)); + $planid = $DB->get_field(self::ACCESS_TABLE, 'planid', ['userid' => $userid]); return $planid; } /** * Returns the access type of the given user for the given plan. * - * @param int $planid The id of the plan. * @param int $userid The id of the user. + * @param int $planid The id of the plan. * @return int The access type of the given user for the given plan. */ public static function get_access_type(int $userid, int $planid): int { @@ -129,7 +169,7 @@ public static function get_access_type(int $userid, int $planid): int { $field = $DB->get_field( self::ACCESS_TABLE, 'accesstype', - array('planid' => $planid, 'userid' => $userid) + ['planid' => $planid, 'userid' => $userid] ); if ($field === false) { @@ -155,22 +195,22 @@ public static function check_edit_permissions(int $planid, int $userid):bool { /** * Returns a list of all deadlines for the given plan. * - * @param integer $planid The id of the plan. + * @param int $planid The id of the plan. * @return array A list of all deadlines for the given plan. */ public static function get_deadlines(int $planid): array { global $DB; - $dbdeadlines = $DB->get_records(self::DEADLINES_TABLE, array('planid' => $planid)); + $dbdeadlines = $DB->get_records(self::DEADLINES_TABLE, ['planid' => $planid]); - $deadlines = array(); + $deadlines = []; foreach ($dbdeadlines as $dbdeadline) { - $deadlines[] = array( + $deadlines[] = [ 'deadlinestart' => $dbdeadline->deadlinestart, 'deadlineend' => $dbdeadline->deadlineend, 'moduleid' => $dbdeadline->moduleid, - ); + ]; } return $deadlines; @@ -179,29 +219,29 @@ public static function get_deadlines(int $planid): array { /** * Retrieves all the information available about the given plan. * - * @param integer $planid The id of the plan. + * @param int $planid The id of the plan. * @return array An array containing all the information available about the given plan. */ public static function get_plan(int $planid) : array { global $DB; - $plan = $DB->get_record(self::TABLE, array('id' => $planid)); - $members = array(); + $plan = $DB->get_record(self::TABLE, ['id' => $planid]); + $members = []; foreach (self::get_plan_members($planid) as $member) { - $members[] = array( + $members[] = [ 'userid' => $member->userid, 'accesstype' => $member->accesstype, - ); + ]; } - return array( + return [ 'name' => $plan->name, 'planid' => $planid, 'enableek' => $plan->enableek, 'deadlines' => self::get_deadlines($planid), 'members' => $members, - ); + ]; } /** @@ -211,36 +251,36 @@ public static function get_plan(int $planid) : array { */ public static function plan_structure() : external_single_structure { return new external_single_structure( - array( + [ 'name' => new external_value(PARAM_TEXT, 'Name of the plan'), 'planid' => new external_value(PARAM_INT, 'ID of the plan'), 'enableek' => new external_value(PARAM_BOOL, 'Whether EK is enabled'), 'deadlines' => new external_multiple_structure( new external_single_structure( - array( + [ 'moduleid' => new external_value(PARAM_INT, 'ID of the module'), 'deadlinestart' => new external_value(PARAM_INT, 'Start of the deadline as an UNIX timestamp'), 'deadlineend' => new external_value(PARAM_INT, 'End of the deadline as an UNIX timestamp'), - ) + ] ) ), 'members' => new external_multiple_structure( new external_single_structure( - array( + [ 'userid' => new external_value(PARAM_INT, 'The id of the user'), 'accesstype' => new external_value(PARAM_INT, 'The role of the user '.PLAN_ACCESS_TYPE::format()), - ) + ] ) ), - ) + ] ); } /** * Copies the given plan to the given user. * - * @param integer $planid The id of the plan. - * @param integer $userid The id of the user. + * @param int $planid The id of the plan. + * @param int $userid The id of the user. * @return integer The id of the new copy of the plan. */ public static function copy_plan(int $planid, int $userid) : int { @@ -248,7 +288,7 @@ public static function copy_plan(int $planid, int $userid) : int { $user = user_helper::get_mdl_user_info($userid); - $plan = $DB->get_record(self::TABLE, array('id' => $planid)); + $plan = $DB->get_record(self::TABLE, ['id' => $planid]); $plan->name = $plan->name . ' (' . $user->username . ')'; $plan->id = null; @@ -265,9 +305,9 @@ public static function copy_plan(int $planid, int $userid) : int { /** * Removes the user from the given plan. * - * @param integer $planid the plan id. - * @param integer $userid the user id. - * @param integer $removeuserid the user id to remove. + * @param int $planid the plan id. + * @param int $userid the user id. + * @param int $removeuserid the user id to remove. * @return int The ID of the new plan for the removed user */ public static function remove_user(int $planid, int $userid, int $removeuserid) : int { @@ -292,7 +332,7 @@ public static function remove_user(int $planid, int $userid, int $removeuserid) $oldaccess = $DB->get_record( self::ACCESS_TABLE, - array('planid' => $planid, 'userid' => $removeuserid), '*', MUST_EXIST + ['planid' => $planid, 'userid' => $removeuserid], '*', MUST_EXIST ); $oldaccess->planid = $newplanid; @@ -302,14 +342,26 @@ public static function remove_user(int $planid, int $userid, int $removeuserid) return $newplanid; } + /** + * Get all invites that have been sent by the user. + * + * @param int $userid ID of the sender + * @return array an array of invites sent by the user + */ public static function get_invites_send(int $userid):array { global $DB; - $invites = $DB->get_records(self::INVITES_TABLE, array('inviterid' => $userid)); + $invites = $DB->get_records(self::INVITES_TABLE, ['inviterid' => $userid]); return $invites; } + /** + * Get all invites that have been received by the user. + * + * @param int $userid ID of the receiver + * @return array an array of invites received by the user + */ public static function get_invites_received(int $userid):array { global $DB; - $invites = $DB->get_records(self::INVITES_TABLE, array('inviteeid' => $userid)); + $invites = $DB->get_records(self::INVITES_TABLE, ['inviteeid' => $userid]); return $invites; } } diff --git a/lbplanner/classes/helpers/user_helper.php b/lbplanner/classes/helpers/user_helper.php index f8732397..80d41d12 100644 --- a/lbplanner/classes/helpers/user_helper.php +++ b/lbplanner/classes/helpers/user_helper.php @@ -26,8 +26,10 @@ /** * Provides helper methods for user related stuff. - * @package local_lbplanner\helpers - * @copyright LB PLANNER + * + * @package local_lbplanner + * @subpackage helpers + * @copyright 2024 NecodeIT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class user_helper { diff --git a/lbplanner/classes/polyfill/enum.php b/lbplanner/classes/polyfill/enum.php index 7bb1d15e..9978de2a 100644 --- a/lbplanner/classes/polyfill/enum.php +++ b/lbplanner/classes/polyfill/enum.php @@ -13,74 +13,99 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * polyfill for php8 enums + * + * @package local_lbplanner + * @subpackage polyfill + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ namespace local_lbplanner\polyfill; +defined('MOODLE_INTERNAL') || die(); + use ReflectionClass; use ValueError; +/** + * Class which is meant to serve as a substitute for native enums. + */ abstract class Enum { - /** - * tries to match the passed value to one of the enum values - * @param mixed $value the value to be matched - * @return mixed either the matching enum value or null if not found - */ - public static function tryFrom(mixed $value): mixed { - $cases = static::cases(); - foreach($cases as $case){ - if($case->value === $value) - return $value; - } - return null; - } - /** - * tries to match the passed value to one of the enum values - * @param mixed $value the value to be matched - * @return mixed the matching enum value - * @throws ValueError if not found - */ - public static function from(mixed $value): mixed { - $cases = static::cases(); - foreach($cases as $case){ - if($case->value === $value) - return $value; - } - - throw new ValueError("value {$value} cannot be represented as a value in enum ".static::class); - } - /** - * @return EnumCase[] array of cases inside this enum - */ - public static function cases(): array { - $reflection = new ReflectionClass(static::class); - $cases = []; - foreach($reflection->getConstants() as $name=>$val){ - array_push($cases,new EnumCase($name,$val)); - } - return $cases; - } - /** - * Formats all possible enum values into a string - * Example: - * (31=>RED,32=>GREEN,33=>YELLOW) - * @return string the resulting string - */ - public static function format(): string { - $result = "["; - $cases = static::cases(); - foreach($cases as $case) { - $result .= "{$case->value}=>{$case->name},"; - } - $result[-1] = ']'; - return $result; - } + /** + * tries to match the passed value to one of the enum values + * @param mixed $value the value to be matched + * @return mixed either the matching enum value or null if not found + */ + public static function try_from(mixed $value): mixed { + foreach (static::cases() as $case) { + if ($case->value === $value) { + return $value; + } + } + return null; + } + /** + * tries to match the passed value to one of the enum values + * @param mixed $value the value to be matched + * @return mixed the matching enum value + * @throws ValueError if not found + */ + public static function from(mixed $value): mixed { + foreach (static::cases() as $case) { + if ($case->value === $value) { + return $value; + } + } + + throw new ValueError("value {$value} cannot be represented as a value in enum ".static::class); + } + /** + * Returns an array of all the cases that exist in this enum + * + * @return EnumCase[] array of cases inside this enum + */ + public static function cases(): array { + $reflection = new ReflectionClass(static::class); + $cases = []; + foreach ($reflection->getConstants() as $name => $val) { + array_push($cases, new EnumCase($name, $val)); + } + return $cases; + } + /** + * Formats all possible enum values into a string + * Example: + * (31=>RED,32=>GREEN,33=>YELLOW) + * @return string the resulting string + */ + public static function format(): string { + $result = "["; + foreach (static::cases() as $case) { + $result .= "{$case->value}=>{$case->name},"; + } + $result[-1] = ']'; + return $result; + } } +/** + * This represents a single case within an Enum + */ class EnumCase { - public string $name; - public mixed $value; - public function __construct($name,$value){ - $this->name = $name; - $this->value = $value; - } -} \ No newline at end of file + /** @var string the name of the case */ + public string $name; + /** @var string the value of the case */ + public mixed $value; + /** + * Constructs an EnumCase + * + * @param string $name the name of the case + * @param mixed $value the value of the case + */ + public function __construct(string $name, mixed $value) { + $this->name = $name; + $this->value = $value; + } +} diff --git a/lbplanner/db/access.php b/lbplanner/db/access.php index 34b52cb3..0302fc56 100644 --- a/lbplanner/db/access.php +++ b/lbplanner/db/access.php @@ -13,30 +13,36 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * contains access levels, i.e. capabilities + * + * @package local_lbplanner + * @subpackage db + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ defined('MOODLE_INTERNAL') || die(); -$capabilities = array( - 'local/lb_planner:student' => array( +$capabilities = [ + 'local/lb_planner:student' => [ 'riskbitmask' => RISK_SPAM, 'captype' => 'write', 'contextlevel' => CONTEXT_SYSTEM, - ), - 'local/lb_planner:teacher' => array( + ], + 'local/lb_planner:teacher' => [ 'riskbitmask' => RISK_SPAM || RISK_PERSONAL, 'captype' => 'write', 'contextlevel' => CONTEXT_SYSTEM, - ), - 'local/lb_planner:admin' => array( + ], + 'local/lb_planner:admin' => [ 'riskbitmask' => RISK_SPAM || RISK_PERSONAL, 'captype' => 'write', 'contextlevel' => CONTEXT_SYSTEM, - ), - 'local/lb_planner:manager' => array( + ], + 'local/lb_planner:manager' => [ 'riskbitmask' => RISK_SPAM || RISK_PERSONAL, 'captype' => 'write', 'contextlevel' => CONTEXT_SYSTEM, - ) - - -); + ], +]; diff --git a/lbplanner/db/install.php b/lbplanner/db/install.php index 1c3512c8..2e0cfb9f 100644 --- a/lbplanner/db/install.php +++ b/lbplanner/db/install.php @@ -13,15 +13,27 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * contains some stuff for the first install of the module + * + * @package local_lbplanner + * @subpackage db + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\config_helper; defined('MOODLE_INTERNAL') || die; +/** + * Runs when plugin is first installed + * right now, it does nothing + */ function xmldb_local_lbplanner_install() { global $DB; - } + config_helper::set_default_active_year(); diff --git a/lbplanner/db/services.php b/lbplanner/db/services.php index 59266a47..2bf60516 100644 --- a/lbplanner/db/services.php +++ b/lbplanner/db/services.php @@ -13,12 +13,19 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . - +/** + * contains all service endpoints + * + * @package local_lbplanner + * @subpackage db + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ defined('MOODLE_INTERNAL') || die(); -$functions = array( - 'local_lbplanner_user_get_user' => array( +$functions = [ + 'local_lbplanner_user_get_user' => [ 'classname' => 'local_lbplanner_services\user_get_user', 'methodname' => 'get_user', 'classpath' => 'local/lbplanner/services/user/get_user.php', @@ -26,8 +33,8 @@ 'type' => 'read', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_user_get_all_users' => array( + ], + 'local_lbplanner_user_get_all_users' => [ 'classname' => 'local_lbplanner_services\user_get_all_users', 'methodname' => 'get_all_users', 'classpath' => 'local/lbplanner/services/user/get_all_users.php', @@ -35,8 +42,8 @@ 'type' => 'read', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_user_register_user' => array( + ], + 'local_lbplanner_user_register_user' => [ 'classname' => 'local_lbplanner_services\user_register_user', 'methodname' => 'register_user', 'classpath' => 'local/lbplanner/services/user/register_user.php', @@ -44,8 +51,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_user_update_user' => array( + ], + 'local_lbplanner_user_update_user' => [ 'classname' => 'local_lbplanner_services\user_update_user', 'methodname' => 'update_user', 'classpath' => 'local/lbplanner/services/user/update_user.php', @@ -53,8 +60,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_courses_get_all_courses' => array( + ], + 'local_lbplanner_courses_get_all_courses' => [ 'classname' => 'local_lbplanner_services\courses_get_all_courses', 'methodname' => 'get_all_courses', 'classpath' => 'local/lbplanner/services/courses/get_all_courses.php', @@ -62,8 +69,8 @@ 'type' => 'read', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_courses_update_course' => array( + ], + 'local_lbplanner_courses_update_course' => [ 'classname' => 'local_lbplanner_services\courses_update_course', 'methodname' => 'update_course', 'classpath' => 'local/lbplanner/services/courses/update_course.php', @@ -71,8 +78,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_modules_get_module' => array( + ], + 'local_lbplanner_modules_get_module' => [ 'classname' => 'local_lbplanner_services\modules_get_module', 'methodname' => 'get_module', 'classpath' => 'local/lbplanner/services/modules/get_module.php', @@ -80,8 +87,8 @@ 'type' => 'read', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_modules_get_all_modules' => array( + ], + 'local_lbplanner_modules_get_all_modules' => [ 'classname' => 'local_lbplanner_services\modules_get_all_modules', 'methodname' => 'get_all_modules', 'classpath' => 'local/lbplanner/services/modules/get_all_modules.php', @@ -89,8 +96,8 @@ 'type' => 'read', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_modules_get_all_course_modules' => array( + ], + 'local_lbplanner_modules_get_all_course_modules' => [ 'classname' => 'local_lbplanner_services\modules_get_all_course_modules', 'methodname' => 'get_all_course_modules', 'classpath' => 'local/lbplanner/services/modules/get_all_course_modules.php', @@ -98,8 +105,8 @@ 'type' => 'read', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_plan_clear_plan' => array( + ], + 'local_lbplanner_plan_clear_plan' => [ 'classname' => 'local_lbplanner_services\plan_clear_plan', 'methodname' => 'clear_plan', 'classpath' => 'local/lbplanner/services/plan/clear_plan.php', @@ -107,8 +114,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_plan_get_plan' => array( + ], + 'local_lbplanner_plan_get_plan' => [ 'classname' => 'local_lbplanner_services\plan_get_plan', 'methodname' => 'get_plan', 'classpath' => 'local/lbplanner/services/plan/get_plan.php', @@ -116,8 +123,8 @@ 'type' => 'read', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_plan_invite_user' => array( + ], + 'local_lbplanner_plan_invite_user' => [ 'classname' => 'local_lbplanner_services\plan_invite_user', 'methodname' => 'invite_user', 'classpath' => 'local/lbplanner/services/plan/invite_user.php', @@ -125,8 +132,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_plan_remove_user' => array( + ], + 'local_lbplanner_plan_remove_user' => [ 'classname' => 'local_lbplanner_services\plan_remove_user', 'methodname' => 'remove_user', 'classpath' => 'local/lbplanner/services/plan/remove_user.php', @@ -134,8 +141,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_plan_update_plan' => array( + ], + 'local_lbplanner_plan_update_plan' => [ 'classname' => 'local_lbplanner_services\plan_update_plan', 'methodname' => 'update_plan', 'classpath' => 'local/lbplanner/services/plan/update_plan.php', @@ -143,8 +150,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_plan_leave_plan' => array( + ], + 'local_lbplanner_plan_leave_plan' => [ 'classname' => 'local_lbplanner_services\plan_leave_plan', 'methodname' => 'leave_plan', 'classpath' => 'local/lbplanner/services/plan/leave_plan.php', @@ -152,8 +159,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_plan_delete_deadline' => array( + ], + 'local_lbplanner_plan_delete_deadline' => [ 'classname' => 'local_lbplanner_services\plan_delete_deadline', 'methodname' => 'delete_deadline', 'classpath' => 'local/lbplanner/services/plan/delete_deadline.php', @@ -161,8 +168,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_user_delete_user' => array( + ], + 'local_lbplanner_user_delete_user' => [ 'classname' => 'local_lbplanner_services\user_delete_user', 'methodname' => 'delete_user', 'classpath' => 'local/lbplanner/services/user/delete_user.php', @@ -170,8 +177,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_plan_set_deadline' => array( + ], + 'local_lbplanner_plan_set_deadline' => [ 'classname' => 'local_lbplanner_services\plan_set_deadline', 'methodname' => 'set_deadline', 'classpath' => 'local/lbplanner/services/plan/set_deadline.php', @@ -179,8 +186,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_plan_update_access' => array( + ], + 'local_lbplanner_plan_update_access' => [ 'classname' => 'local_lbplanner_services\plan_update_access', 'methodname' => 'update_access', 'classpath' => 'local/lbplanner/services/plan/update_access.php', @@ -188,8 +195,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_plan_get_invites' => array( + ], + 'local_lbplanner_plan_get_invites' => [ 'classname' => 'local_lbplanner_services\plan_get_invites', 'methodname' => 'get_invites', 'classpath' => 'local/lbplanner/services/plan/get_invites.php', @@ -197,8 +204,8 @@ 'type' => 'read', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_notifications_get_all_notifications' => array( + ], + 'local_lbplanner_notifications_get_all_notifications' => [ 'classname' => 'local_lbplanner_services\notifications_get_all_notifications', 'methodname' => 'get_all_notifications', 'classpath' => 'local/lbplanner/services/notifications/get_all_notifications.php', @@ -206,8 +213,8 @@ 'type' => 'read', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_notifications_update_notification' => array( + ], + 'local_lbplanner_notifications_update_notification' => [ 'classname' => 'local_lbplanner_services\notifications_update_notification', 'methodname' => 'update_notification', 'classpath' => 'local/lbplanner/services/notifications/update_notification.php', @@ -215,8 +222,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_feedback_submit_feedback' => array( + ], + 'local_lbplanner_feedback_submit_feedback' => [ 'classname' => 'local_lbplanner_services\feedback_submit_feedback', 'methodname' => 'submit_feedback', 'classpath' => 'local/lbplanner/services/feedback/submit_feedback.php', @@ -224,8 +231,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_feedback_get_all_feedbacks' => array( + ], + 'local_lbplanner_feedback_get_all_feedbacks' => [ 'classname' => 'local_lbplanner_services\feedback_get_all_feedbacks', 'methodname' => 'get_all_feedbacks', 'classpath' => 'local/lbplanner/services/feedback/get_all_feedbacks.php', @@ -233,8 +240,8 @@ 'type' => 'read', 'capabilities' => 'local/lb_planner:admin, local/lb_planner:manager', 'ajax' => true, - ), - 'local_lbplanner_feedback_update_feedback' => array( + ], + 'local_lbplanner_feedback_update_feedback' => [ 'classname' => 'local_lbplanner_services\feedback_update_feedback', 'methodname' => 'update_feedback', 'classpath' => 'local/lbplanner/services/feedback/update_feedback.php', @@ -242,8 +249,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:admin, local/lb_planner:manager', 'ajax' => true, - ), - 'local_lbplanner_feedback_delete_feedback' => array( + ], + 'local_lbplanner_feedback_delete_feedback' => [ 'classname' => 'local_lbplanner_services\feedback_delete_feedback', 'methodname' => 'delete_feedback', 'classpath' => 'local/lbplanner/services/feedback/delete_feedback.php', @@ -251,8 +258,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:admin, local/lb_planner:manager', 'ajax' => true, - ), - 'local_lbplanner_plan_accept_invite' => array( + ], + 'local_lbplanner_plan_accept_invite' => [ 'classname' => 'local_lbplanner_services\plan_accept_invite', 'methodname' => 'accept_invite', 'classpath' => 'local/lbplanner/services/plan/accept_invite.php', @@ -260,8 +267,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_plan_decline_invite' => array( + ], + 'local_lbplanner_plan_decline_invite' => [ 'classname' => 'local_lbplanner_services\plan_decline_invite', 'methodname' => 'decline_invite', 'classpath' => 'local/lbplanner/services/plan/decline_invite.php', @@ -269,8 +276,8 @@ 'type' => 'write', 'capabilities' => 'local/lb_planner:student', 'ajax' => true, - ), - 'local_lbplanner_config_get_version' => array( + ], + 'local_lbplanner_config_get_version' => [ 'classname' => 'local_lbplanner_services\config_get_version', 'methodname' => 'get_version', 'classpath' => 'local/lbplanner/services/config/get_version.php', @@ -278,12 +285,12 @@ 'type' => 'read', 'capabilities' => '', 'ajax' => true, - ), -); + ], +]; -$services = array( - 'LB Planner API' => array( - 'functions' => array( +$services = [ + 'LB Planner API' => [ + 'functions' => [ 'local_lbplanner_user_get_user', 'local_lbplanner_user_get_all_users', 'local_lbplanner_user_register_user', @@ -293,7 +300,6 @@ 'local_lbplanner_modules_get_all_course_modules', 'local_lbplanner_modules_get_all_modules', 'local_lbplanner_modules_get_module', - 'local_lbplanner_plan_add_deadline', 'local_lbplanner_plan_clear_plan', 'local_lbplanner_plan_delete_deadline', 'local_lbplanner_plan_get_plan', @@ -301,7 +307,7 @@ 'local_lbplanner_plan_get_invites', 'local_lbplanner_plan_leave_plan', 'local_lbplanner_plan_remove_user', - 'local_lbplanner_plan_update_deadline', + 'local_lbplanner_plan_set_deadline', 'local_lbplanner_plan_update_plan', 'local_lbplanner_notifications_get_all_notifications', 'local_lbplanner_notifications_update_notification', @@ -315,9 +321,9 @@ 'local_lbplanner_plan_accept_invite', 'local_lbplanner_plan_decline_invite', 'local_lbplanner_config_get_version', - ), + ], 'restrictedusers' => 0, 'enabled' => 1, - 'shortname' => 'lb_planner_api' - ), -); + 'shortname' => 'lb_planner_api', + ], +]; diff --git a/lbplanner/db/upgrade.php b/lbplanner/db/upgrade.php index bd52dcd0..a072dc19 100644 --- a/lbplanner/db/upgrade.php +++ b/lbplanner/db/upgrade.php @@ -13,10 +13,25 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * for upgrading the db + * + * @package local_lbplanner + * @subpackage db + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ use local_lbplanner\helpers\config_helper; -function xmldb_local_lbplanner_upgrade($oldversion) { +/** + * Upgrades the DB version + * right now it only sets the default active year + * + * @param mixed $oldversion (unused) the previous version to upgrade from + * @return bool true + */ +function xmldb_local_lbplanner_upgrade($oldversion): bool { config_helper::set_default_active_year(); return true; } diff --git a/lbplanner/lang/en/local_lbplanner.php b/lbplanner/lang/en/local_lbplanner.php index 85f45bbd..c0074026 100644 --- a/lbplanner/lang/en/local_lbplanner.php +++ b/lbplanner/lang/en/local_lbplanner.php @@ -13,8 +13,15 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * Defines some translation strings in english + * + * @package local_lbplanner + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ -defined('MOODLE_INTERNAL') or die(); +defined('MOODLE_INTERNAL') || die(); $string['pluginname'] = 'LB Planner'; $string['lb_planner:student'] = 'LB Planner Student'; diff --git a/lbplanner/services/config/get_version.php b/lbplanner/services/config/get_version.php index 3f3c51ec..1f66b731 100644 --- a/lbplanner/services/config/get_version.php +++ b/lbplanner/services/config/get_version.php @@ -23,25 +23,43 @@ /** * Get version service. + * + * @package local_lbplanner + * @subpackage services_config + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class config_get_version extends external_api { - public static function get_version_parameters() { + /** + * Parameters for get_version. + * @return external_function_parameters + */ + public static function get_version_parameters(): external_function_parameters { return new external_function_parameters( - array() + [] ); } - public static function get_version() { - $release = get_config('local_lbplanner', 'release'); - return array( - 'release' => get_config('local_lbplanner', 'release')); + /** + * Returns the version. + * + * @return array containing the version + */ + public static function get_version(): array { + return [ + 'release' => get_config('local_lbplanner', 'release'), + ]; } - public static function get_version_returns() { + /** + * Returns the structure of the versioning array. + * @return external_single_structure + */ + public static function get_version_returns(): external_single_structure { return new external_single_structure( - array( + [ 'release' => new external_value(PARAM_TEXT, 'the current LBPlanner version'), - ) + ] ); } } diff --git a/lbplanner/services/courses/get_all_courses.php b/lbplanner/services/courses/get_all_courses.php index 66dae9be..976e71d5 100644 --- a/lbplanner/services/courses/get_all_courses.php +++ b/lbplanner/services/courses/get_all_courses.php @@ -29,9 +29,9 @@ /** * Get all the courses of the current year. * - * Retrievs all the courses of the current school year. * @package local_lbplanner - * @copyright 2023 necodeIT + * @subpackage services_courses + * @copyright 2024 necodeIT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class courses_get_all_courses extends external_api { diff --git a/lbplanner/services/courses/update_course.php b/lbplanner/services/courses/update_course.php index c784c144..c37c592a 100644 --- a/lbplanner/services/courses/update_course.php +++ b/lbplanner/services/courses/update_course.php @@ -27,10 +27,10 @@ /** * Update the data for a course. * - * Updates the data for a specific course. * @package local_lbplanner + * @subpackage services_courses + * @copyright 2024 necodeIT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @copyright 2023 necodeIT */ class courses_update_course extends external_api { /** @@ -47,7 +47,7 @@ public static function update_course_parameters(): external_function_parameters 'Whether the course is enabled or not', VALUE_DEFAULT, null - ) + ), ]); } diff --git a/lbplanner/services/feedback/delete_feedback.php b/lbplanner/services/feedback/delete_feedback.php index ac42f5a1..6b5cefb9 100644 --- a/lbplanner/services/feedback/delete_feedback.php +++ b/lbplanner/services/feedback/delete_feedback.php @@ -24,15 +24,31 @@ /** * Deletes feedback from the database. + * + * @package local_lbplanner + * @subpackage services_feedback + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class feedback_delete_feedback extends external_api { - public static function delete_feedback_parameters() { + /** + * Parameters for delete_feedback. + * @return external_function_parameters + */ + public static function delete_feedback_parameters(): external_function_parameters { return new external_function_parameters([ 'feedbackid' => new external_value(PARAM_INT, 'ID of the feedback to delete', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), ]); } - public static function delete_feedback($feedbackid) { + /** + * Deletes feedback from the database. + * + * @param int $feedbackid ID of the feedback to delete + * @return void + * @throws \moodle_exception when feedback wasn't found + */ + public static function delete_feedback(int $feedbackid) { global $DB, $USER; self::validate_parameters( @@ -49,6 +65,10 @@ public static function delete_feedback($feedbackid) { $DB->delete_records(feedback_helper::LBPLANNER_FEEDBACK_TABLE, ['id' => $feedbackid]); } + /** + * Returns the structure of nothing. + * @return null + */ public static function delete_feedback_returns() { return null; } diff --git a/lbplanner/services/feedback/get_all_feedbacks.php b/lbplanner/services/feedback/get_all_feedbacks.php index d91d31a0..207ee2ef 100644 --- a/lbplanner/services/feedback/get_all_feedbacks.php +++ b/lbplanner/services/feedback/get_all_feedbacks.php @@ -23,18 +23,36 @@ /** * Get all feedback from the database. + * + * @package local_lbplanner + * @subpackage services_feedback + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class feedback_get_all_feedbacks extends external_api { - public static function get_all_feedbacks_parameters() { + /** + * Parameters for get_all_feedbacks. + * @return external_function_parameters + */ + public static function get_all_feedbacks_parameters(): external_function_parameters { return new external_function_parameters([]); } + /** + * Returns all feedbacks from the database. + * + * @return array all feedback objects + */ public static function get_all_feedbacks(): array { feedback_helper::assert_admin_access(); return feedback_helper::get_all_feedbacks(); } - public static function get_all_feedbacks_returns() { + /** + * Returns the structure of the array of feedbacks. + * @return external_multiple_structure + */ + public static function get_all_feedbacks_returns(): external_multiple_structure { return new external_multiple_structure( feedback_helper::structure(), ); diff --git a/lbplanner/services/feedback/submit_feedback.php b/lbplanner/services/feedback/submit_feedback.php index 47b6cdd2..1c857c67 100644 --- a/lbplanner/services/feedback/submit_feedback.php +++ b/lbplanner/services/feedback/submit_feedback.php @@ -23,19 +23,55 @@ /** * Add feedback to the database. + * + * @package local_lbplanner + * @subpackage services_feedback + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class feedback_submit_feedback extends external_api { - public static function submit_feedback_parameters() { + /** + * Parameters for submit_feedback. + * @return external_function_parameters + */ + public static function submit_feedback_parameters(): external_function_parameters { return new external_function_parameters( [ - 'type' => new external_value(PARAM_INT, 'type of Feedback (bug, typo, feature, other)', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'content' => new external_value(PARAM_TEXT, 'feedback contents', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'logfile' => new external_value(PARAM_TEXT, 'file name of the associated log file', VALUE_DEFAULT, null, NULL_NOT_ALLOWED ), + 'type' => new external_value( + PARAM_INT, + 'type of Feedback (bug, typo, feature, other)', // TODO: use enums. + VALUE_REQUIRED, + null, + NULL_NOT_ALLOWED, + ), + 'content' => new external_value( + PARAM_TEXT, + 'feedback contents', + VALUE_REQUIRED, + null, + NULL_NOT_ALLOWED, + ), + 'logfile' => new external_value( + PARAM_TEXT, + 'file name of the associated log file', + VALUE_DEFAULT, + null, + NULL_NOT_ALLOWED, + ), ] ); } - public static function submit_feedback($type, $content, $logfile) { + /** + * Add feedback to the database. + * + * @param int $type type of Feedback + * @see feedback_helper + * @param string $content feedback contents + * @param string $logfile file name of the associated log file + * @return int The ID of the new feedback + */ + public static function submit_feedback(int $type, string $content, string $logfile): int { global $DB, $USER; self::validate_parameters( @@ -43,6 +79,8 @@ public static function submit_feedback($type, $content, $logfile) { ['type' => $type, 'content' => $content, 'logfile' => $logfile] ); + // TODO: validate $type. + $id = $DB->insert_record(feedback_helper::LBPLANNER_FEEDBACK_TABLE, [ 'content' => $content, 'userid' => $USER->id, @@ -55,7 +93,11 @@ public static function submit_feedback($type, $content, $logfile) { return $id; } - public static function submit_feedback_returns() { + /** + * Returns the structure of the feedback ID. + * @return external_value + */ + public static function submit_feedback_returns(): external_value { return new external_value(PARAM_INT, "The ID of the new feedback"); } } diff --git a/lbplanner/services/feedback/update_feedback.php b/lbplanner/services/feedback/update_feedback.php index dd7a9168..85df8503 100644 --- a/lbplanner/services/feedback/update_feedback.php +++ b/lbplanner/services/feedback/update_feedback.php @@ -24,17 +24,37 @@ /** * Updates feedback from the database. + * + * @package local_lbplanner + * @subpackage services_feedback + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class feedback_update_feedback extends external_api { - public static function update_feedback_parameters() { + /** + * Parameters for update_feedback. + * @return external_function_parameters + */ + public static function update_feedback_parameters(): external_function_parameters { return new external_function_parameters([ - 'feedbackid' => new external_value(PARAM_INT, 'ID of the feedback to be updated', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + 'feedbackid' => + new external_value(PARAM_INT, 'ID of the feedback to be updated', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), 'notes' => new external_value(PARAM_TEXT, 'updated notes', VALUE_DEFAULT, null, NULL_ALLOWED), 'status' => new external_value(PARAM_INT, 'updated status', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), ]); } - public static function update_feedback($feedbackid, $notes, $status) { + /** + * Updates feedback from the database. + * + * @param int $feedbackid ID of the feedback to be updated + * @param string $notes updated notes + * @param int $status updated status + * @see feedback_helper + * @return void + * @throws \moodle_exception when feedback not found or status invalid + */ + public static function update_feedback(int $feedbackid, string $notes, int $status) { global $DB, $USER; self::validate_parameters( @@ -50,7 +70,7 @@ public static function update_feedback($feedbackid, $notes, $status) { $feedback = $DB->get_record(feedback_helper::LBPLANNER_FEEDBACK_TABLE, ['id' => $feedbackid], '*', MUST_EXIST); $feedback->notes = $notes; - if ($status > 1 || $status < 0) { + if ($status > 1 || $status < 0) { // TODO: use enum to validate. throw new \moodle_exception('Invalid status'); } $feedback->status = $status; @@ -60,6 +80,10 @@ public static function update_feedback($feedbackid, $notes, $status) { $DB->update_record(feedback_helper::LBPLANNER_FEEDBACK_TABLE, $feedback); } + /** + * Returns the structure of nothing. + * @return null + */ public static function update_feedback_returns() { return null; } diff --git a/lbplanner/services/modules/get_all_course_modules.php b/lbplanner/services/modules/get_all_course_modules.php index 9ca6555b..b53ec82d 100644 --- a/lbplanner/services/modules/get_all_course_modules.php +++ b/lbplanner/services/modules/get_all_course_modules.php @@ -25,10 +25,19 @@ /** * Get all the modules of the given course. + * + * @package local_lbplanner + * @subpackage services_modules + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class modules_get_all_course_modules extends external_api { - public static function get_all_course_modules_parameters() { - return new external_function_parameters(array( + /** + * Parameters for get_all_course_modules + * @return external_function_parameters + */ + public static function get_all_course_modules_parameters(): external_function_parameters { + return new external_function_parameters([ 'courseid' => new external_value(PARAM_INT, 'The id of the course', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), 'userid' => new external_value(PARAM_INT, 'The id of the user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), 'ekenabled' => new external_value( @@ -37,15 +46,23 @@ public static function get_all_course_modules_parameters() { VALUE_REQUIRED, false, NULL_NOT_ALLOWED), - )); + ]); } - public static function get_all_course_modules($courseid, $userid, $ekenabled) { + /** + * Returns all the modules inside a course. + * + * @param int $courseid The ID of the course + * @param int $userid The ID of the user + * @param bool $ekenabled whether or not to include ek modules + * @return array the modules + */ + public static function get_all_course_modules(int $courseid, int $userid, bool $ekenabled): array { global $DB; self::validate_parameters( self::get_all_course_modules_parameters(), - array('courseid' => $courseid, 'userid' => $userid, 'ekenabled' => $ekenabled) + ['courseid' => $courseid, 'userid' => $userid, 'ekenabled' => $ekenabled] ); user_helper::assert_access($userid); @@ -53,7 +70,11 @@ public static function get_all_course_modules($courseid, $userid, $ekenabled) { return modules_helper::get_all_course_modules($courseid, $userid, $ekenabled); } - public static function get_all_course_modules_returns() { + /** + * Returns the structure of the module array. + * @return external_multiple_structure + */ + public static function get_all_course_modules_returns(): external_multiple_structure { return new external_multiple_structure( modules_helper::structure(), ); diff --git a/lbplanner/services/modules/get_all_modules.php b/lbplanner/services/modules/get_all_modules.php index 6d2d08e3..e3363765 100644 --- a/lbplanner/services/modules/get_all_modules.php +++ b/lbplanner/services/modules/get_all_modules.php @@ -28,24 +28,39 @@ /** * Get all the modules of the current year. + * + * @package local_lbplanner + * @subpackage services_modules + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class modules_get_all_modules extends external_api { - public static function get_all_modules_parameters() { - return new external_function_parameters(array( + /** + * Parameters for get_all_modules. + * @return external_function_parameters + */ + public static function get_all_modules_parameters(): external_function_parameters { + return new external_function_parameters([ 'userid' => new external_value(PARAM_INT, 'The id of the user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - )); + ]); } - public static function get_all_modules($userid) { + /** + * Returns all the modules for a user. + * + * @param int $userid The ID of the user + * @return array the modules + */ + public static function get_all_modules(int $userid): array { global $DB; - self::validate_parameters(self::get_all_modules_parameters(), array('userid' => $userid)); + self::validate_parameters(self::get_all_modules_parameters(), ['userid' => $userid]); user_helper::assert_access($userid); - $modules = array(); + $modules = []; - $courses = self::call_external_function('local_lbplanner_courses_get_all_courses', array('userid' => $userid)); + $courses = self::call_external_function('local_lbplanner_courses_get_all_courses', ['userid' => $userid]); $plan = plan_helper::get_plan(plan_helper::get_plan_id($userid)); $ekenabled = $plan["enableek"]; @@ -61,9 +76,13 @@ public static function get_all_modules($userid) { return $modules; } - public static function get_all_modules_returns() { + /** + * Returns the structure of the module array. + * @return external_multiple_structure + */ + public static function get_all_modules_returns(): external_multiple_structure { return new external_multiple_structure( - modules_helper::structure(), + modules_helper::structure(), ); } } diff --git a/lbplanner/services/modules/get_module.php b/lbplanner/services/modules/get_module.php index d225e5f9..a57c33d4 100644 --- a/lbplanner/services/modules/get_module.php +++ b/lbplanner/services/modules/get_module.php @@ -18,6 +18,7 @@ use external_api; use external_function_parameters; +use external_single_structure; use external_value; use local_lbplanner\helpers\modules_helper; use local_lbplanner\helpers\plan_helper; @@ -25,30 +26,50 @@ /** * Get the data for a module. + * + * @package local_lbplanner + * @subpackage services_modules + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class modules_get_module extends external_api { - public static function get_module_parameters() { - return new external_function_parameters(array( + /** + * Parameters for get_module. + * @return external_function_parameters + */ + public static function get_module_parameters(): external_function_parameters { + return new external_function_parameters([ 'moduleid' => new external_value(PARAM_INT, 'The id of the module', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), 'userid' => new external_value(PARAM_INT, 'The id of the user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - )); + ]); } - public static function get_module($moduleid, $userid) { + /** + * Returns the data for a module + * + * @param int $moduleid The ID of the course + * @param int $userid The ID of the user + * @return array the module + */ + public static function get_module(int $moduleid, int $userid): array { global $DB; - self::validate_parameters(self::get_module_parameters(), array('moduleid' => $moduleid, 'userid' => $userid)); + self::validate_parameters(self::get_module_parameters(), ['moduleid' => $moduleid, 'userid' => $userid]); user_helper::assert_access($userid); - if (!$DB->record_exists(modules_helper::MDL_ASSIGN_TABLE, array('id' => $moduleid))) { + if (!$DB->record_exists(modules_helper::MDL_ASSIGN_TABLE, ['id' => $moduleid])) { throw new \moodle_exception('Module not found'); } return modules_helper::get_module($moduleid, $userid); } - public static function get_module_returns() { + /** + * Returns the structure of the module. + * @return external_single_structure + */ + public static function get_module_returns(): external_single_structure { return modules_helper::structure(); } } diff --git a/lbplanner/services/notifications/get_all_notifications.php b/lbplanner/services/notifications/get_all_notifications.php index 7ac3085c..8829ded4 100644 --- a/lbplanner/services/notifications/get_all_notifications.php +++ b/lbplanner/services/notifications/get_all_notifications.php @@ -22,14 +22,28 @@ use local_lbplanner\helpers\notifications_helper; /** - * Get all the notifications of the given user. + * Get all the notifications of the user. + * + * @package local_lbplanner + * @subpackage services_notifications + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class notifications_get_all_notifications extends external_api { - public static function get_all_notifications_parameters() { + /** + * Parameters for get_all_notifications. + * @return external_function_parameters + */ + public static function get_all_notifications_parameters(): external_function_parameters { return new external_function_parameters([]); } - public static function get_all_notifications() { + /** + * Returns all the notifications of the user + * + * @return array + */ + public static function get_all_notifications(): array { global $DB, $USER; $dbnotifications = $DB->get_records(notifications_helper::TABLE, ['userid' => $USER->id]); @@ -50,7 +64,11 @@ public static function get_all_notifications() { return $notifications; } - public static function get_all_notifications_returns() { + /** + * Returns the structure of the array of notifications. + * @return external_multiple_structure + */ + public static function get_all_notifications_returns(): external_multiple_structure { return new external_multiple_structure( notifications_helper::structure() ); diff --git a/lbplanner/services/notifications/update_notification.php b/lbplanner/services/notifications/update_notification.php index 106f830e..3fdbf6d0 100644 --- a/lbplanner/services/notifications/update_notification.php +++ b/lbplanner/services/notifications/update_notification.php @@ -22,10 +22,19 @@ use local_lbplanner\helpers\notifications_helper; /** - * Update the notification status of the given user and id. + * Update the notification status. + * + * @package local_lbplanner + * @subpackage services_notifications + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class notifications_update_notification extends external_api { - public static function update_notification_parameters() { + /** + * Parameters for update_notification. + * @return external_function_parameters + */ + public static function update_notification_parameters(): external_function_parameters { return new external_function_parameters([ 'status' => new external_value( PARAM_INT, @@ -34,11 +43,21 @@ public static function update_notification_parameters() { null, NULL_NOT_ALLOWED ), - 'notificationid' => new external_value(PARAM_INT, 'ID of the notification to be updated', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + 'notificationid' => + new external_value(PARAM_INT, 'ID of the notification to be updated', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), ]); } - public static function update_notification($status, $notificationid) { + /** + * Update the notification status. + * + * @param int $status notification status + * @see notifications_helper + * @param int $notificationid ID of the notification to be updated + * @return void + * @throws \moodle_exception when the notification doesn't exist + */ + public static function update_notification(int $status, int $notificationid) { global $DB; self::validate_parameters( @@ -57,6 +76,10 @@ public static function update_notification($status, $notificationid) { $DB->update_record(notifications_helper::TABLE, $notification); } + /** + * Returns the structure of nothing. + * @return null + */ public static function update_notification_returns() { return null; } diff --git a/lbplanner/services/plan/accept_invite.php b/lbplanner/services/plan/accept_invite.php index 4540a4cd..b148e092 100644 --- a/lbplanner/services/plan/accept_invite.php +++ b/lbplanner/services/plan/accept_invite.php @@ -27,15 +27,31 @@ /** * Accept an invite to the plan. + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class plan_accept_invite extends external_api { - public static function accept_invite_parameters() { + /** + * Parameters for accept_invite. + * @return external_function_parameters + */ + public static function accept_invite_parameters(): external_function_parameters { return new external_function_parameters([ 'inviteid' => new external_value(PARAM_INT, 'the ID of the invite to be accepted', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), ]); } - public static function accept_invite($inviteid) { + /** + * Accepts an invite + * + * @param int $inviteid the ID of the invite to be accepted + * @return void + * @throws \moodle_exception when invite not found, already accepted or declined + */ + public static function accept_invite(int $inviteid) { global $DB, $USER; self::validate_parameters(self::accept_invite_parameters(), [ @@ -113,7 +129,10 @@ public static function accept_invite($inviteid) { } } - + /** + * Returns the structure of nothing. + * @return null + */ public static function accept_invite_returns() { return null; } diff --git a/lbplanner/services/plan/clear_plan.php b/lbplanner/services/plan/clear_plan.php index e1dc5df5..6a90fd97 100644 --- a/lbplanner/services/plan/clear_plan.php +++ b/lbplanner/services/plan/clear_plan.php @@ -22,12 +22,27 @@ /** * Clear the plan for the given user. + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class plan_clear_plan extends external_api { - public static function clear_plan_parameters() { + /** + * Parameters for clear_plan. + * @return external_function_parameters + */ + public static function clear_plan_parameters(): external_function_parameters { return new external_function_parameters([]); } + /** + * Clear the plan. + * + * @return void + * @throws Exception when access denied + */ public static function clear_plan() { global $DB, $USER; @@ -40,6 +55,10 @@ public static function clear_plan() { $DB->delete_records(plan_helper::DEADLINES_TABLE, ['planid' => $planid ]); } + /** + * Returns the structure of nothing. + * @return null + */ public static function clear_plan_returns() { return null; } diff --git a/lbplanner/services/plan/decline_invite.php b/lbplanner/services/plan/decline_invite.php index 8f787b07..59191871 100644 --- a/lbplanner/services/plan/decline_invite.php +++ b/lbplanner/services/plan/decline_invite.php @@ -26,15 +26,31 @@ /** * Decline an invite from the plan. + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class plan_decline_invite extends external_api { - public static function decline_invite_parameters() { + /** + * Parameters for decline_invite. + * @return external_function_parameters + */ + public static function decline_invite_parameters(): external_function_parameters { return new external_function_parameters([ 'inviteid' => new external_value(PARAM_INT, 'the ID of the invite to be declined', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), ]); } - public static function decline_invite($inviteid) { + /** + * Decline an invite. + * + * @param int $inviteid the ID of the invite to be declined + * @return void + * @throws \moodle_exception when invite not found, already accepted or declined + */ + public static function decline_invite(int $inviteid) { global $DB, $USER; self::validate_parameters(self::decline_invite_parameters(), [ @@ -70,7 +86,10 @@ public static function decline_invite($inviteid) { $DB->update_record(plan_helper::INVITES_TABLE, $invite); } - + /** + * Returns the structure of nothing. + * @return null + */ public static function decline_invite_returns() { return null; } diff --git a/lbplanner/services/plan/delete_deadline.php b/lbplanner/services/plan/delete_deadline.php index 94b4db70..d9a9d215 100644 --- a/lbplanner/services/plan/delete_deadline.php +++ b/lbplanner/services/plan/delete_deadline.php @@ -23,9 +23,18 @@ /** * Delete a deadline from your plan + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class plan_delete_deadline extends external_api { - public static function delete_deadline_parameters() { + /** + * Parameters for delete_deadline. + * @return external_function_parameters + */ + public static function delete_deadline_parameters(): external_function_parameters { return new external_function_parameters([ 'moduleid' => new external_value( PARAM_INT, @@ -37,7 +46,14 @@ public static function delete_deadline_parameters() { ]); } - public static function delete_deadline($moduleid) { + /** + * Delete a deadline. + * + * @param int $moduleid ID of the Module + * @return void + * @throws Exception when access denied + */ + public static function delete_deadline(int $moduleid) { global $DB, $USER; self::validate_parameters( @@ -62,6 +78,10 @@ public static function delete_deadline($moduleid) { ); } + /** + * Returns the structure of nothing. + * @return null + */ public static function delete_deadline_returns() { return null; } diff --git a/lbplanner/services/plan/get_invites.php b/lbplanner/services/plan/get_invites.php index 7cbbcf72..dbeddf01 100644 --- a/lbplanner/services/plan/get_invites.php +++ b/lbplanner/services/plan/get_invites.php @@ -24,13 +24,27 @@ /** * Get all the invites of the current user. + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class plan_get_invites extends external_api { - public static function get_invites_parameters() { + /** + * Parameters for get_invites. + * @return external_function_parameters + */ + public static function get_invites_parameters(): external_function_parameters { return new external_function_parameters([]); } - public static function get_invites() { + /** + * Returns all invites of the current user. + * + * @return array + */ + public static function get_invites(): array { global $DB, $USER; $invitesreceived = $DB->get_records(plan_helper::INVITES_TABLE, ['inviteeid' => $USER->id]); @@ -63,7 +77,11 @@ public static function get_invites() { return $invites; } - public static function get_invites_returns() { + /** + * Returns the structure of the array of invites. + * @return external_multiple_structure + */ + public static function get_invites_returns(): external_multiple_structure { return new external_multiple_structure( invite_helper::structure() ); diff --git a/lbplanner/services/plan/get_plan.php b/lbplanner/services/plan/get_plan.php index e4913ba7..822c2e82 100644 --- a/lbplanner/services/plan/get_plan.php +++ b/lbplanner/services/plan/get_plan.php @@ -18,17 +18,32 @@ use external_api; use external_function_parameters; +use external_single_structure; use local_lbplanner\helpers\plan_helper; /** * Get the plan of the given user. + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class plan_get_plan extends external_api { - public static function get_plan_parameters() { + /** + * Parameters for get_plan. + * @return external_function_parameters + */ + public static function get_plan_parameters(): external_function_parameters { return new external_function_parameters([]); } - public static function get_plan() { + /** + * Returns the plan of the current user. + * + * @return array + */ + public static function get_plan(): array { global $DB, $USER; $planid = plan_helper::get_plan_id($USER->id); @@ -36,7 +51,11 @@ public static function get_plan() { return plan_helper::get_plan($planid); } - public static function get_plan_returns() { + /** + * Returns the structure of the plan. + * @return external_single_structure + */ + public static function get_plan_returns(): external_single_structure { return plan_helper::plan_structure(); } } diff --git a/lbplanner/services/plan/invite_user.php b/lbplanner/services/plan/invite_user.php index 065c5398..41b3469c 100644 --- a/lbplanner/services/plan/invite_user.php +++ b/lbplanner/services/plan/invite_user.php @@ -18,6 +18,7 @@ use external_api; use external_function_parameters; +use external_single_structure; use external_value; use local_lbplanner\helpers\invite_helper; use local_lbplanner\helpers\NOTIF_TRIGGER; @@ -26,10 +27,19 @@ use local_lbplanner\helpers\PLAN_INVITE_STATE; /** - * Invite a user to your plan + * Invite a user to the current user's plan + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class plan_invite_user extends external_api { - public static function invite_user_parameters() { + /** + * Parameters for invite_user. + * @return external_function_parameters + */ + public static function invite_user_parameters(): external_function_parameters { return new external_function_parameters([ 'inviteeid' => new external_value( PARAM_INT, @@ -41,7 +51,13 @@ public static function invite_user_parameters() { ]); } - public static function invite_user($inviteeid) { + /** + * Invite a user to the current user's plan + * + * @param int $inviteeid ID of the user who gets invited + * @return mixed the newly created invite + */ + public static function invite_user(int $inviteeid): mixed { global $DB, $USER; self::validate_parameters( @@ -90,7 +106,11 @@ public static function invite_user($inviteeid) { return $invite; } - public static function invite_user_returns() { + /** + * Returns the structure of the invite. + * @return external_single_structure + */ + public static function invite_user_returns(): external_single_structure { return invite_helper::structure(); } } diff --git a/lbplanner/services/plan/leave_plan.php b/lbplanner/services/plan/leave_plan.php index 9253ee8a..b7600e36 100644 --- a/lbplanner/services/plan/leave_plan.php +++ b/lbplanner/services/plan/leave_plan.php @@ -26,18 +26,35 @@ /** * Leave your plan + * * if no other user exists in the plan, the user can't leave + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class plan_leave_plan extends external_api { - public static function leave_plan_parameters() { + /** + * Parameters for leave_plan. + * @return external_function_parameters + */ + public static function leave_plan_parameters(): external_function_parameters { return new external_function_parameters([]); } + /** + * Leave your plan + * + * @return void + * @throws \moodle_exception when user is only member left in plan + */ public static function leave_plan() { global $DB, $USER; $planid = plan_helper::get_plan_id($USER->id); + // TODO: remove useless check. if (plan_helper::get_access_type($USER->id, $planid) === PLAN_ACCESS_TYPE::NONE) { throw new \moodle_exception('User is not a member of this plan'); } @@ -100,6 +117,11 @@ public static function leave_plan() { NOTIF_TRIGGER::PLAN_LEFT ); } + + /** + * Returns the structure of nothing. + * @return null + */ public static function leave_plan_returns() { return null; } diff --git a/lbplanner/services/plan/remove_user.php b/lbplanner/services/plan/remove_user.php index c18a751c..2cd75cfd 100644 --- a/lbplanner/services/plan/remove_user.php +++ b/lbplanner/services/plan/remove_user.php @@ -23,15 +23,30 @@ /** * Remove a user from your plan + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class plan_remove_user extends external_api { - public static function remove_user_parameters() { + /** + * Parameters for remove_user. + * @return external_function_parameters + */ + public static function remove_user_parameters(): external_function_parameters { return new external_function_parameters([ 'userid' => new external_value(PARAM_INT, 'ID of the user to remove', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), ]); } - public static function remove_user($userid, $planid) { + /** + * Remove a user from your plan + * + * @param int $userid ID of the user to remove + * @return void + */ + public static function remove_user(int $userid) { global $DB, $USER; self::validate_parameters( @@ -44,6 +59,10 @@ public static function remove_user($userid, $planid) { plan_helper::remove_user($planid, $USER->id, $userid); } + /** + * Returns the structure of nothing. + * @return null + */ public static function remove_user_returns() { return null; } diff --git a/lbplanner/services/plan/set_deadline.php b/lbplanner/services/plan/set_deadline.php index fcb77b2f..9ad07a8f 100644 --- a/lbplanner/services/plan/set_deadline.php +++ b/lbplanner/services/plan/set_deadline.php @@ -22,28 +22,37 @@ use local_lbplanner\helpers\plan_helper; /** - * Set the deadline for a module + * Set the deadline for a module. + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class plan_set_deadline extends external_api { + /** + * Parameters for set_deadline. + * @return external_function_parameters + */ public static function set_deadline_parameters() { return new external_function_parameters([ 'moduleid' => new external_value( PARAM_INT, - 'The ID of the module the deadline is for', + 'ID of the module the deadline is for', VALUE_REQUIRED, null, NULL_NOT_ALLOWED ), 'deadlinestart' => new external_value( PARAM_INT, - 'The start of the deadline', + 'Start of the deadline', VALUE_REQUIRED, null, NULL_NOT_ALLOWED ), 'deadlineend' => new external_value( PARAM_INT, - 'The end of the deadline', + 'End of the deadline', VALUE_REQUIRED, null, NULL_NOT_ALLOWED @@ -51,7 +60,16 @@ public static function set_deadline_parameters() { ]); } - public static function set_deadline($moduleid, $deadlinestart, $deadlineend) { + /** + * Set the deadline for a module + * + * @param int $moduleid ID of the module the deadline is for + * @param int $deadlinestart Start of the deadline + * @param int $deadlineend End of the deadline + * @return void + * @throws \moodle_exception when access denied + */ + public static function set_deadline(int $moduleid, int $deadlinestart, int $deadlineend): external_function_parameters { global $DB, $USER; self::validate_parameters( @@ -69,9 +87,9 @@ public static function set_deadline($moduleid, $deadlinestart, $deadlineend) { throw new \moodle_exception('Access denied'); } - // if a deadline already exists, + // If a deadline already exists. if (!$DB->record_exists(plan_helper::DEADLINES_TABLE, ['moduleid' => $moduleid, 'planid' => $planid])) { - // update the existing deadline + // Update the existing deadline. $deadline = $DB->get_record(plan_helper::DEADLINES_TABLE, ['moduleid' => $moduleid, 'planid' => $planid]); $deadline->deadlinestart = $deadlinestart; @@ -79,7 +97,7 @@ public static function set_deadline($moduleid, $deadlinestart, $deadlineend) { $DB->update_record(plan_helper::DEADLINES_TABLE, $deadline); } else { - // otherwise insert a new one + // Otherwise insert a new one. $deadline = new \stdClass(); $deadline->planid = $planid; @@ -91,6 +109,10 @@ public static function set_deadline($moduleid, $deadlinestart, $deadlineend) { } } + /** + * Returns the structure of nothing. + * @return null + */ public static function set_deadline_returns() { return null; } diff --git a/lbplanner/services/plan/update_access.php b/lbplanner/services/plan/update_access.php index 5c8eea72..b4a79e86 100644 --- a/lbplanner/services/plan/update_access.php +++ b/lbplanner/services/plan/update_access.php @@ -24,13 +24,22 @@ /** * Update the access of the plan. + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class plan_update_access extends external_api { - public static function update_access_parameters() { + /** + * Parameters for update_access. + * @return external_function_parameters + */ + public static function update_access_parameters(): external_function_parameters { return new external_function_parameters([ 'accesstype' => new external_value( PARAM_INT, - 'New access type', + 'New access type '.PLAN_ACCESS_TYPE::format(), VALUE_REQUIRED, null, NULL_NOT_ALLOWED @@ -45,7 +54,16 @@ public static function update_access_parameters() { ]); } - public static function update_access($accesstype, $memberid) { + /** + * Update the access of the plan. + * + * @param int $accesstype new access type + * @see PLAN_ACCESS_TYPE + * @param int $memberid ID of the member to have their access changed + * @return void + * @throws \moodle_exception when access denied, type not valid or insufficient permissions + */ + public static function update_access(int $accesstype, int $memberid) { global $DB, $USER; self::validate_parameters( @@ -59,7 +77,7 @@ public static function update_access($accesstype, $memberid) { throw new \moodle_exception('Access denied'); } - $accesstypeobj = PLAN_ACCESS_TYPE::tryFrom($accesstype); + $accesstypeobj = PLAN_ACCESS_TYPE::try_from($accesstype); if ($accesstypeobj === null) { throw new \moodle_exception('Access type not valid'); @@ -83,6 +101,10 @@ public static function update_access($accesstype, $memberid) { $DB->update_record(plan_helper::ACCESS_TABLE, $access); } + /** + * Returns the structure of nothing. + * @return null + */ public static function update_access_returns() { return null; } diff --git a/lbplanner/services/plan/update_plan.php b/lbplanner/services/plan/update_plan.php index 63418e1f..586e4e42 100644 --- a/lbplanner/services/plan/update_plan.php +++ b/lbplanner/services/plan/update_plan.php @@ -22,10 +22,19 @@ use local_lbplanner\helpers\plan_helper; /** - * Update the plan of the given user. + * Update the plan details. + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class plan_update_plan extends external_api { - public static function update_plan_parameters() { + /** + * Parameters for update_plan. + * @return external_function_parameters + */ + public static function update_plan_parameters(): external_function_parameters { return new external_function_parameters([ 'planname' => new external_value( PARAM_TEXT, @@ -44,7 +53,15 @@ public static function update_plan_parameters() { ]); } - public static function update_plan($planname, $enableek) { + /** + * Update the plan details. + * + * @param string $planname Name of the Plan + * @param bool $enableek Whether EK is enabled for the plan + * @return void + * @throws Exception when access denied + */ + public static function update_plan(string $planname, bool $enableek) { global $DB, $USER; self::validate_parameters( @@ -65,6 +82,10 @@ public static function update_plan($planname, $enableek) { $DB->update_record(plan_helper::TABLE, $plan); } + /** + * Returns the structure of nothing. + * @return null + */ public static function update_plan_returns() { return null; } diff --git a/lbplanner/services/user/delete_user.php b/lbplanner/services/user/delete_user.php index 422a4a68..9a7b9dd0 100644 --- a/lbplanner/services/user/delete_user.php +++ b/lbplanner/services/user/delete_user.php @@ -31,9 +31,11 @@ * Removes all user data stored by the lbplanner app. * * Admins can pass a userid to delete the user with the given id - * @package local_lbplanner - * @copyright 2023 necodeIT - * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @package local_lbplanner + * @subpackage services_user + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class user_delete_user extends external_api { /** diff --git a/lbplanner/services/user/get_all_users.php b/lbplanner/services/user/get_all_users.php index 6fdd9a2a..9ab5bf8d 100644 --- a/lbplanner/services/user/get_all_users.php +++ b/lbplanner/services/user/get_all_users.php @@ -30,9 +30,10 @@ /** * Gets all users registered by the lbplanner app. * - * @package local_lbplanner - * @copyright 2023 necodeIT - * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package local_lbplanner + * @subpackage services_user + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class user_get_all_users extends external_api { /** diff --git a/lbplanner/services/user/get_user.php b/lbplanner/services/user/get_user.php index 4849810d..fee2bd95 100644 --- a/lbplanner/services/user/get_user.php +++ b/lbplanner/services/user/get_user.php @@ -31,9 +31,11 @@ * Get the data for a user. * * Get the data for a user. param userid (optional) gives back the user data with the given ID - * @package local_lbplanner - * @copyright 2023 necodeIT - * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @package local_lbplanner + * @subpackage services_user + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class user_get_user extends external_api { /** diff --git a/lbplanner/services/user/register_user.php b/lbplanner/services/user/register_user.php index ed405792..aed07f2d 100644 --- a/lbplanner/services/user/register_user.php +++ b/lbplanner/services/user/register_user.php @@ -34,9 +34,10 @@ /** * Register a new user in the lbplanner app. * - * @package local_lbplanner - * @copyright 2023 necodeIT - * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package local_lbplanner + * @subpackage services_user + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class user_register_user extends external_api { /** @@ -64,7 +65,7 @@ public static function register_user_parameters(): external_function_parameters VALUE_DEFAULT, 0, NULL_NOT_ALLOWED, - ) + ), ]); } diff --git a/lbplanner/services/user/update_user.php b/lbplanner/services/user/update_user.php index 9abc4676..1a2ae9d8 100644 --- a/lbplanner/services/user/update_user.php +++ b/lbplanner/services/user/update_user.php @@ -29,9 +29,10 @@ /** * Update the data for a user. * - * @package local_lbplanner - * @copyright 2023 necodeIT - * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package local_lbplanner + * @subpackage services_user + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class user_update_user extends external_api { /** diff --git a/lbplanner/settings.php b/lbplanner/settings.php index 24b59fd4..d892dec4 100644 --- a/lbplanner/settings.php +++ b/lbplanner/settings.php @@ -13,6 +13,13 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * Defines some settings + * + * @package local_lbplanner + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ defined('MOODLE_INTERNAL') || die; diff --git a/lbplanner/version.php b/lbplanner/version.php index 68f4a001..d4177cbc 100644 --- a/lbplanner/version.php +++ b/lbplanner/version.php @@ -13,6 +13,13 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * Defines versioning + * + * @package local_lbplanner + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ defined('MOODLE_INTERNAL') || die(); From cf3ba62ad2c8cf1677eb65228b124cbec80bc7c5 Mon Sep 17 00:00:00 2001 From: Muhi <49810240+mkocagoel@users.noreply.github.com> Date: Tue, 27 Feb 2024 15:03:34 +0100 Subject: [PATCH 23/92] Lp 204 add custom fields for each activity (#73) * Added dependency to the local_modcustomfield plugin * Testing compatibility with customfields * So i tried to use the customfield version from the plugin and found out that it uses the customfield from moodle itself aswell. Now it works. small tweaks needed * added testing * Fixed bug Since moodle does save the plugin list as a Map in an array and i didnt know it the function never executed * Minor Tweaks * Further Tweaks * tweaking the service itself * removed function. Not necessary * Last tweaks before merge * Tweaking --- lbplanner/classes/helpers/config_helper.php | 79 ++++++++++++++++++--- lbplanner/db/install.php | 9 +-- lbplanner/db/upgrade.php | 5 +- lbplanner/version.php | 6 +- 4 files changed, 82 insertions(+), 17 deletions(-) diff --git a/lbplanner/classes/helpers/config_helper.php b/lbplanner/classes/helpers/config_helper.php index 7261a3c7..57c65be4 100644 --- a/lbplanner/classes/helpers/config_helper.php +++ b/lbplanner/classes/helpers/config_helper.php @@ -16,6 +16,11 @@ namespace local_lbplanner\helpers; +use core_component; +use core_customfield\category_controller; +use customfield_select\field_controller; +use local_modcustomfields\customfield\mod_handler; + /** * Helper class for config * @@ -30,25 +35,81 @@ class config_helper { */ public static function set_default_active_year() { $currentmonth = idate('m'); - // TODO: At least one of these comments ↓ is clearly wrong. Muhi's thing to fix. + $currentyear = idate('Y') % 100; + $lastyear = $currentyear - 1; + $nextyear = $currentyear + 1; + // Adding the default active year, when the plugin is installed for the first time. + // If the current month is between August and December, the default active year is set to current year and the next year. if ($currentmonth >= 8 && $currentmonth <= 12) { - // Adding the default active year, when the plugin is installed for the first time. set_config( 'defaultactiveyear', - substr(strval(idate('Y')), 2) - .'/'. - substr(strval(idate('Y') + 1), 2), + $currentyear . '/' . $nextyear, 'local_lbplanner' ); + // If the current month is between January and July, the default active year is set to the previous year and the + // current year. } else { - // Adding the default active year, when the plugin is installed for the first time. set_config( 'defaultactiveyear', - substr(strval(idate('Y') - 1), 2) - .'/'. - substr(strval(idate('Y')), 2), + $lastyear . '/' . $currentyear, 'local_lbplanner' ); } } + + /** + * Adds a customfield to moodle for each activity where teachers can select GK EK or both. + * + * Default value is GK. + * @throws \coding_exception + * @throws \moodle_exception + * @throws \coding_exception + */ + public static function add_customfield(): void { + // Check if the category is already created and only create it if it doesn't exist. + // Check if plugin "modcustomfields" is installed and create the category and the custom field. + if (!get_config('local_lbplanner', 'categoryid')) { + + if (array_key_exists('modcustomfields', core_component::get_plugin_list('local'))) { + + $handler = mod_handler::create(); + $categoryid = $handler->create_category('LB Planner'); + + set_config('categoryid', $categoryid, 'local_lbplanner'); + $categorycontroller = category_controller::create($categoryid, null, $handler); + $categorycontroller->save(); + + // Dont ask me why but moodle doesnt allow me to just insert the String "select" into the type field. + $record = new \stdClass(); + $record->type = 'select'; + + $fieldcontroller = field_controller::create(0, $record, $categorycontroller); + // Added the default attributes for the custom field. + $fieldcontroller->set('name', 'LB Planner Task Type'); + $fieldcontroller->set('description', 'Tracks whether the task is GK/EK/GKandEK/TEST/SA/M'); + $fieldcontroller->set('type', 'select'); + // Because moodle wants me to save the configdata as a json string, I have to do this. + // I don't know why moodle does this, but it does. I don't like it. but I have to do it. so I do it. + $fieldcontroller->set( + 'configdata', + '{"required":"1","uniquevalues":"0","options":"GK\r\nEK\r\nGK and EK\r\nTEST\r\nSA\r\nM", + "defaultvalue":"GK","locked":"0","visibility":"2"}' + ); + $fieldcontroller->set('shortname', 'lb_planner_gk_ek'); + $fieldcontroller->save(); + } + } + } + + /** + * Get the category id from the config + * @return int the category id if it is set, -1 otherwise + */ + public static function get_category_id(): int { + if (!get_config('local_lbplanner', 'categoryid')) { + return -1; + } else { + return intval(get_config('local_lbplanner', 'categoryid')); + } + } } diff --git a/lbplanner/db/install.php b/lbplanner/db/install.php index 2e0cfb9f..b37862df 100644 --- a/lbplanner/db/install.php +++ b/lbplanner/db/install.php @@ -22,18 +22,15 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\config_helper; + defined('MOODLE_INTERNAL') || die; /** * Runs when plugin is first installed - * right now, it does nothing */ function xmldb_local_lbplanner_install() { - global $DB; + config_helper::set_default_active_year(); + config_helper::add_customfield(); } - -config_helper::set_default_active_year(); - diff --git a/lbplanner/db/upgrade.php b/lbplanner/db/upgrade.php index a072dc19..ee29a436 100644 --- a/lbplanner/db/upgrade.php +++ b/lbplanner/db/upgrade.php @@ -32,7 +32,10 @@ * @return bool true */ function xmldb_local_lbplanner_upgrade($oldversion): bool { - config_helper::set_default_active_year(); + if ($oldversion < 2024022700) { + config_helper::set_default_active_year(); + config_helper::add_customfield(); + } return true; } diff --git a/lbplanner/version.php b/lbplanner/version.php index d4177cbc..d3e51d99 100644 --- a/lbplanner/version.php +++ b/lbplanner/version.php @@ -27,6 +27,10 @@ $plugin->component = 'local_lbplanner'; $plugin->release = 'Alpha v.'.$release; -$plugin->version = 2023030601; +$plugin->version = 2024022700; +$plugin->dependencies = [ + // Depend upon version 2023110600 of local_modcustomfields. + 'local_modcustomfields' => 2023110600, +]; set_config('release', $release, 'local_lbplanner'); From 3f44810867efe15a96a548412c4db3b120114c55 Mon Sep 17 00:00:00 2001 From: Muhi <49810240+mkocagoel@users.noreply.github.com> Date: Tue, 27 Feb 2024 15:26:36 +0100 Subject: [PATCH 24/92] Fixing CI errors (#74) * Fixing CI errors * Comforting Riedler --- lbplanner/classes/helpers/course_helper.php | 59 +++++++++++-------- lbplanner/classes/helpers/feedback_helper.php | 22 ++++--- lbplanner/classes/helpers/invite_helper.php | 9 +-- lbplanner/classes/helpers/modules_helper.php | 14 ++--- .../classes/helpers/notifications_helper.php | 19 +++--- lbplanner/classes/helpers/plan_helper.php | 46 ++++++++++----- lbplanner/classes/helpers/user_helper.php | 40 ++++++++----- lbplanner/db/install.php | 2 - lbplanner/services/courses/update_course.php | 2 +- 9 files changed, 125 insertions(+), 88 deletions(-) diff --git a/lbplanner/classes/helpers/course_helper.php b/lbplanner/classes/helpers/course_helper.php index b2219af2..2bbfcc40 100644 --- a/lbplanner/classes/helpers/course_helper.php +++ b/lbplanner/classes/helpers/course_helper.php @@ -23,10 +23,10 @@ /** * Helper class for courses * - * @package local_lbplanner + * @package local_lbplanner * @subpackage helpers - * @copyright 2024 NecodeIT - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class course_helper { @@ -38,23 +38,24 @@ class course_helper { /** * A list of nice colors to choose from :) */ - const COLORS = [ - "#f50057", - "#536dfe", - "#f9a826", - "#00bfa6", - "#9b59b6", - "#37bbca", - "#e67e22", - "#37CA48", - "#CA3737", - "#B5CA37", - "#37CA9E", - "#3792CA", - "#376ECA", - "#8B37CA", - "#CA37B9", - ]; + const COLORS + = [ + "#f50057", + "#536dfe", + "#f9a826", + "#00bfa6", + "#9b59b6", + "#37bbca", + "#e67e22", + "#37CA48", + "#CA3737", + "#B5CA37", + "#37CA9E", + "#3792CA", + "#376ECA", + "#8B37CA", + "#CA37B9", + ]; /** * constant that represents a disabled course */ @@ -72,8 +73,8 @@ class course_helper { * @return string the current year the last 2 digits (20/20) * @throws dml_exception */ - public static function get_current_year() : string { - if (strpos(get_config('local_lbplanner', 'activeyear'), '/' ) !== false) { + public static function get_current_year(): string { + if (strpos(get_config('local_lbplanner', 'activeyear'), '/') !== false) { return get_config('local_lbplanner', 'activeyear'); } return get_config('local_lbplanner', 'defaultactiveyear'); @@ -83,11 +84,12 @@ public static function get_current_year() : string { * Get course from lbpanner DB * * @param int $courseid id of the course in lbplanner - * @param int $userid id of the user + * @param int $userid id of the user + * * @return stdClass course from lbplanner * @throws dml_exception */ - public static function get_lbplanner_course(int $courseid, int $userid) : stdClass { + public static function get_lbplanner_course(int $courseid, int $userid): stdClass { global $DB; return $DB->get_record(self::LBPLANNER_COURSE_TABLE, ['courseid' => $courseid, 'userid' => $userid]); } @@ -96,27 +98,32 @@ public static function get_lbplanner_course(int $courseid, int $userid) : stdCla * Check if the user is enrolled in the course * * @param int $courseid course id - * @param int $userid user id + * @param int $userid user id + * * @return bool true if the user is enrolled */ - public static function check_access(int $courseid, int $userid) : bool { + public static function check_access(int $courseid, int $userid): bool { $context = context_course::instance($courseid); return is_enrolled($context, $userid, '', true); } + /** * gets the fullname from a course * * @param int $courseid the course id + * * @return string the fullname of the course * @throws dml_exception */ public static function get_fullname(int $courseid): string { return get_course($courseid)->fullname; } + /** * Check if the course is from the current year * * @param int $courseid the course id + * * @return bool true if the course is from the current year * @throws dml_exception */ diff --git a/lbplanner/classes/helpers/feedback_helper.php b/lbplanner/classes/helpers/feedback_helper.php index 0473277d..9322864e 100644 --- a/lbplanner/classes/helpers/feedback_helper.php +++ b/lbplanner/classes/helpers/feedback_helper.php @@ -27,10 +27,10 @@ /** * Helper class for feedback * - * @package local_lbplanner + * @package local_lbplanner * @subpackage helpers - * @copyright 2024 NecodeIT - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class feedback_helper { @@ -44,7 +44,6 @@ class feedback_helper { */ const STATUS_READ = 1; - /** * The name of the table which is used by LP to store feedback in */ @@ -55,7 +54,7 @@ class feedback_helper { * * @return external_single_structure The structure of a module. */ - public static function structure() : external_single_structure { + public static function structure(): external_single_structure { return new external_single_structure( [ 'content' => new external_value(PARAM_TEXT, 'Content of the feedback'), @@ -71,33 +70,38 @@ public static function structure() : external_single_structure { ] ); } + /** * Gives back the feedback of the given feedbackid * * @param int $feedbackid The id of the feedback + * * @return stdClass The feedback */ - public static function get_feedback(int $feedbackid) : stdClass { + public static function get_feedback(int $feedbackid): stdClass { global $DB; return $DB->get_record(self::LBPLANNER_FEEDBACK_TABLE, ['id' => $feedbackid]); } + /** * Checks if the user has access to feedback * * @throws \moodle_exception when the user has no access */ public static function assert_admin_access() { - if (!has_capability(user_helper::CAPABILITY_ADMIN, \context_system::instance()) && - !has_capability(user_helper::CAPABILITY_MANAGER, \context_system::instance())) { + if (!has_capability(user_helper::CAPABILITY_ADMIN, \context_system::instance()) + && !has_capability(user_helper::CAPABILITY_MANAGER, \context_system::instance()) + ) { throw new \moodle_exception('Acces denied'); } } /** * Returns all feedback records. + * * @return array all feedback records */ - public static function get_all_feedbacks() : array { + public static function get_all_feedbacks(): array { global $DB; return $DB->get_records(self::LBPLANNER_FEEDBACK_TABLE); } diff --git a/lbplanner/classes/helpers/invite_helper.php b/lbplanner/classes/helpers/invite_helper.php index a90c8e41..184cdfe7 100644 --- a/lbplanner/classes/helpers/invite_helper.php +++ b/lbplanner/classes/helpers/invite_helper.php @@ -22,18 +22,19 @@ /** * Helper class for plan invites * - * @package local_lbplanner + * @package local_lbplanner * @subpackage helpers - * @copyright 2024 NecodeIT - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class invite_helper { /** * Returns the data structure of an invite. + * * @return external_single_structure The data structure of an invite. */ - public static function structure() : external_single_structure { + public static function structure(): external_single_structure { return new external_single_structure( [ 'id' => new external_value(PARAM_INT, 'invite ID'), diff --git a/lbplanner/classes/helpers/modules_helper.php b/lbplanner/classes/helpers/modules_helper.php index be7120c6..aa0c2179 100644 --- a/lbplanner/classes/helpers/modules_helper.php +++ b/lbplanner/classes/helpers/modules_helper.php @@ -156,7 +156,7 @@ class modules_helper { * * @return external_single_structure The structure of a module. */ - public static function structure() : external_single_structure { + public static function structure(): external_single_structure { return new external_single_structure( [ 'moduleid' => new external_value(PARAM_INT, 'Module ID'), @@ -180,7 +180,7 @@ public static function structure() : external_single_structure { * @param int $gradepass The grade to pass the module. * @return integer The enum value for the grade. */ - public static function determin_uinified_grade(int $grade, int $maxgrade, int $mingrade, int $gradepass) : int { + public static function determin_uinified_grade(int $grade, int $maxgrade, int $mingrade, int $gradepass): int { if ($grade < $gradepass) { return MODULE_GRADE::RIP; } @@ -210,7 +210,7 @@ public static function determin_uinified_grade(int $grade, int $maxgrade, int $m * @param bool $late Whether the module is late. * @return integer The enum value for the module status. */ - public static function map_status(bool $submitted, bool $done, bool $late) : int { + public static function map_status(bool $submitted, bool $done, bool $late): int { if ($done) { return MODULE_STATUS::DONE; } else if ($submitted) { @@ -228,7 +228,7 @@ public static function map_status(bool $submitted, bool $done, bool $late) : int * @param string $modulename The name of the module. * @return integer The enum value for the module type. */ - public static function determin_type(string $modulename) : int { + public static function determin_type(string $modulename): int { // Convert module name to uppercase. $modulename = strtoupper($modulename); @@ -262,7 +262,7 @@ public static function determin_type(string $modulename) : int { * @param int $courseid The id of the course. * @return string The url of the module. */ - public static function get_module_url(int $moduleid, int $courseid) : string { + public static function get_module_url(int $moduleid, int $courseid): string { global $DB; $view = $DB->get_record( @@ -280,7 +280,7 @@ public static function get_module_url(int $moduleid, int $courseid) : string { * @param int $userid The id of the user. * @return array The module. */ - public static function get_module(int $moduleid, int $userid) : array { + public static function get_module(int $moduleid, int $userid): array { global $DB; date_default_timezone_set('UTC'); @@ -365,7 +365,7 @@ public static function get_module(int $moduleid, int $userid) : array { * @param bool $ekenabled Whether EK modules should be included. * @return array The modules. */ - public static function get_all_course_modules(int $courseid, int $userid, bool $ekenabled) : array { + public static function get_all_course_modules(int $courseid, int $userid, bool $ekenabled): array { global $DB; $mdlmodules = $DB->get_records(self::ASSIGN_TABLE, ['course' => $courseid]); diff --git a/lbplanner/classes/helpers/notifications_helper.php b/lbplanner/classes/helpers/notifications_helper.php index b81a9ec7..9cddb1d4 100644 --- a/lbplanner/classes/helpers/notifications_helper.php +++ b/lbplanner/classes/helpers/notifications_helper.php @@ -16,10 +16,10 @@ /** * Provides helper classes for notification related stuff * - * @package local_lbplanner + * @package local_lbplanner * @subpackage helpers - * @copyright 2024 NecodeIT - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace local_lbplanner\helpers; @@ -91,11 +91,11 @@ class notifications_helper { * * @return external_single_structure The data structure of a notification. */ - public static function structure() : external_single_structure { + public static function structure(): external_single_structure { return new external_single_structure([ - 'status' => new external_value(PARAM_INT, 'The status of the notification '.NOTIF_STATUS::format()), + 'status' => new external_value(PARAM_INT, 'The status of the notification ' . NOTIF_STATUS::format()), 'type' => - new external_value(PARAM_INT, 'The type of the event that triggered the notification '.NOTIF_TRIGGER::format()), + new external_value(PARAM_INT, 'The type of the event that triggered the notification ' . NOTIF_TRIGGER::format()), 'info' => new external_value(PARAM_INT, 'Additional information about the notification'), 'userid' => new external_value(PARAM_INT, 'The ID of the user for whom the notification is for'), 'notificationid' => new external_value(PARAM_INT, 'The ID of the notification', NULL_NOT_ALLOWED), @@ -108,11 +108,12 @@ public static function structure() : external_single_structure { * Notifies the given user about the given event, with the given info. * * @param int $userid The user to notify. - * @param int $info Additional information as stringified json. - * @param int $type The type of notification. + * @param int $info Additional information as stringified json. + * @param int $type The type of notification. + * * @return integer The id of the notification. */ - public static function notify_user( int $userid, int $info, int $type ): int { + public static function notify_user(int $userid, int $info, int $type): int { global $DB; $notification = new \stdClass(); diff --git a/lbplanner/classes/helpers/plan_helper.php b/lbplanner/classes/helpers/plan_helper.php index 4970a1f5..04a4606d 100644 --- a/lbplanner/classes/helpers/plan_helper.php +++ b/lbplanner/classes/helpers/plan_helper.php @@ -16,10 +16,10 @@ /** * Provides helper classes for any tables related with the planning function of the app * - * @package local_lbplanner + * @package local_lbplanner * @subpackage helpers - * @copyright 2024 NecodeIT - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace local_lbplanner\helpers; @@ -119,9 +119,10 @@ class plan_helper { * Returns a list of user id's that are members of the plan. * * @param int $planid The id of the plan. + * * @return array An array of user id's. */ - public static function get_plan_members(int $planid):array { + public static function get_plan_members(int $planid): array { global $DB; $members = $DB->get_records(self::ACCESS_TABLE, ['planid' => $planid]); return $members; @@ -131,9 +132,10 @@ public static function get_plan_members(int $planid):array { * Returns the user id of the owner of the plan. * * @param int $planid The id of the plan. + * * @return integer The user id of the owner. */ - public static function get_owner(int $planid):int { + public static function get_owner(int $planid): int { global $DB; $owner = $DB->get_field( @@ -148,9 +150,10 @@ public static function get_owner(int $planid):int { * Returns the id of the plan that the given user is a member of. * * @param int $userid The id of the user. + * * @return integer The id of the plan the given user is a member of. */ - public static function get_plan_id(int $userid):int { + public static function get_plan_id(int $userid): int { global $DB; $planid = $DB->get_field(self::ACCESS_TABLE, 'planid', ['userid' => $userid]); return $planid; @@ -161,6 +164,7 @@ public static function get_plan_id(int $userid):int { * * @param int $userid The id of the user. * @param int $planid The id of the plan. + * * @return int The access type of the given user for the given plan. */ public static function get_access_type(int $userid, int $planid): int { @@ -184,9 +188,10 @@ public static function get_access_type(int $userid, int $planid): int { * * @param int $planid The id of the plan. * @param int $userid The id of the user. + * * @return boolean True if the given user has editing permissions for the given plan. */ - public static function check_edit_permissions(int $planid, int $userid):bool { + public static function check_edit_permissions(int $planid, int $userid): bool { $access = self::get_access_type($userid, $planid); return $access === PLAN_ACCESS_TYPE::OWNER || $access === PLAN_ACCESS_TYPE::WRITE; @@ -196,6 +201,7 @@ public static function check_edit_permissions(int $planid, int $userid):bool { * Returns a list of all deadlines for the given plan. * * @param int $planid The id of the plan. + * * @return array A list of all deadlines for the given plan. */ public static function get_deadlines(int $planid): array { @@ -220,9 +226,10 @@ public static function get_deadlines(int $planid): array { * Retrieves all the information available about the given plan. * * @param int $planid The id of the plan. + * * @return array An array containing all the information available about the given plan. */ - public static function get_plan(int $planid) : array { + public static function get_plan(int $planid): array { global $DB; $plan = $DB->get_record(self::TABLE, ['id' => $planid]); @@ -249,7 +256,7 @@ public static function get_plan(int $planid) : array { * * @return external_single_structure The structure. */ - public static function plan_structure() : external_single_structure { + public static function plan_structure(): external_single_structure { return new external_single_structure( [ 'name' => new external_value(PARAM_TEXT, 'Name of the plan'), @@ -268,7 +275,7 @@ public static function plan_structure() : external_single_structure { new external_single_structure( [ 'userid' => new external_value(PARAM_INT, 'The id of the user'), - 'accesstype' => new external_value(PARAM_INT, 'The role of the user '.PLAN_ACCESS_TYPE::format()), + 'accesstype' => new external_value(PARAM_INT, 'The role of the user ' . PLAN_ACCESS_TYPE::format()), ] ) ), @@ -281,9 +288,10 @@ public static function plan_structure() : external_single_structure { * * @param int $planid The id of the plan. * @param int $userid The id of the user. + * * @return integer The id of the new copy of the plan. */ - public static function copy_plan(int $planid, int $userid) : int { + public static function copy_plan(int $planid, int $userid): int { global $DB; $user = user_helper::get_mdl_user_info($userid); @@ -302,15 +310,17 @@ public static function copy_plan(int $planid, int $userid) : int { } return $newplanid; } + /** * Removes the user from the given plan. * - * @param int $planid the plan id. - * @param int $userid the user id. + * @param int $planid the plan id. + * @param int $userid the user id. * @param int $removeuserid the user id to remove. + * * @return int The ID of the new plan for the removed user */ - public static function remove_user(int $planid, int $userid, int $removeuserid) : int { + public static function remove_user(int $planid, int $userid, int $removeuserid): int { global $DB; if (self::get_owner($planid) != $userid) { throw new \moodle_exception('Access denied'); @@ -342,24 +352,28 @@ public static function remove_user(int $planid, int $userid, int $removeuserid) return $newplanid; } + /** * Get all invites that have been sent by the user. * * @param int $userid ID of the sender + * * @return array an array of invites sent by the user */ - public static function get_invites_send(int $userid):array { + public static function get_invites_send(int $userid): array { global $DB; $invites = $DB->get_records(self::INVITES_TABLE, ['inviterid' => $userid]); return $invites; } + /** * Get all invites that have been received by the user. * * @param int $userid ID of the receiver + * * @return array an array of invites received by the user */ - public static function get_invites_received(int $userid):array { + public static function get_invites_received(int $userid): array { global $DB; $invites = $DB->get_records(self::INVITES_TABLE, ['inviteeid' => $userid]); return $invites; diff --git a/lbplanner/classes/helpers/user_helper.php b/lbplanner/classes/helpers/user_helper.php index 80d41d12..23305e2c 100644 --- a/lbplanner/classes/helpers/user_helper.php +++ b/lbplanner/classes/helpers/user_helper.php @@ -27,10 +27,10 @@ /** * Provides helper methods for user related stuff. * - * @package local_lbplanner + * @package local_lbplanner * @subpackage helpers - * @copyright 2024 NecodeIT - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class user_helper { @@ -57,12 +57,13 @@ class user_helper { /** * Maps CAPABILITY shortnames to their corresponding enum value. */ - const CAPABILITY_ENUMS = [ - self::CAPABILITY_ADMIN => 1, - self::CAPABILITY_MANAGER => 2, - self::CAPABILITY_TEACHER => 4, - self::CAPABILITY_STUDENT => 8, - ]; + const CAPABILITY_ENUMS + = [ + self::CAPABILITY_ADMIN => 1, + self::CAPABILITY_MANAGER => 2, + self::CAPABILITY_TEACHER => 4, + self::CAPABILITY_STUDENT => 8, + ]; /** * Name of the user database @@ -73,9 +74,10 @@ class user_helper { * Checks if the current user has access to the given user id. * * @param int $userid The id of the user to check access for. + * * @return bool True if the current user has access to the given user id, false otherwise. */ - public static function check_access(int $userid):bool { + public static function check_access(int $userid): bool { global $USER; return $USER->id == $userid; } @@ -85,6 +87,7 @@ public static function check_access(int $userid):bool { * Throws an exception if the current user does not have access. * * @param int $userid The id of the user to check access for. + * * @return void * @throws moodle_exception */ @@ -97,7 +100,9 @@ public static function assert_access(int $userid): void { /** * Checks if the given user is an admin. + * * @param int $userid The id of the user to check. + * * @return bool True if the given user is an admin, false otherwise. * @throws coding_exception * @throws dml_exception @@ -106,6 +111,7 @@ public static function is_admin(int $userid): bool { $context = context_system::instance(); return has_capability(self::CAPABILITY_ADMIN, $context, $userid, false); } + /** * Gives back a bitmask which represents the capabilities of the given user. * 0 = no capabilities @@ -127,11 +133,12 @@ public static function is_admin(int $userid): bool { * * * @param int $userid The id of the user to check access for. + * * @return int The capabilities of the given user. * @throws coding_exception * @throws dml_exception */ - public static function get_user_capability_bitmask(int $userid) : int { + public static function get_user_capability_bitmask(int $userid): int { $capabilities = 0; $context = context_system::instance(); if (has_capability(self::CAPABILITY_ADMIN, $context, $userid, false)) { @@ -148,10 +155,12 @@ public static function get_user_capability_bitmask(int $userid) : int { } return $capabilities; } + /** * Checks if the given user exists in the LB_PLANNER_USER database. * * @param int $userid The id of the user to check. + * * @return bool True if the user exists, false otherwise. * @throws dml_exception */ @@ -171,6 +180,7 @@ public static function check_user_exists(int $userid): bool { * ``` * * @param int $userid The id of the user to retrieve. + * * @return stdClass The user with the given id. * @throws dml_exception */ @@ -181,9 +191,9 @@ public static function get_user(int $userid): stdClass { /** * Retrieves the full name of the user with the given id. - * @deprecated not in use * * @return string The full name of the user with the given id. + * @deprecated not in use */ public static function get_complete_name(): string { global $USER; @@ -192,10 +202,12 @@ public static function get_complete_name(): string { /** * This Function is used to get the user picture of a user. + * * @param int $userid The id of the user to retrieve the picture for. - * @throws coding_exception - * @throws dml_exception + * * @return string The url of the user picture. + * @throws dml_exception + * @throws coding_exception */ public static function get_mdl_user_picture(int $userid): string { global $PAGE; diff --git a/lbplanner/db/install.php b/lbplanner/db/install.php index b37862df..4cef3c56 100644 --- a/lbplanner/db/install.php +++ b/lbplanner/db/install.php @@ -25,8 +25,6 @@ use local_lbplanner\helpers\config_helper; -defined('MOODLE_INTERNAL') || die; - /** * Runs when plugin is first installed */ diff --git a/lbplanner/services/courses/update_course.php b/lbplanner/services/courses/update_course.php index c37c592a..5010779d 100644 --- a/lbplanner/services/courses/update_course.php +++ b/lbplanner/services/courses/update_course.php @@ -62,7 +62,7 @@ public static function update_course_parameters(): external_function_parameters * @throws invalid_parameter_exception * @throws moodle_exception */ - public static function update_course( $courseid, $color, $shortname, $enabled): void { + public static function update_course($courseid, $color, $shortname, $enabled): void { global $DB , $USER; self::validate_parameters( From a3929b38da1a98ab96764238fcc7913c61ae33cc Mon Sep 17 00:00:00 2001 From: Riedler Date: Wed, 13 Mar 2024 08:09:51 +0100 Subject: [PATCH 25/92] LP-211: fix enums not being loaded (#78) * moved enums into their own files (plus EnumCase too) * removed unneeded moodle internal checks * fixed accidental tab indents * moved more enums out of modules_helper * lots of smaller formatting and CI fixes * more CI fixes --- lbplanner/classes/enums/MODULE_GRADE.php | 55 +++++++++++++ lbplanner/classes/enums/MODULE_STATUS.php | 51 ++++++++++++ lbplanner/classes/enums/MODULE_TYPE.php | 55 +++++++++++++ lbplanner/classes/enums/NOTIF_STATUS.php | 43 ++++++++++ lbplanner/classes/enums/NOTIF_TRIGGER.php | 59 +++++++++++++ lbplanner/classes/enums/PLAN_ACCESS_TYPE.php | 51 ++++++++++++ lbplanner/classes/enums/PLAN_EK.php | 43 ++++++++++ lbplanner/classes/enums/PLAN_INVITE_STATE.php | 51 ++++++++++++ lbplanner/classes/helpers/modules_helper.php | 82 +------------------ .../classes/helpers/notifications_helper.php | 51 +----------- lbplanner/classes/helpers/plan_helper.php | 66 +-------------- .../classes/polyfill/{enum.php => Enum.php} | 25 +----- lbplanner/classes/polyfill/EnumCase.php | 49 +++++++++++ lbplanner/services/plan/accept_invite.php | 4 +- lbplanner/services/plan/decline_invite.php | 3 +- lbplanner/services/plan/invite_user.php | 3 +- lbplanner/services/plan/leave_plan.php | 4 +- lbplanner/services/plan/update_access.php | 2 +- lbplanner/services/user/delete_user.php | 9 +- lbplanner/services/user/register_user.php | 8 +- lbplanner/version.php | 2 +- 21 files changed, 474 insertions(+), 242 deletions(-) create mode 100644 lbplanner/classes/enums/MODULE_GRADE.php create mode 100644 lbplanner/classes/enums/MODULE_STATUS.php create mode 100644 lbplanner/classes/enums/MODULE_TYPE.php create mode 100644 lbplanner/classes/enums/NOTIF_STATUS.php create mode 100644 lbplanner/classes/enums/NOTIF_TRIGGER.php create mode 100644 lbplanner/classes/enums/PLAN_ACCESS_TYPE.php create mode 100644 lbplanner/classes/enums/PLAN_EK.php create mode 100644 lbplanner/classes/enums/PLAN_INVITE_STATE.php rename lbplanner/classes/polyfill/{enum.php => Enum.php} (83%) create mode 100644 lbplanner/classes/polyfill/EnumCase.php diff --git a/lbplanner/classes/enums/MODULE_GRADE.php b/lbplanner/classes/enums/MODULE_GRADE.php new file mode 100644 index 00000000..4cbe7a47 --- /dev/null +++ b/lbplanner/classes/enums/MODULE_GRADE.php @@ -0,0 +1,55 @@ +. +/** + * enum for module grade + * + * @package local_lbplanner + * @subpackage enums + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\enums; + +// TODO: revert to native enums once we migrate to php8. + +use local_lbplanner\polyfill\Enum; + +/** + * Grades a module can receive + */ +class MODULE_GRADE extends Enum { + /** + * Erweiterte Kompetenz vollständig. + */ + const EKV = 0; + /** + * Erweiterte Kompetenz überwiegend. + */ + const EK = 1; + /** + * Grundlegende Kompetenz vollständig. + */ + const GKV = 2; + /** + * Grundlegende Kompetenz überwiegend. + */ + const GK = 3; + /** + * Negative grade. + */ + const RIP = 4; +} diff --git a/lbplanner/classes/enums/MODULE_STATUS.php b/lbplanner/classes/enums/MODULE_STATUS.php new file mode 100644 index 00000000..7f0d87b1 --- /dev/null +++ b/lbplanner/classes/enums/MODULE_STATUS.php @@ -0,0 +1,51 @@ +. +/** + * enum for module status + * + * @package local_lbplanner + * @subpackage enums + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\enums; + +// TODO: revert to native enums once we migrate to php8. + +use local_lbplanner\polyfill\Enum; + +/** + * Stati a module can be in + */ +class MODULE_STATUS extends Enum { + /** + * Finished module. + */ + const DONE = 0; + /** + * Uploaded module. + */ + const UPLOADED = 1; + /** + * Overdue module. + */ + const LATE = 2; + /** + * Todo module. + */ + const PENDING = 3; +} diff --git a/lbplanner/classes/enums/MODULE_TYPE.php b/lbplanner/classes/enums/MODULE_TYPE.php new file mode 100644 index 00000000..47de6a0f --- /dev/null +++ b/lbplanner/classes/enums/MODULE_TYPE.php @@ -0,0 +1,55 @@ +. +/** + * enum for module type + * + * @package local_lbplanner + * @subpackage enums + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\enums; + +// TODO: revert to native enums once we migrate to php8. + +use local_lbplanner\polyfill\Enum; + +/** + * Module Types + */ +class MODULE_TYPE extends Enum { + /** + * Grundlegende Kompetenz. + */ + const GK = 0; + /** + * Erweiterte Kompetenz. + */ + const EK = 1; + /** + * Test i.e. exam. + */ + const TEST = 2; + /** + * TODO: ??? + */ + const M = 3; + /** + * TODO: ??? + */ + const NONE = 4; +} diff --git a/lbplanner/classes/enums/NOTIF_STATUS.php b/lbplanner/classes/enums/NOTIF_STATUS.php new file mode 100644 index 00000000..aef9d02f --- /dev/null +++ b/lbplanner/classes/enums/NOTIF_STATUS.php @@ -0,0 +1,43 @@ +. +/** + * enum for notif status + * + * @package local_lbplanner + * @subpackage enums + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\enums; + +// TODO: revert to native enums once we migrate to php8. + +use local_lbplanner\polyfill\Enum; + +/** + * Stati a notification can be in + */ +class NOTIF_STATUS extends Enum { + /** + * unread notification + */ + const UNREAD = 0; + /** + * read notification + */ + const READ = 1; +} diff --git a/lbplanner/classes/enums/NOTIF_TRIGGER.php b/lbplanner/classes/enums/NOTIF_TRIGGER.php new file mode 100644 index 00000000..3b1be9fd --- /dev/null +++ b/lbplanner/classes/enums/NOTIF_TRIGGER.php @@ -0,0 +1,59 @@ +. +/** + * enum for notif trigger + * + * @package local_lbplanner + * @subpackage enums + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\enums; + +// TODO: revert to native enums once we migrate to php8. + +use local_lbplanner\polyfill\Enum; + +/** + * Possible triggers for sending a notification + */ +class NOTIF_TRIGGER extends Enum { + /** + * Invitation sent + */ + const INVITE = 0; + /** + * Invitation accepted + */ + const INVITE_ACCEPTED = 1; + /** + * Invitation declined + */ + const INVITE_DECLINED = 2; + /** + * User left the plan + */ + const PLAN_LEFT = 3; + /** + * User got removed from the plan + */ + const PLAN_REMOVED = 4; + /** + * User registered + */ + const USER_REGISTERED = 5; +} diff --git a/lbplanner/classes/enums/PLAN_ACCESS_TYPE.php b/lbplanner/classes/enums/PLAN_ACCESS_TYPE.php new file mode 100644 index 00000000..3b8b07f1 --- /dev/null +++ b/lbplanner/classes/enums/PLAN_ACCESS_TYPE.php @@ -0,0 +1,51 @@ +. +/** + * enum for plan access type + * + * @package local_lbplanner + * @subpackage enums + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\enums; + +// TODO: revert to native enums once we migrate to php8. + +use local_lbplanner\polyfill\Enum; + +/** + * Levels of access that a user can have for a plan + */ +class PLAN_ACCESS_TYPE extends Enum { + /** + * owning the plan + */ + const OWNER = 0; + /** + * allowed to modify the plan + */ + const WRITE = 1; + /** + * allowed to look at the plan + */ + const READ = 2; + /** + * disallowed + */ + const NONE = -1; +} diff --git a/lbplanner/classes/enums/PLAN_EK.php b/lbplanner/classes/enums/PLAN_EK.php new file mode 100644 index 00000000..302ecdb1 --- /dev/null +++ b/lbplanner/classes/enums/PLAN_EK.php @@ -0,0 +1,43 @@ +. +/** + * enum for plan EK + * + * @package local_lbplanner + * @subpackage enums + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\enums; + +// TODO: revert to native enums once we migrate to php8. + +use local_lbplanner\polyfill\Enum; + +/** + * Whether EK modules are enabled inside the planner + */ +class PLAN_EK extends Enum { + /** + * EK hidden + */ + const DISABLED = 0; + /** + * EK visible + */ + const ENABLED = 1; +} diff --git a/lbplanner/classes/enums/PLAN_INVITE_STATE.php b/lbplanner/classes/enums/PLAN_INVITE_STATE.php new file mode 100644 index 00000000..58a4f569 --- /dev/null +++ b/lbplanner/classes/enums/PLAN_INVITE_STATE.php @@ -0,0 +1,51 @@ +. +/** + * enum for plan invite state + * + * @package local_lbplanner + * @subpackage enums + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\enums; + +// TODO: revert to native enums once we migrate to php8. + +use local_lbplanner\polyfill\Enum; + +/** + * States an invite can be in + */ +class PLAN_INVITE_STATE extends Enum { + /** + * pending invite + */ + const PENDING = 0; + /** + * accepted invite + */ + const ACCEPTED = 1; + /** + * declined invite + */ + const DECLINED = 2; + /** + * expired invite + */ + const EXPIRED = 3; +} diff --git a/lbplanner/classes/helpers/modules_helper.php b/lbplanner/classes/helpers/modules_helper.php index aa0c2179..51b06eed 100644 --- a/lbplanner/classes/helpers/modules_helper.php +++ b/lbplanner/classes/helpers/modules_helper.php @@ -24,92 +24,12 @@ namespace local_lbplanner\helpers; -defined('MOODLE_INTERNAL') || die(); - use block_accessreview\external\get_module_data; use external_function_parameters; use external_single_structure; use external_value; use moodle_url; - -use local_lbplanner\polyfill\Enum; - - -// TODO: revert to native enums once we migrate to php8. - -/** - * Stati a module can be in - */ -class MODULE_STATUS extends Enum { - /** - * Finished module. - */ - const DONE = 0; - /** - * Uploaded module. - */ - const UPLOADED = 1; - /** - * Overdue module. - */ - const LATE = 2; - /** - * Todo module. - */ - const PENDING = 3; -} - -/** - * Grades a module can receive - */ -class MODULE_GRADE extends Enum { - /** - * Erweiterte Kompetenz vollständig. - */ - const EKV = 0; - /** - * Erweiterte Kompetenz überwiegend. - */ - const EK = 1; - /** - * Grundlegende Kompetenz vollständig. - */ - const GKV = 2; - /** - * Grundlegende Kompetenz überwiegend. - */ - const GK = 3; - /** - * Negative grade. - */ - const RIP = 4; -} - -/** - * Module Types - */ -class MODULE_TYPE extends Enum { - /** - * Grundlegende Kompetenz. - */ - const GK = 0; - /** - * Erweiterte Kompetenz. - */ - const EK = 1; - /** - * Test i.e. exam. - */ - const TEST = 2; - /** - * TODO: ??? - */ - const M = 3; - /** - * TODO: ??? - */ - const NONE = 4; -} +use local_lbplanner\enums\{MODULE_STATUS, MODULE_GRADE, MODULE_TYPE}; /** * Contains helper functions for working with modules. diff --git a/lbplanner/classes/helpers/notifications_helper.php b/lbplanner/classes/helpers/notifications_helper.php index 9cddb1d4..adf1c50d 100644 --- a/lbplanner/classes/helpers/notifications_helper.php +++ b/lbplanner/classes/helpers/notifications_helper.php @@ -24,58 +24,9 @@ namespace local_lbplanner\helpers; -defined('MOODLE_INTERNAL') || die(); - use external_single_structure; use external_value; - -// TODO: revert to native enums once we migrate to php8. - -use local_lbplanner\polyfill\Enum; - -/** - * Stati a notification can be in - */ -class NOTIF_STATUS extends Enum { - /** - * unread notification - */ - const UNREAD = 0; - /** - * read notification - */ - const READ = 1; -} - -/** - * Possible triggers for sending a notification - */ -class NOTIF_TRIGGER extends Enum { - /** - * Invitation sent - */ - const INVITE = 0; - /** - * Invitation accepted - */ - const INVITE_ACCEPTED = 1; - /** - * Invitation declined - */ - const INVITE_DECLINED = 2; - /** - * User left the plan - */ - const PLAN_LEFT = 3; - /** - * User got removed from the plan - */ - const PLAN_REMOVED = 4; - /** - * User registered - */ - const USER_REGISTERED = 5; -} +use local_lbplanner\enums\{NOTIF_STATUS, NOTIF_TRIGGER}; /** * Provides helper methods for notification related stuff diff --git a/lbplanner/classes/helpers/plan_helper.php b/lbplanner/classes/helpers/plan_helper.php index 04a4606d..d7a79648 100644 --- a/lbplanner/classes/helpers/plan_helper.php +++ b/lbplanner/classes/helpers/plan_helper.php @@ -24,72 +24,10 @@ namespace local_lbplanner\helpers; -defined('MOODLE_INTERNAL') || die(); - use external_single_structure; use external_value; use external_multiple_structure; -use local_lbplanner\polyfill\Enum; - -// TODO: revert to native enums once we migrate to php8. - -/** - * Levels of access that a user can have for a plan - */ -class PLAN_ACCESS_TYPE extends Enum { - /** - * owning the plan - */ - const OWNER = 0; - /** - * allowed to modify the plan - */ - const WRITE = 1; - /** - * allowed to look at the plan - */ - const READ = 2; - /** - * disallowed - */ - const NONE = -1; -} - -/** - * Whether EK modules are enabled inside the planner - */ -class PLAN_EK extends Enum { - /** - * EK hidden - */ - const DISABLED = 0; - /** - * EK visible - */ - const ENABLED = 1; -} - -/** - * States an invite can be in - */ -class PLAN_INVITE_STATE extends Enum { - /** - * pending invite - */ - const PENDING = 0; - /** - * accepted invite - */ - const ACCEPTED = 1; - /** - * declined invite - */ - const DECLINED = 2; - /** - * expired invite - */ - const EXPIRED = 3; -} +use local_lbplanner\enums\PLAN_ACCESS_TYPE; /** * Provides helper methods for any tables related with the planning function of the app @@ -294,7 +232,7 @@ public static function plan_structure(): external_single_structure { public static function copy_plan(int $planid, int $userid): int { global $DB; - $user = user_helper::get_mdl_user_info($userid); + $user = user_helper::get_mdl_user_info($userid); // TODO: get_mdl_user_info doesn't exist anymore. $plan = $DB->get_record(self::TABLE, ['id' => $planid]); $plan->name = $plan->name . ' (' . $user->username . ')'; diff --git a/lbplanner/classes/polyfill/enum.php b/lbplanner/classes/polyfill/Enum.php similarity index 83% rename from lbplanner/classes/polyfill/enum.php rename to lbplanner/classes/polyfill/Enum.php index 9978de2a..1d8b7b19 100644 --- a/lbplanner/classes/polyfill/enum.php +++ b/lbplanner/classes/polyfill/Enum.php @@ -24,15 +24,14 @@ namespace local_lbplanner\polyfill; -defined('MOODLE_INTERNAL') || die(); - use ReflectionClass; use ValueError; +use lb_planner_local\polyfill\EnumCase; /** * Class which is meant to serve as a substitute for native enums. */ -abstract class Enum { +class Enum { /** * tries to match the passed value to one of the enum values * @param mixed $value the value to be matched @@ -89,23 +88,3 @@ public static function format(): string { return $result; } } - -/** - * This represents a single case within an Enum - */ -class EnumCase { - /** @var string the name of the case */ - public string $name; - /** @var string the value of the case */ - public mixed $value; - /** - * Constructs an EnumCase - * - * @param string $name the name of the case - * @param mixed $value the value of the case - */ - public function __construct(string $name, mixed $value) { - $this->name = $name; - $this->value = $value; - } -} diff --git a/lbplanner/classes/polyfill/EnumCase.php b/lbplanner/classes/polyfill/EnumCase.php new file mode 100644 index 00000000..f5e35750 --- /dev/null +++ b/lbplanner/classes/polyfill/EnumCase.php @@ -0,0 +1,49 @@ +. +/** + * case for enums + * + * @package local_lbplanner + * @subpackage polyfill + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace lb_planner_local\polyfill; + +defined('MOODLE_INTERNAL') || die(); + +// TODO: revert to native enums once we migrate to php8. + +/** + * This represents a single case within an Enum + */ +class EnumCase { + /** @var string the name of the case */ + public string $name; + /** @var string the value of the case */ + public mixed $value; + /** + * Constructs an EnumCase + * + * @param string $name the name of the case + * @param mixed $value the value of the case + */ + public function __construct(string $name, mixed $value) { + $this->name = $name; + $this->value = $value; + } +}; diff --git a/lbplanner/services/plan/accept_invite.php b/lbplanner/services/plan/accept_invite.php index b148e092..e3c8893c 100644 --- a/lbplanner/services/plan/accept_invite.php +++ b/lbplanner/services/plan/accept_invite.php @@ -21,9 +21,7 @@ use external_value; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; -use local_lbplanner\helpers\PLAN_ACCESS_TYPE; -use local_lbplanner\helpers\PLAN_INVITE_STATE; -use local_lbplanner\helpers\NOTIF_TRIGGER; +use local_lbplanner\enums\{PLAN_ACCESS_TYPE, PLAN_INVITE_STATE, NOTIF_TRIGGER}; /** * Accept an invite to the plan. diff --git a/lbplanner/services/plan/decline_invite.php b/lbplanner/services/plan/decline_invite.php index 59191871..044672e9 100644 --- a/lbplanner/services/plan/decline_invite.php +++ b/lbplanner/services/plan/decline_invite.php @@ -19,10 +19,9 @@ use external_api; use external_function_parameters; use external_value; -use local_lbplanner\helpers\NOTIF_TRIGGER; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; -use local_lbplanner\helpers\PLAN_INVITE_STATE; +use local_lbplanner\enums\{NOTIF_TRIGGER, PLAN_INVITE_STATE}; /** * Decline an invite from the plan. diff --git a/lbplanner/services/plan/invite_user.php b/lbplanner/services/plan/invite_user.php index 41b3469c..e572fdf1 100644 --- a/lbplanner/services/plan/invite_user.php +++ b/lbplanner/services/plan/invite_user.php @@ -21,10 +21,9 @@ use external_single_structure; use external_value; use local_lbplanner\helpers\invite_helper; -use local_lbplanner\helpers\NOTIF_TRIGGER; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; -use local_lbplanner\helpers\PLAN_INVITE_STATE; +use local_lbplanner\enums\{NOTIF_TRIGGER, PLAN_INVITE_STATE}; /** * Invite a user to the current user's plan diff --git a/lbplanner/services/plan/leave_plan.php b/lbplanner/services/plan/leave_plan.php index b7600e36..5a7e9b28 100644 --- a/lbplanner/services/plan/leave_plan.php +++ b/lbplanner/services/plan/leave_plan.php @@ -18,11 +18,9 @@ use external_api; use external_function_parameters; -use local_lbplanner\helpers\NOTIF_TRIGGER; use local_lbplanner\helpers\plan_helper; use local_lbplanner\helpers\notifications_helper; -use local_lbplanner\helpers\PLAN_ACCESS_TYPE; -use local_lbplanner\helpers\PLAN_INVITE_STATE; +use local_lbplanner\enums\{NOTIF_TRIGGER, PLAN_ACCESS_TYPE, PLAN_INVITE_STATE}; /** * Leave your plan diff --git a/lbplanner/services/plan/update_access.php b/lbplanner/services/plan/update_access.php index b4a79e86..a9ddd3ea 100644 --- a/lbplanner/services/plan/update_access.php +++ b/lbplanner/services/plan/update_access.php @@ -19,7 +19,7 @@ use external_api; use external_function_parameters; use external_value; -use local_lbplanner\helpers\PLAN_ACCESS_TYPE; +use local_lbplanner\enums\PLAN_ACCESS_TYPE; use local_lbplanner\helpers\plan_helper; /** diff --git a/lbplanner/services/user/delete_user.php b/lbplanner/services/user/delete_user.php index 9a7b9dd0..01c90bfc 100644 --- a/lbplanner/services/user/delete_user.php +++ b/lbplanner/services/user/delete_user.php @@ -19,12 +19,9 @@ use dml_exception; use external_api; use external_function_parameters; -use external_single_structure; use external_value; -use local_lbplanner\helpers\user_helper; -use local_lbplanner\helpers\plan_helper; -use local_lbplanner\helpers\course_helper; -use local_lbplanner\helpers\notifications_helper; +use local_lbplanner\helpers\{user_helper, plan_helper, course_helper, notifications_helper}; +use local_lbplanner\enums\{PLAN_INVITE_STATE, PLAN_ACCESS_TYPE}; use moodle_exception; /** @@ -81,7 +78,7 @@ public static function delete_user($userid) { if ( !(count(plan_helper::get_plan_members($planid)) == 1 ) && - !(plan_helper::get_access_type($planid, $userid) == plan_helper::ACCESS_TYPE_OWNER)) { + !(plan_helper::get_access_type($planid, $userid) == PLAN_ACCESS_TYPE::OWNER)) { self::call_external_function('local_lbplanner_plan_leave_plan', ['userid' => $userid, 'planid' => $planid]); } $DB->delete_records(plan_helper::DEADLINES_TABLE, ['planid' => $planid]); diff --git a/lbplanner/services/user/register_user.php b/lbplanner/services/user/register_user.php index aed07f2d..67e0562f 100644 --- a/lbplanner/services/user/register_user.php +++ b/lbplanner/services/user/register_user.php @@ -22,12 +22,8 @@ use external_single_structure; use external_value; use invalid_parameter_exception; -use local_lbplanner\helpers\NOTIF_TRIGGER; -use local_lbplanner\helpers\PLAN_ACCESS_TYPE; -use local_lbplanner\helpers\PLAN_EK; -use local_lbplanner\helpers\user_helper; -use local_lbplanner\helpers\plan_helper; -use local_lbplanner\helpers\notifications_helper; +use local_lbplanner\helpers\{user_helper, plan_helper, notifications_helper}; +use local_lbplanner\enums\{NOTIF_TRIGGER, PLAN_ACCESS_TYPE, PLAN_EK}; use moodle_exception; use stdClass; diff --git a/lbplanner/version.php b/lbplanner/version.php index d3e51d99..caab6006 100644 --- a/lbplanner/version.php +++ b/lbplanner/version.php @@ -27,7 +27,7 @@ $plugin->component = 'local_lbplanner'; $plugin->release = 'Alpha v.'.$release; -$plugin->version = 2024022700; +$plugin->version = 2024031200; $plugin->dependencies = [ // Depend upon version 2023110600 of local_modcustomfields. 'local_modcustomfields' => 2023110600, From a96165a4316d9c2aba1fc256bf7e22222c31fb27 Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Tue, 9 Apr 2024 19:25:40 +0200 Subject: [PATCH 26/92] first draft of slot booking table structure --- lbplanner/db/install.xml | 53 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/lbplanner/db/install.xml b/lbplanner/db/install.xml index f0d274fb..29794e5f 100644 --- a/lbplanner/db/install.xml +++ b/lbplanner/db/install.xml @@ -114,5 +114,58 @@ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + +
From 70ddc77c69c565548d0d2c75cda24c692c63d5d6 Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Tue, 9 Apr 2024 23:01:21 +0200 Subject: [PATCH 27/92] WIP groundwork + WIP get_my_slots API endpoint --- lbplanner/classes/enums/WEEKDAY.php | 66 ++++++++++ lbplanner/classes/helpers/slot_helper.php | 113 +++++++++++++++++ lbplanner/classes/model/reservation.php | 62 ++++++++++ lbplanner/classes/model/slot.php | 142 ++++++++++++++++++++++ lbplanner/classes/model/slot_filter.php | 44 +++++++ lbplanner/db/install.xml | 4 +- lbplanner/services/slots/get_my_slots.php | 92 ++++++++++++++ 7 files changed, 521 insertions(+), 2 deletions(-) create mode 100644 lbplanner/classes/enums/WEEKDAY.php create mode 100644 lbplanner/classes/helpers/slot_helper.php create mode 100644 lbplanner/classes/model/reservation.php create mode 100644 lbplanner/classes/model/slot.php create mode 100644 lbplanner/classes/model/slot_filter.php create mode 100644 lbplanner/services/slots/get_my_slots.php diff --git a/lbplanner/classes/enums/WEEKDAY.php b/lbplanner/classes/enums/WEEKDAY.php new file mode 100644 index 00000000..024e9451 --- /dev/null +++ b/lbplanner/classes/enums/WEEKDAY.php @@ -0,0 +1,66 @@ +. +/** + * enum for weekdays + * (cringe, ik, but we need these defined concretely) + * + * @package local_lbplanner + * @subpackage enums + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\enums; + +// TODO: revert to native enums once we migrate to php8. + +use local_lbplanner\polyfill\Enum; + +/** + * All the days of the week. + * All seven of them. + * Yup. + */ +class WEEKDAY extends Enum { + /** + * monday + */ + const MONDAY = 1; + /** + * tuesday + */ + const TUESDAY = 2; + /** + * wednesday + */ + const WEDNESDAY = 3; + /** + * thursday + */ + const THURSDAY = 4; + /** + * friday + */ + const FRIDAY = 5; + /** + * saturday + */ + const SATURDAY = 6; + /** + * sunday + */ + const SUNDAY = 7; +} diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php new file mode 100644 index 00000000..4a6717b4 --- /dev/null +++ b/lbplanner/classes/helpers/slot_helper.php @@ -0,0 +1,113 @@ +. +/** + * Provides helper classes for any tables related with the slot booking function of the app + * + * @package local_lbplanner + * @subpackage helpers + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\helpers; + +use local_lbplanner\model\{slot, reservation, slot_filter}; + +/** + * Provides helper methods for any tables related with the planning function of the app + */ +class slot_helper { + /** + * local_lbplanner_slots table. + */ + const TABLE_SLOTS = 'local_lbplanner_slots'; + /** + * local_lbplanner_reservations table. + */ + const TABLE_RESERVATIONS = 'local_lbplanner_reservations'; + /** + * local_lbplanner_slot_courses table. + */ + const TABLE_SLOT_FILTERS = 'local_lbplanner_slot_courses'; + /** + * local_lbplanner_supervisors table. + */ + const TABLE_SUPERVISORS = 'local_lbplanner_supervisors'; + + /** + * Returns a list of all slots. + * + * @return slot[] An array of the slots. + */ + public static function get_all_slots(): array { + global $DB; + $slots = $DB->get_records(self::TABLE_SLOTS, []); + + $slots_obj = []; + foreach($slots as $slot){ + array_push($slots_obj, new slot(...$slot)); + } + + return $slots_obj; + } + + /** + * Returns a singular slot. + * + * @return slot the requested slot + */ + public static function get_slot(int $slotid): slot { + global $DB; + $slot = $DB->get_record(self::TABLE_SLOTS, ['id'=>$slotid]); + + return new slot(...$slot); + } + + /** + * Returns reservations for a slot. + * + * @return reservation[] the requested reservations + */ + public static function get_reservations_for_slot(int $slotid): array { + global $DB; + $reservations = $DB->get_records(self::TABLE_RESERVATIONS, ['slotid'=>$slotid]); + + $reservations_obj = []; + foreach($reservations as $reservation){ + $reservation['date'] = new \DateTime($reservation['date']); + array_push($reservations_obj, new reservation(...$reservation)); + } + + return $reservations_obj; + } + + /** + * Returns filters for a slot. + * + * @return slot_filter[] the requested filters + */ + public static function get_filters_for_slot(int $slotid): array { + global $DB; + $filters = $DB->get_records(self::TABLE_SLOT_FILTERS, ['slotid'=>$slotid]); + + $filters_obj = []; + foreach($filters as $filter){ + array_push($filters_obj, new slot_filter(...$filter)); + } + + return $filters_obj; + } +} diff --git a/lbplanner/classes/model/reservation.php b/lbplanner/classes/model/reservation.php new file mode 100644 index 00000000..900190f2 --- /dev/null +++ b/lbplanner/classes/model/reservation.php @@ -0,0 +1,62 @@ +. +/** + * Model for a reservation + * + * @package local_lbplanner + * @subpackage helpers + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\model; + +use local_lbplanner\model\slot; +use local_lbplanner\helpers\slot_helper; + +/** + * Model class for reservation + */ +class reservation { + public int $id; + public int $slotid; + public \DateTimeImmutable $date; + public int $userid; + public int $reserverid; + private ?slot $slot; + + public function __construct(int $id, int $slotid, \DateTimeImmutable $date, int $userid, int $reserverid) { + $this->id = $id; + $this->slotid = $slotid; + $this->date = $date; + $this->userid = $userid; + $this->reserverid = $reserverid; + $this->slot = null; + } + + /** + * Returns the associated slot. + * + * @returns slot the associated slot + */ + public function get_slot(): slot { + if(is_null($this->slot)){ + $this->slot = slot_helper::get_slot($this->slotid); + } + + return $this->slot; + } +} diff --git a/lbplanner/classes/model/slot.php b/lbplanner/classes/model/slot.php new file mode 100644 index 00000000..b81c8058 --- /dev/null +++ b/lbplanner/classes/model/slot.php @@ -0,0 +1,142 @@ +. +/** + * Model for a slot + * + * @package local_lbplanner + * @subpackage helpers + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\model; + +use local_lbplanner\enums\WEEKDAY; +use local_lbplanner\helpers\slot_helper; + +use external_single_structure; +use external_value; + +/** + * Model class for slot + */ +class slot { + public int $id; + public int $startunit; + public int $duration; + public int $weekday; + public string $room; + public int $size; + private ?int $fullness; + private ?bool $for_curuser; + + public function __construct(int $id, int $startunit, int $duration, int $weekday, string $room, int $size) { + $this->id = $id; + assert($startunit > 0); + $this->startunit = $startunit; + assert($duration > 0); + $this->duration = $duration; + $this->weekday = WEEKDAY::from($weekday); + assert(strlen($room) > 0 && strlen($room) <= 7); + $this->room = $room; + assert($size >= 0); // Make it technically possible to not allow any students in a room to temporarily disable the slot. + $this->size = $size; + $this->fullness = null; + $this->for_curuser = null; + } + + /** + * Returns how many reservations there are for this slot. + * + * @return int fullness + */ + public function get_fullness(): int { + if(is_null($this->fullness)){ + $this->_check_reservations(); + } + + return $this->fullness; + } + + /** + * Returns whether the current user has a reservation for this slot. + * + * @return bool for_curuser + */ + public function get_for_curuser(): bool { + if(is_null($this->for_curuser)){ + $this->_check_reservations(); + } + + return $this->for_curuser; + } + + /** + * Prepares data for the API endpoint. + * + * @return array a representation of this slot and its data + */ + public function prepare_for_api(): array { + return [ + 'id' => $this->id, + 'startunit' => $this->startunit, + 'duration' => $this->duration, + 'weekday' => $this->weekday, + 'room' => $this->room, + 'size' => $this->size, + 'fullness' => $this->get_fullness(), + 'for_curuser' => $this->get_for_curuser(), + ]; + } + + /** + * Returns the data structure of a slot for the API. + * + * @return external_single_structure The data structure of a slot for the API. + */ + public static function api_structure(): external_single_structure { + return new external_single_structure( + [ + 'id' => new external_value(PARAM_INT, 'slot ID'), + 'startunit' => new external_value(PARAM_INT, 'unit this slot starts in (8:00 is unit 1)'), + 'duration' => new external_value(PARAM_INT, 'duration of the slot in units'), + 'weekday' => new external_value(PARAM_INT, 'The day this unit repeats weekly: '.WEEKDAY::format()), + 'room' => new external_value(PARAM_TEXT, 'The room this slot is for'), + 'size' => new external_value(PARAM_INT, 'total capacity of the slot'), + 'fullness' => new external_value(PARAM_INT, 'how many people have already reserved this slot'), + 'for_curuser' => new external_value(PARAM_BOOL, 'whether the current user has reserved this slot'), + ] + ); + } + + /** + * Queries reservations for this slot and fills in internal data with that info. + */ + private function _check_reservations(): void { + global $USER; + $reservations = slot_helper::get_reservations_for_slot($this->id); + + $this->fullness = sizeof($reservations); + + foreach($reservations as $reservation){ + if($reservation->userid == $USER['id']){ + $this->for_curuser = true; + return; + } + } + $this->for_curuser = false; + } +} diff --git a/lbplanner/classes/model/slot_filter.php b/lbplanner/classes/model/slot_filter.php new file mode 100644 index 00000000..e3334260 --- /dev/null +++ b/lbplanner/classes/model/slot_filter.php @@ -0,0 +1,44 @@ +. +/** + * Model for a filter for slots + * + * @package local_lbplanner + * @subpackage helpers + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\model; + +/** + * Model class for a filter for slots + */ +class slot_filter { + public int $id; + public int $slotid; + public ?int $courseid; + public ?string $vintage; + + public function __construct(int $id, int $slotid, ?int $courseid, ?string $vintage) { + $this->id = $id; + $this->slotid = $slotid; + $this->courseid = $courseid; + if(!is_null($vintage)) + assert(strlen($vintage) <= 7); + $this->vintage = $vintage; + } +} diff --git a/lbplanner/db/install.xml b/lbplanner/db/install.xml index 29794e5f..13c855e2 100644 --- a/lbplanner/db/install.xml +++ b/lbplanner/db/install.xml @@ -146,8 +146,8 @@ - - + + diff --git a/lbplanner/services/slots/get_my_slots.php b/lbplanner/services/slots/get_my_slots.php new file mode 100644 index 00000000..75aeff98 --- /dev/null +++ b/lbplanner/services/slots/get_my_slots.php @@ -0,0 +1,92 @@ +. + +namespace local_lbplanner_services; + +use external_api; +use external_function_parameters; +use local_lbplanner\helpers\slot_helper; +use local_lbplanner\model\slot; + +/** + * Returns all slots the user is supposed to see. + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class get_slots extends external_api { + /** + * Parameters for get_my_slots. + * @return external_function_parameters + */ + public static function get_my_slots_parameters(): external_function_parameters { + return new external_function_parameters([]); + } + + /** + * Returns slots the current user is supposed to see + */ + public static function get_my_slots() { + global $USER; + // NOTE: could be better solved by applying filters within one complex SQL query. + // Oh well. + + $all_slots = slot_helper::get_all_slots(); + + $my_courses = self::call_external_function('local_lbplanner_courses_get_all_courses', ['userid' => $USER->id]); + $my_courseids = []; + foreach($my_courses as $course){ + array_push($my_courseids, $course->courseid); + } + + $my_slots = []; + foreach($all_slots as $slot){ + $filters = slot_helper::get_filters_for_slot($slot->id); + foreach($filters as $filter) { + // Checking for course ID. + if(!is_null($filter->courseid) and !in_array($filter->courseid, $my_courseids)) { + continue; + } + // Checking for vintage. + if(!is_null($filter->vintage) and $USER->address !== $filter->vintage) { + continue; + } + // If all filters passed, add slot to my slots and break. + array_push($my_slots, $slot); + break; + } + } + + // TODO: check for time, weekday, etc. + + $returnslots = []; + foreach($my_slots as $slot){ + array_push($returnslots, $slot->prepare_for_api()); + } + + return $returnslots; + } + + /** + * Returns the structure of the slot array + * @return external_single_structure + */ + public static function get_my_slots_returns() { + return slot::api_structure(); + } +} From c15c051e86e8dd9d644e30892f472fdaf5ff1025 Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Wed, 17 Apr 2024 11:48:01 +0200 Subject: [PATCH 28/92] minor fix in Enum.php documentation --- lbplanner/classes/polyfill/Enum.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lbplanner/classes/polyfill/Enum.php b/lbplanner/classes/polyfill/Enum.php index 1d8b7b19..3e7d5f1a 100644 --- a/lbplanner/classes/polyfill/Enum.php +++ b/lbplanner/classes/polyfill/Enum.php @@ -76,7 +76,7 @@ public static function cases(): array { /** * Formats all possible enum values into a string * Example: - * (31=>RED,32=>GREEN,33=>YELLOW) + * [31=>RED,32=>GREEN,33=>YELLOW] * @return string the resulting string */ public static function format(): string { From f73518abb0ab5843520e8f2e7df229da43dc0ab1 Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Wed, 17 Apr 2024 11:55:15 +0200 Subject: [PATCH 29/92] refactored parts of Enum.php code deduplication, added name lookup --- lbplanner/classes/polyfill/Enum.php | 58 +++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/lbplanner/classes/polyfill/Enum.php b/lbplanner/classes/polyfill/Enum.php index 3e7d5f1a..a85422a4 100644 --- a/lbplanner/classes/polyfill/Enum.php +++ b/lbplanner/classes/polyfill/Enum.php @@ -35,15 +35,34 @@ class Enum { /** * tries to match the passed value to one of the enum values * @param mixed $value the value to be matched - * @return mixed either the matching enum value or null if not found + * @param bool $try whether to return null (true) or throw an error (false) if not found + * @return ?EnumCase the matching enum case or null if not found and $try==true + * @throws ValueError if not found and $try==false */ - public static function try_from(mixed $value): mixed { + private static function _find(mixed $value, bool $try): ?EnumCase { foreach (static::cases() as $case) { if ($case->value === $value) { - return $value; + return $case; } } - return null; + + if($try) + return null; + else + throw new ValueError("value {$value} cannot be represented as a value in enum ".static::class); + } + /** + * tries to match the passed value to one of the enum values + * @param mixed $value the value to be matched + * @return mixed either the matching enum value or null if not found + */ + public static function try_from(mixed $value): ?mixed { + // TODO: replace with nullsafe operator in php8. + $case = static::_find($value, true); + if(is_null($case)) + return null; + else + return $case->value; } /** * tries to match the passed value to one of the enum values @@ -52,13 +71,30 @@ public static function try_from(mixed $value): mixed { * @throws ValueError if not found */ public static function from(mixed $value): mixed { - foreach (static::cases() as $case) { - if ($case->value === $value) { - return $value; - } - } - - throw new ValueError("value {$value} cannot be represented as a value in enum ".static::class); + return static::_find($value, false)->value; + } + /** + * tries to match the passed value to one of the enum values + * @param mixed $value the value to be matched + * @return string the matching enum case name + * @throws mixed either the matching enum case name or null if not found + */ + public static function try_name_from(mixed $value): ?string { + // TODO: replace with nullsafe operator in php8. + $case = static::_find($value, true); + if(is_null($case)) + return null; + else + return $case->name; + } + /** + * tries to match the passed value to one of the enum values + * @param mixed $value the value to be matched + * @return string the matching enum case name + * @throws ValueError if not found + */ + public static function name_from(mixed $value): string { + return static::_find($value, false)->name; } /** * Returns an array of all the cases that exist in this enum From 5c5a5b8f872eeda39a9d7e986be2ad4ee2a87e68 Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Wed, 17 Apr 2024 12:22:27 +0200 Subject: [PATCH 30/92] defined school units MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …crudely. but good enough --- lbplanner/classes/helpers/slot_helper.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 4a6717b4..f2fea2b5 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -30,6 +30,28 @@ * Provides helper methods for any tables related with the planning function of the app */ class slot_helper { + /** + * school units according to untis, in H:i format + */ + const SCHOOL_UNITS = [ + null, + '08:00', + '08:50', + '09:50', + '10:40', + '11:30', + '12:30', + '13:20', + '14:10', + '15:10', + '16:00', + '17:00', // All units after this point are 45min long instead of the usual 50. + '17:45', // We will assume 50min anyway because it's easier that way. + '18:45', + '19:30', + '20:15', + '21:00', + ]; /** * local_lbplanner_slots table. */ From d439ef5ea95f3d36ff14bd83031b2b84a7f29613 Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Wed, 17 Apr 2024 12:23:10 +0200 Subject: [PATCH 31/92] finished get_my_slots API call --- lbplanner/services/slots/get_my_slots.php | 34 +++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/lbplanner/services/slots/get_my_slots.php b/lbplanner/services/slots/get_my_slots.php index 75aeff98..07ac4b53 100644 --- a/lbplanner/services/slots/get_my_slots.php +++ b/lbplanner/services/slots/get_my_slots.php @@ -16,13 +16,19 @@ namespace local_lbplanner_services; +use DateInterval; +use DateTime; +use DateTimeImmutable; use external_api; use external_function_parameters; +use external_single_structure; use local_lbplanner\helpers\slot_helper; use local_lbplanner\model\slot; +use local_lbplanner\enums\WEEKDAY; /** - * Returns all slots the user is supposed to see. + * Returns all slots the user can theoretically reserve. + * This does not include times the user has already reserved a slot for. * * @package local_lbplanner * @subpackage services_plan @@ -54,6 +60,9 @@ public static function get_my_slots() { array_push($my_courseids, $course->courseid); } + /** + * @var slot[] $my_slots + */ $my_slots = []; foreach($all_slots as $slot){ $filters = slot_helper::get_filters_for_slot($slot->id); @@ -62,6 +71,7 @@ public static function get_my_slots() { if(!is_null($filter->courseid) and !in_array($filter->courseid, $my_courseids)) { continue; } + // TODO: replace address with cohorts. // Checking for vintage. if(!is_null($filter->vintage) and $USER->address !== $filter->vintage) { continue; @@ -72,11 +82,25 @@ public static function get_my_slots() { } } - // TODO: check for time, weekday, etc. - + $now = new DateTimeImmutable(); + /** + * @var slot[] $returnslots + */ $returnslots = []; + // Calculate date and time each slot happens next, and add it to the return list if within reach from today. foreach($my_slots as $slot){ - array_push($returnslots, $slot->prepare_for_api()); + $slotdaytime = slot_helper::SCHOOL_UNITS[$slot->startunit]; + $slotdatetime = DateTime::createFromFormat('Y-m-d H:i',$now->format('Y-m-d ').$slotdaytime); + // Move to next day this weekday occurs (doesn't move if it's the same as today). + $slotdatetime->modify('this '.WEEKDAY::name_from($slot->weekday)); + + // Check if slot is before now (because time of day and such) and move it a week into the future if so. + if($now->diff($slotdatetime)->invert === 1) + $slotdatetime->add(new DateInterval('P1W')); + + // TODO: make setting of "3 days in advance" changeable. + if($now->diff($slotdatetime)->days <= 3) + array_push($returnslots, $slot->prepare_for_api()); } return $returnslots; @@ -86,7 +110,7 @@ public static function get_my_slots() { * Returns the structure of the slot array * @return external_single_structure */ - public static function get_my_slots_returns() { + public static function get_my_slots_returns(): external_single_structure { return slot::api_structure(); } } From 113a8078bd6d06f7d8b68269de4b373b9c8f3b00 Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Wed, 17 Apr 2024 12:31:54 +0200 Subject: [PATCH 32/92] made moodle codesniffer happy --- lbplanner/classes/helpers/slot_helper.php | 3 ++ lbplanner/services/slots/get_my_slots.php | 36 ++++++++++------------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index f2fea2b5..637e3bf6 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -88,6 +88,7 @@ public static function get_all_slots(): array { /** * Returns a singular slot. + * @param int $slotid ID of the slot * * @return slot the requested slot */ @@ -100,6 +101,7 @@ public static function get_slot(int $slotid): slot { /** * Returns reservations for a slot. + * @param int $slotid ID of the slot * * @return reservation[] the requested reservations */ @@ -118,6 +120,7 @@ public static function get_reservations_for_slot(int $slotid): array { /** * Returns filters for a slot. + * @param int $slotid ID of the slot * * @return slot_filter[] the requested filters */ diff --git a/lbplanner/services/slots/get_my_slots.php b/lbplanner/services/slots/get_my_slots.php index 07ac4b53..ddb76a47 100644 --- a/lbplanner/services/slots/get_my_slots.php +++ b/lbplanner/services/slots/get_my_slots.php @@ -52,55 +52,51 @@ public static function get_my_slots() { // NOTE: could be better solved by applying filters within one complex SQL query. // Oh well. - $all_slots = slot_helper::get_all_slots(); + $allSlots = slot_helper::get_all_slots(); - $my_courses = self::call_external_function('local_lbplanner_courses_get_all_courses', ['userid' => $USER->id]); - $my_courseids = []; - foreach($my_courses as $course){ - array_push($my_courseids, $course->courseid); + $myCourses = self::call_external_function('local_lbplanner_courses_get_all_courses', ['userid' => $USER->id]); + $myCourseids = []; + foreach ($myCourses as $course) { + array_push($myCourseids, $course->courseid); } - /** - * @var slot[] $my_slots - */ - $my_slots = []; - foreach($all_slots as $slot){ + $mySlots = []; + foreach ($allSlots as $slot) { $filters = slot_helper::get_filters_for_slot($slot->id); foreach($filters as $filter) { // Checking for course ID. - if(!is_null($filter->courseid) and !in_array($filter->courseid, $my_courseids)) { + if (!is_null($filter->courseid) && !in_array($filter->courseid, $myCourseids)) { continue; } // TODO: replace address with cohorts. // Checking for vintage. - if(!is_null($filter->vintage) and $USER->address !== $filter->vintage) { + if (!is_null($filter->vintage) && $USER->address !== $filter->vintage) { continue; } // If all filters passed, add slot to my slots and break. - array_push($my_slots, $slot); + array_push($mySlots, $slot); break; } } $now = new DateTimeImmutable(); - /** - * @var slot[] $returnslots - */ $returnslots = []; // Calculate date and time each slot happens next, and add it to the return list if within reach from today. - foreach($my_slots as $slot){ + foreach ($mySlots as $slot) { $slotdaytime = slot_helper::SCHOOL_UNITS[$slot->startunit]; - $slotdatetime = DateTime::createFromFormat('Y-m-d H:i',$now->format('Y-m-d ').$slotdaytime); + $slotdatetime = DateTime::createFromFormat('Y-m-d H:i', $now->format('Y-m-d ').$slotdaytime); // Move to next day this weekday occurs (doesn't move if it's the same as today). $slotdatetime->modify('this '.WEEKDAY::name_from($slot->weekday)); // Check if slot is before now (because time of day and such) and move it a week into the future if so. - if($now->diff($slotdatetime)->invert === 1) + if ($now->diff($slotdatetime)->invert === 1) { $slotdatetime->add(new DateInterval('P1W')); + } // TODO: make setting of "3 days in advance" changeable. - if($now->diff($slotdatetime)->days <= 3) + if ($now->diff($slotdatetime)->days <= 3) { array_push($returnslots, $slot->prepare_for_api()); + } } return $returnslots; From fed9cffc9c87851cda0edd1f0d6c356f2170953a Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Wed, 17 Apr 2024 12:39:42 +0200 Subject: [PATCH 33/92] made codesniffer even more happy --- lbplanner/classes/helpers/slot_helper.php | 28 +++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 637e3bf6..1add2a39 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -78,12 +78,12 @@ public static function get_all_slots(): array { global $DB; $slots = $DB->get_records(self::TABLE_SLOTS, []); - $slots_obj = []; - foreach($slots as $slot){ - array_push($slots_obj, new slot(...$slot)); + $slotsObj = []; + foreach ($slots as $slot) { + array_push($slotsObj, new slot(...$slot)); } - return $slots_obj; + return $slotsObj; } /** @@ -94,7 +94,7 @@ public static function get_all_slots(): array { */ public static function get_slot(int $slotid): slot { global $DB; - $slot = $DB->get_record(self::TABLE_SLOTS, ['id'=>$slotid]); + $slot = $DB->get_record(self::TABLE_SLOTS, ['id' => $slotid]); return new slot(...$slot); } @@ -107,15 +107,15 @@ public static function get_slot(int $slotid): slot { */ public static function get_reservations_for_slot(int $slotid): array { global $DB; - $reservations = $DB->get_records(self::TABLE_RESERVATIONS, ['slotid'=>$slotid]); + $reservations = $DB->get_records(self::TABLE_RESERVATIONS, ['slotid' => $slotid]); - $reservations_obj = []; - foreach($reservations as $reservation){ + $reservationsObj = []; + foreach ($reservations as $reservation) { $reservation['date'] = new \DateTime($reservation['date']); - array_push($reservations_obj, new reservation(...$reservation)); + array_push($reservationsObj, new reservation(...$reservation)); } - return $reservations_obj; + return $reservationsObj; } /** @@ -126,13 +126,13 @@ public static function get_reservations_for_slot(int $slotid): array { */ public static function get_filters_for_slot(int $slotid): array { global $DB; - $filters = $DB->get_records(self::TABLE_SLOT_FILTERS, ['slotid'=>$slotid]); + $filters = $DB->get_records(self::TABLE_SLOT_FILTERS, ['slotid' => $slotid]); - $filters_obj = []; + $filtersObj = []; foreach($filters as $filter){ - array_push($filters_obj, new slot_filter(...$filter)); + array_push($filtersObj, new slot_filter(...$filter)); } - return $filters_obj; + return $filtersObj; } } From eb101ef93421bbeedd5f1e8726a40f892acd3ef8 Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Wed, 17 Apr 2024 13:15:15 +0200 Subject: [PATCH 34/92] FUCK MOODLE DEVS AMAB stands for All Moodledevs Are Bad --- lbplanner/classes/enums/WEEKDAY.php | 12 ++-- lbplanner/classes/helpers/slot_helper.php | 18 +++--- lbplanner/classes/model/reservation.php | 38 ++++++++++-- lbplanner/classes/model/slot.php | 72 +++++++++++++++++------ lbplanner/classes/model/slot_filter.php | 22 ++++++- lbplanner/classes/polyfill/Enum.php | 27 +++++---- lbplanner/services/slots/get_my_slots.php | 18 +++--- 7 files changed, 149 insertions(+), 58 deletions(-) diff --git a/lbplanner/classes/enums/WEEKDAY.php b/lbplanner/classes/enums/WEEKDAY.php index 024e9451..7d5a5b3c 100644 --- a/lbplanner/classes/enums/WEEKDAY.php +++ b/lbplanner/classes/enums/WEEKDAY.php @@ -39,27 +39,27 @@ class WEEKDAY extends Enum { * monday */ const MONDAY = 1; - /** + /** * tuesday */ const TUESDAY = 2; - /** + /** * wednesday */ const WEDNESDAY = 3; - /** + /** * thursday */ const THURSDAY = 4; - /** + /** * friday */ const FRIDAY = 5; - /** + /** * saturday */ const SATURDAY = 6; - /** + /** * sunday */ const SUNDAY = 7; diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 1add2a39..1d23f615 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -78,12 +78,12 @@ public static function get_all_slots(): array { global $DB; $slots = $DB->get_records(self::TABLE_SLOTS, []); - $slotsObj = []; + $slotsobj = []; foreach ($slots as $slot) { - array_push($slotsObj, new slot(...$slot)); + array_push($slotsobj, new slot(...$slot)); } - return $slotsObj; + return $slotsobj; } /** @@ -109,13 +109,13 @@ public static function get_reservations_for_slot(int $slotid): array { global $DB; $reservations = $DB->get_records(self::TABLE_RESERVATIONS, ['slotid' => $slotid]); - $reservationsObj = []; + $reservationsobj = []; foreach ($reservations as $reservation) { $reservation['date'] = new \DateTime($reservation['date']); array_push($reservationsObj, new reservation(...$reservation)); } - return $reservationsObj; + return $reservationsobj; } /** @@ -128,11 +128,11 @@ public static function get_filters_for_slot(int $slotid): array { global $DB; $filters = $DB->get_records(self::TABLE_SLOT_FILTERS, ['slotid' => $slotid]); - $filtersObj = []; - foreach($filters as $filter){ - array_push($filtersObj, new slot_filter(...$filter)); + $filtersobj = []; + foreach ($filters as $filter) { + array_push($filtersobj, new slot_filter(...$filter)); } - return $filtersObj; + return $filtersobj; } } diff --git a/lbplanner/classes/model/reservation.php b/lbplanner/classes/model/reservation.php index 900190f2..d3af0ddb 100644 --- a/lbplanner/classes/model/reservation.php +++ b/lbplanner/classes/model/reservation.php @@ -24,6 +24,7 @@ namespace local_lbplanner\model; +use DateTimeImmutable; use local_lbplanner\model\slot; use local_lbplanner\helpers\slot_helper; @@ -31,14 +32,43 @@ * Model class for reservation */ class reservation { + /** + * @var int $id ID of reservation + */ public int $id; + /** + * @var int $slotid ID of the linked slot + * @link slot + */ public int $slotid; - public \DateTimeImmutable $date; + /** + * @var DateTimeImmutable $date date this reservation is on (time will be ignored) + */ + public DateTimeImmutable $date; + /** + * @var int $userid ID of the user this reservation is for + */ public int $userid; + /** + * @var int $reserverid ID of the user who submitted this reservation (either pupil or supervisor) + */ public int $reserverid; + /** + * @var ?slot $slot the linked slot (gets filled in by helper functions) + * @link slot + */ private ?slot $slot; - public function __construct(int $id, int $slotid, \DateTimeImmutable $date, int $userid, int $reserverid) { + /** + * Constructs a reservation + * @param int $id ID of reservation + * @param int $slotid ID of the linked slot + * @param DateTimeImmutable $date date this reservation is on (time will be ignored) + * @param int $userid ID of the user this reservation is for + * @param int $reserverid ID of the user who submitted this reservation (either pupil or supervisor) + * @link slot + */ + public function __construct(int $id, int $slotid, DateTimeImmutable $date, int $userid, int $reserverid) { $this->id = $id; $this->slotid = $slotid; $this->date = $date; @@ -50,10 +80,10 @@ public function __construct(int $id, int $slotid, \DateTimeImmutable $date, int /** * Returns the associated slot. * - * @returns slot the associated slot + * @return slot the associated slot */ public function get_slot(): slot { - if(is_null($this->slot)){ + if (is_null($this->slot)) { $this->slot = slot_helper::get_slot($this->slotid); } diff --git a/lbplanner/classes/model/slot.php b/lbplanner/classes/model/slot.php index b81c8058..42e5db3c 100644 --- a/lbplanner/classes/model/slot.php +++ b/lbplanner/classes/model/slot.php @@ -34,15 +34,53 @@ * Model class for slot */ class slot { + /** + * @var int $id ID of slot + */ public int $id; + /** + * @var int $startunit Unit this slot starts in + * @link slot_helper::SCHOOL_UNITS + */ public int $startunit; + /** + * @var int $duration duration of slot in units + * @link slot_helper::SCHOOL_UNITS + */ public int $duration; + /** + * @var int $weekday weekday this slot occurs in + * @link WEEKDAY + */ public int $weekday; + /** + * @var string $room room this slot is for + */ public string $room; + /** + * @var int $size how many pupils fit in this slot + */ public int $size; + /** + * @var ?int $fullness how many pupils have already reserved this slot (gets filled in by helper functions) + */ private ?int $fullness; - private ?bool $for_curuser; + /** + * @var ?bool $forcuruser whether the current user has reserved this slot (gets filled in by helper functions) + */ + private ?bool $forcuruser; + /** + * Constructs a new Slot + * @param int $id ID of slot + * @param int $startunit Unit this slot starts in + * @param int $duration duration of slot in units + * @param int $weekday weekday this slot occurs in + * @param string $room room this slot is for + * @param int $size how many pupils fit in this slot + * @link slot_helper::SCHOOL_UNITS + * @link WEEKDAY + */ public function __construct(int $id, int $startunit, int $duration, int $weekday, string $room, int $size) { $this->id = $id; assert($startunit > 0); @@ -55,7 +93,7 @@ public function __construct(int $id, int $startunit, int $duration, int $weekday assert($size >= 0); // Make it technically possible to not allow any students in a room to temporarily disable the slot. $this->size = $size; $this->fullness = null; - $this->for_curuser = null; + $this->forcuruser = null; } /** @@ -64,8 +102,8 @@ public function __construct(int $id, int $startunit, int $duration, int $weekday * @return int fullness */ public function get_fullness(): int { - if(is_null($this->fullness)){ - $this->_check_reservations(); + if (is_null($this->fullness)) { + $this->check_reservations(); } return $this->fullness; @@ -74,14 +112,14 @@ public function get_fullness(): int { /** * Returns whether the current user has a reservation for this slot. * - * @return bool for_curuser + * @return bool forcuruser */ - public function get_for_curuser(): bool { - if(is_null($this->for_curuser)){ - $this->_check_reservations(); + public function get_forcuruser(): bool { + if (is_null($this->forcuruser)) { + $this->check_reservations(); } - return $this->for_curuser; + return $this->forcuruser; } /** @@ -98,7 +136,7 @@ public function prepare_for_api(): array { 'room' => $this->room, 'size' => $this->size, 'fullness' => $this->get_fullness(), - 'for_curuser' => $this->get_for_curuser(), + 'forcuruser' => $this->get_forcuruser(), ]; } @@ -117,7 +155,7 @@ public static function api_structure(): external_single_structure { 'room' => new external_value(PARAM_TEXT, 'The room this slot is for'), 'size' => new external_value(PARAM_INT, 'total capacity of the slot'), 'fullness' => new external_value(PARAM_INT, 'how many people have already reserved this slot'), - 'for_curuser' => new external_value(PARAM_BOOL, 'whether the current user has reserved this slot'), + 'forcuruser' => new external_value(PARAM_BOOL, 'whether the current user has reserved this slot'), ] ); } @@ -125,18 +163,18 @@ public static function api_structure(): external_single_structure { /** * Queries reservations for this slot and fills in internal data with that info. */ - private function _check_reservations(): void { + private function check_reservations(): void { global $USER; $reservations = slot_helper::get_reservations_for_slot($this->id); - $this->fullness = sizeof($reservations); + $this->fullness = count($reservations); - foreach($reservations as $reservation){ - if($reservation->userid == $USER['id']){ - $this->for_curuser = true; + foreach ($reservations as $reservation) { + if ($reservation->userid === $USER['id']) { + $this->forcuruser = true; return; } } - $this->for_curuser = false; + $this->forcuruser = false; } } diff --git a/lbplanner/classes/model/slot_filter.php b/lbplanner/classes/model/slot_filter.php index e3334260..d798f2c7 100644 --- a/lbplanner/classes/model/slot_filter.php +++ b/lbplanner/classes/model/slot_filter.php @@ -28,17 +28,37 @@ * Model class for a filter for slots */ class slot_filter { + /** + * @var int $id ID of filter + */ public int $id; + /** + * @var int $id ID of linked slot + */ public int $slotid; + /** + * @var ?int $id ID of linked course or null if any + */ public ?int $courseid; + /** + * @var ?string $vintage linked class or null if any + */ public ?string $vintage; + /** + * Constructs new slot_filter + * @param int $id ID of filter + * @param int $slotid ID of linked slot + * @param ?int $courseid ID of linked course or null if any + * @param ?string $vintage linked class or null if any + */ public function __construct(int $id, int $slotid, ?int $courseid, ?string $vintage) { $this->id = $id; $this->slotid = $slotid; $this->courseid = $courseid; - if(!is_null($vintage)) + if (!is_null($vintage)) { assert(strlen($vintage) <= 7); + } $this->vintage = $vintage; } } diff --git a/lbplanner/classes/polyfill/Enum.php b/lbplanner/classes/polyfill/Enum.php index a85422a4..e5c4d2a3 100644 --- a/lbplanner/classes/polyfill/Enum.php +++ b/lbplanner/classes/polyfill/Enum.php @@ -39,30 +39,32 @@ class Enum { * @return ?EnumCase the matching enum case or null if not found and $try==true * @throws ValueError if not found and $try==false */ - private static function _find(mixed $value, bool $try): ?EnumCase { + private static function find(mixed $value, bool $try): ?EnumCase { foreach (static::cases() as $case) { if ($case->value === $value) { return $case; } } - if($try) + if ($try) { return null; - else + } else { throw new ValueError("value {$value} cannot be represented as a value in enum ".static::class); + } } /** * tries to match the passed value to one of the enum values * @param mixed $value the value to be matched * @return mixed either the matching enum value or null if not found */ - public static function try_from(mixed $value): ?mixed { + public static function try_from(mixed $value): mixed { // TODO: replace with nullsafe operator in php8. - $case = static::_find($value, true); - if(is_null($case)) + $case = static::find($value, true); + if (is_null($case)) { return null; - else + } else { return $case->value; + } } /** * tries to match the passed value to one of the enum values @@ -71,7 +73,7 @@ public static function try_from(mixed $value): ?mixed { * @throws ValueError if not found */ public static function from(mixed $value): mixed { - return static::_find($value, false)->value; + return static::find($value, false)->value; } /** * tries to match the passed value to one of the enum values @@ -81,11 +83,12 @@ public static function from(mixed $value): mixed { */ public static function try_name_from(mixed $value): ?string { // TODO: replace with nullsafe operator in php8. - $case = static::_find($value, true); - if(is_null($case)) + $case = static::find($value, true); + if (is_null($case)) { return null; - else + } else { return $case->name; + } } /** * tries to match the passed value to one of the enum values @@ -94,7 +97,7 @@ public static function try_name_from(mixed $value): ?string { * @throws ValueError if not found */ public static function name_from(mixed $value): string { - return static::_find($value, false)->name; + return static::find($value, false)->name; } /** * Returns an array of all the cases that exist in this enum diff --git a/lbplanner/services/slots/get_my_slots.php b/lbplanner/services/slots/get_my_slots.php index ddb76a47..414a373c 100644 --- a/lbplanner/services/slots/get_my_slots.php +++ b/lbplanner/services/slots/get_my_slots.php @@ -52,20 +52,20 @@ public static function get_my_slots() { // NOTE: could be better solved by applying filters within one complex SQL query. // Oh well. - $allSlots = slot_helper::get_all_slots(); + $allslots = slot_helper::get_all_slots(); - $myCourses = self::call_external_function('local_lbplanner_courses_get_all_courses', ['userid' => $USER->id]); - $myCourseids = []; - foreach ($myCourses as $course) { - array_push($myCourseids, $course->courseid); + $mycourses = self::call_external_function('local_lbplanner_courses_get_all_courses', ['userid' => $USER->id]); + $mycourseids = []; + foreach ($mycourses as $course) { + array_push($mycourseids, $course->courseid); } $mySlots = []; - foreach ($allSlots as $slot) { + foreach ($allslots as $slot) { $filters = slot_helper::get_filters_for_slot($slot->id); - foreach($filters as $filter) { + foreach ($filters as $filter) { // Checking for course ID. - if (!is_null($filter->courseid) && !in_array($filter->courseid, $myCourseids)) { + if (!is_null($filter->courseid) && !in_array($filter->courseid, $mycourseids)) { continue; } // TODO: replace address with cohorts. @@ -74,7 +74,7 @@ public static function get_my_slots() { continue; } // If all filters passed, add slot to my slots and break. - array_push($mySlots, $slot); + array_push($myslots, $slot); break; } } From 46480f167d289dc5d0451b3f314984c7b841b0ab Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Wed, 17 Apr 2024 13:22:08 +0200 Subject: [PATCH 35/92] KILL KILL KILL GRRR --- lbplanner/classes/helpers/slot_helper.php | 2 +- lbplanner/classes/model/reservation.php | 2 -- lbplanner/classes/model/slot.php | 3 --- lbplanner/services/slots/get_my_slots.php | 4 ++-- 4 files changed, 3 insertions(+), 8 deletions(-) diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 1d23f615..7124b542 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -112,7 +112,7 @@ public static function get_reservations_for_slot(int $slotid): array { $reservationsobj = []; foreach ($reservations as $reservation) { $reservation['date'] = new \DateTime($reservation['date']); - array_push($reservationsObj, new reservation(...$reservation)); + array_push($reservationsobj, new reservation(...$reservation)); } return $reservationsobj; diff --git a/lbplanner/classes/model/reservation.php b/lbplanner/classes/model/reservation.php index d3af0ddb..513009b0 100644 --- a/lbplanner/classes/model/reservation.php +++ b/lbplanner/classes/model/reservation.php @@ -38,7 +38,6 @@ class reservation { public int $id; /** * @var int $slotid ID of the linked slot - * @link slot */ public int $slotid; /** @@ -55,7 +54,6 @@ class reservation { public int $reserverid; /** * @var ?slot $slot the linked slot (gets filled in by helper functions) - * @link slot */ private ?slot $slot; diff --git a/lbplanner/classes/model/slot.php b/lbplanner/classes/model/slot.php index 42e5db3c..8e2fa1e0 100644 --- a/lbplanner/classes/model/slot.php +++ b/lbplanner/classes/model/slot.php @@ -40,17 +40,14 @@ class slot { public int $id; /** * @var int $startunit Unit this slot starts in - * @link slot_helper::SCHOOL_UNITS */ public int $startunit; /** * @var int $duration duration of slot in units - * @link slot_helper::SCHOOL_UNITS */ public int $duration; /** * @var int $weekday weekday this slot occurs in - * @link WEEKDAY */ public int $weekday; /** diff --git a/lbplanner/services/slots/get_my_slots.php b/lbplanner/services/slots/get_my_slots.php index 414a373c..3c99f00f 100644 --- a/lbplanner/services/slots/get_my_slots.php +++ b/lbplanner/services/slots/get_my_slots.php @@ -60,7 +60,7 @@ public static function get_my_slots() { array_push($mycourseids, $course->courseid); } - $mySlots = []; + $myslots = []; foreach ($allslots as $slot) { $filters = slot_helper::get_filters_for_slot($slot->id); foreach ($filters as $filter) { @@ -82,7 +82,7 @@ public static function get_my_slots() { $now = new DateTimeImmutable(); $returnslots = []; // Calculate date and time each slot happens next, and add it to the return list if within reach from today. - foreach ($mySlots as $slot) { + foreach ($myslots as $slot) { $slotdaytime = slot_helper::SCHOOL_UNITS[$slot->startunit]; $slotdatetime = DateTime::createFromFormat('Y-m-d H:i', $now->format('Y-m-d ').$slotdaytime); // Move to next day this weekday occurs (doesn't move if it's the same as today). From d0a459c44160e1ce4f8f65ab70d6473e5267c0a5 Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Wed, 17 Apr 2024 13:49:46 +0200 Subject: [PATCH 36/92] HOTFIX: oops I fucked up :) --- lbplanner/services/slots/get_my_slots.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lbplanner/services/slots/get_my_slots.php b/lbplanner/services/slots/get_my_slots.php index 3c99f00f..1692b0c9 100644 --- a/lbplanner/services/slots/get_my_slots.php +++ b/lbplanner/services/slots/get_my_slots.php @@ -21,7 +21,7 @@ use DateTimeImmutable; use external_api; use external_function_parameters; -use external_single_structure; +use external_multiple_structure; use local_lbplanner\helpers\slot_helper; use local_lbplanner\model\slot; use local_lbplanner\enums\WEEKDAY; @@ -35,7 +35,7 @@ * @copyright 2024 necodeIT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class get_slots extends external_api { +class get_my_slots extends external_api { /** * Parameters for get_my_slots. * @return external_function_parameters @@ -104,9 +104,11 @@ public static function get_my_slots() { /** * Returns the structure of the slot array - * @return external_single_structure + * @return external_multiple_structure */ - public static function get_my_slots_returns(): external_single_structure { - return slot::api_structure(); + public static function get_my_slots_returns(): external_multiple_structure { + return new external_multiple_structure( + slot::api_structure() + ); } } From 69aa697c3fcdd0f9bea14d52a4a94c962b089d65 Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Wed, 17 Apr 2024 15:02:13 +0200 Subject: [PATCH 37/92] generalized parts of get_my_slots for/to slot_helper --- lbplanner/classes/helpers/slot_helper.php | 68 +++++++++++++++++++++++ lbplanner/services/slots/get_my_slots.php | 51 ++--------------- 2 files changed, 72 insertions(+), 47 deletions(-) diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 7124b542..99a1633a 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -24,6 +24,12 @@ namespace local_lbplanner\helpers; +use DateInterval; +use DateTime; +use DateTimeImmutable; + +use external_api; +use local_lbplanner\enums\WEEKDAY; use local_lbplanner\model\{slot, reservation, slot_filter}; /** @@ -135,4 +141,66 @@ public static function get_filters_for_slot(int $slotid): array { return $filtersobj; } + + /** + * Filters an array of slots for the slots that the user can reserve. + * @param slot[] $allslots the slots to filter + * @param mixed $user a user object - e.g. $USER or a user object from the database + * @return slot[] the filtered slot array + */ + public static function filter_slots_for_user(array $allslots, mixed $user): array { + $mycourses = external_api::call_external_function('local_lbplanner_courses_get_all_courses', ['userid' => $user->id]); + $mycourseids = []; + foreach ($mycourses as $course) { + array_push($mycourseids, $course->courseid); + } + + $slots = []; + foreach ($allslots as $slot) { + $filters = slot_helper::get_filters_for_slot($slot->id); + foreach ($filters as $filter) { + // Checking for course ID. + if (!is_null($filter->courseid) && !in_array($filter->courseid, $mycourseids)) { + continue; + } + // TODO: replace address with cohorts. + // Checking for vintage. + if (!is_null($filter->vintage) && $user->address !== $filter->vintage) { + continue; + } + // If all filters passed, add slot to my slots and break. + array_push($slots, $slot); + break; + } + } + return $slots; + } + + /** + * Filters an array of slots for a timerange around now. + * @param slot[] $allslots the slots to filter + * @param DateTimeImmutable $now a point in time representing the point in time to start filtering at + * @param int $range how many days in the future the slot is allowed to be + * @return slot[] the filtered slot array + */ + public static function filter_slots_for_time(array $allslots, DateTimeImmutable $now, int $range): array { + $slots = []; + // Calculate date and time each slot happens next, and add it to the return list if within reach from today. + foreach ($allslots as $slot) { + $slotdaytime = slot_helper::SCHOOL_UNITS[$slot->startunit]; + $slotdatetime = DateTime::createFromFormat('Y-m-d H:i', $now->format('Y-m-d ').$slotdaytime); + // Move to next day this weekday occurs (doesn't move if it's the same as today). + $slotdatetime->modify('this '.WEEKDAY::name_from($slot->weekday)); + + // Check if slot is before now (because time of day and such) and move it a week into the future if so. + if ($now->diff($slotdatetime)->invert === 1) { + $slotdatetime->add(new DateInterval('P1W')); + } + + if ($now->diff($slotdatetime)->days <= $range) { + array_push($slots, $slot->prepare_for_api()); + } + } + return $slots; + } } diff --git a/lbplanner/services/slots/get_my_slots.php b/lbplanner/services/slots/get_my_slots.php index 1692b0c9..f8e9dc59 100644 --- a/lbplanner/services/slots/get_my_slots.php +++ b/lbplanner/services/slots/get_my_slots.php @@ -16,15 +16,13 @@ namespace local_lbplanner_services; -use DateInterval; -use DateTime; use DateTimeImmutable; + use external_api; use external_function_parameters; use external_multiple_structure; use local_lbplanner\helpers\slot_helper; use local_lbplanner\model\slot; -use local_lbplanner\enums\WEEKDAY; /** * Returns all slots the user can theoretically reserve. @@ -49,55 +47,14 @@ public static function get_my_slots_parameters(): external_function_parameters { */ public static function get_my_slots() { global $USER; - // NOTE: could be better solved by applying filters within one complex SQL query. - // Oh well. $allslots = slot_helper::get_all_slots(); - $mycourses = self::call_external_function('local_lbplanner_courses_get_all_courses', ['userid' => $USER->id]); - $mycourseids = []; - foreach ($mycourses as $course) { - array_push($mycourseids, $course->courseid); - } - - $myslots = []; - foreach ($allslots as $slot) { - $filters = slot_helper::get_filters_for_slot($slot->id); - foreach ($filters as $filter) { - // Checking for course ID. - if (!is_null($filter->courseid) && !in_array($filter->courseid, $mycourseids)) { - continue; - } - // TODO: replace address with cohorts. - // Checking for vintage. - if (!is_null($filter->vintage) && $USER->address !== $filter->vintage) { - continue; - } - // If all filters passed, add slot to my slots and break. - array_push($myslots, $slot); - break; - } - } + $myslots = slot_helper::filter_slots_for_user($allslots, $USER); $now = new DateTimeImmutable(); - $returnslots = []; - // Calculate date and time each slot happens next, and add it to the return list if within reach from today. - foreach ($myslots as $slot) { - $slotdaytime = slot_helper::SCHOOL_UNITS[$slot->startunit]; - $slotdatetime = DateTime::createFromFormat('Y-m-d H:i', $now->format('Y-m-d ').$slotdaytime); - // Move to next day this weekday occurs (doesn't move if it's the same as today). - $slotdatetime->modify('this '.WEEKDAY::name_from($slot->weekday)); - - // Check if slot is before now (because time of day and such) and move it a week into the future if so. - if ($now->diff($slotdatetime)->invert === 1) { - $slotdatetime->add(new DateInterval('P1W')); - } - - // TODO: make setting of "3 days in advance" changeable. - if ($now->diff($slotdatetime)->days <= 3) { - array_push($returnslots, $slot->prepare_for_api()); - } - } + // TODO: make setting of "3 days in advance" changeable. + $returnslots = slot_helper::filter_slots_for_time($myslots, $now, 3); return $returnslots; } From 4c00b96eaec4b158151a1594a2f8f11686f958ce Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Wed, 17 Apr 2024 15:43:12 +0200 Subject: [PATCH 38/92] added get_student_slots API call + minor refactors --- lbplanner/classes/helpers/slot_helper.php | 36 ++++++++- lbplanner/services/slots/get_my_slots.php | 8 +- .../services/slots/get_student_slots.php | 74 +++++++++++++++++++ 3 files changed, 110 insertions(+), 8 deletions(-) create mode 100644 lbplanner/services/slots/get_student_slots.php diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 99a1633a..38a196ac 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -36,6 +36,14 @@ * Provides helper methods for any tables related with the planning function of the app */ class slot_helper { + /** + * how far into the future a user can reserve a slot + */ + const RESERVATION_RANGE_USER = 3; + /** + * how far into the future a supervisor can reserve a slot for a user + */ + const RESERVATION_RANGE_SUPERVISOR = 7; /** * school units according to untis, in H:i format */ @@ -92,6 +100,30 @@ public static function get_all_slots(): array { return $slotsobj; } + /** + * Returns a list of all slots belonging to a supervisor. + * @param int $supervisorid userid of the supervisor in question + * + * @return slot[] An array of the slots. + */ + public static function get_supervisor_slots(int $supervisorid): array { + global $DB; + + $slots = $DB->get_records_sql( + 'SELECT slot.* FROM {'.self::TABLE_SLOTS.'} as slot'. + 'INNER JOIN '.self::TABLE_SUPERVISORS.' as supervisor ON supervisor.slotid=slot.id'. + 'WHERE supervisor.userid=?', + [$supervisorid] + ); + + $slotsobj = []; + foreach ($slots as $slot) { + array_push($slotsobj, new slot(...$slot)); + } + + return $slotsobj; + } + /** * Returns a singular slot. * @param int $slotid ID of the slot @@ -179,11 +211,11 @@ public static function filter_slots_for_user(array $allslots, mixed $user): arra /** * Filters an array of slots for a timerange around now. * @param slot[] $allslots the slots to filter - * @param DateTimeImmutable $now a point in time representing the point in time to start filtering at * @param int $range how many days in the future the slot is allowed to be * @return slot[] the filtered slot array */ - public static function filter_slots_for_time(array $allslots, DateTimeImmutable $now, int $range): array { + public static function filter_slots_for_time(array $allslots, int $range): array { + $now = new DateTimeImmutable(); $slots = []; // Calculate date and time each slot happens next, and add it to the return list if within reach from today. foreach ($allslots as $slot) { diff --git a/lbplanner/services/slots/get_my_slots.php b/lbplanner/services/slots/get_my_slots.php index f8e9dc59..84df1b3c 100644 --- a/lbplanner/services/slots/get_my_slots.php +++ b/lbplanner/services/slots/get_my_slots.php @@ -16,8 +16,6 @@ namespace local_lbplanner_services; -use DateTimeImmutable; - use external_api; use external_function_parameters; use external_multiple_structure; @@ -45,16 +43,14 @@ public static function get_my_slots_parameters(): external_function_parameters { /** * Returns slots the current user is supposed to see */ - public static function get_my_slots() { + public static function get_my_slots(): array { global $USER; $allslots = slot_helper::get_all_slots(); $myslots = slot_helper::filter_slots_for_user($allslots, $USER); - $now = new DateTimeImmutable(); - // TODO: make setting of "3 days in advance" changeable. - $returnslots = slot_helper::filter_slots_for_time($myslots, $now, 3); + $returnslots = slot_helper::filter_slots_for_time($myslots, slot_helper::RESERVATION_RANGE_USER); return $returnslots; } diff --git a/lbplanner/services/slots/get_student_slots.php b/lbplanner/services/slots/get_student_slots.php new file mode 100644 index 00000000..95201c43 --- /dev/null +++ b/lbplanner/services/slots/get_student_slots.php @@ -0,0 +1,74 @@ +. + +namespace local_lbplanner_services; + +use external_api; +use external_function_parameters; +use external_multiple_structure; +use external_value; +use local_lbplanner\helpers\slot_helper; +use local_lbplanner\model\slot; + +/** + * Returns all slots a supervisor can theoretically reserve for a user. + * This does not include times the user has already reserved a slot for. + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class get_student_slots extends external_api { + /** + * Parameters for get_student_slots. + * @return external_function_parameters + */ + public static function get_my_slots_parameters(): external_function_parameters { + return new external_function_parameters([ + 'userid' => new external_value(PARAM_INT, 'ID of the user to query for', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), + ]); + } + + /** + * Returns slots of a user the supervisor can see. + */ + public static function get_student_slots(int $userid): array { + global $USER; + self::validate_parameters( + self::get_my_slots_parameters(), + ['userid' => $userid] + ); + + $superslots = slot_helper::get_supervisor_slots($USER->id); + + $myslots = slot_helper::filter_slots_for_user($superslots, $userid); + + $returnslots = slot_helper::filter_slots_for_time($myslots, slot_helper::RESERVATION_RANGE_SUPERVISOR); + + return $returnslots; + } + + /** + * Returns the structure of the slot array + * @return external_multiple_structure + */ + public static function get_student_slots_returns(): external_multiple_structure { + return new external_multiple_structure( + slot::api_structure() + ); + } +} From febdce9b51c9b449e7cc4fffc3a3d4b2aae89aa8 Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Wed, 17 Apr 2024 15:52:40 +0200 Subject: [PATCH 39/92] made codesniffer happy hopefully --- lbplanner/classes/helpers/slot_helper.php | 4 ++-- lbplanner/services/slots/get_my_slots.php | 2 +- lbplanner/services/slots/get_student_slots.php | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 38a196ac..576d88b8 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -189,7 +189,7 @@ public static function filter_slots_for_user(array $allslots, mixed $user): arra $slots = []; foreach ($allslots as $slot) { - $filters = slot_helper::get_filters_for_slot($slot->id); + $filters = self::get_filters_for_slot($slot->id); foreach ($filters as $filter) { // Checking for course ID. if (!is_null($filter->courseid) && !in_array($filter->courseid, $mycourseids)) { @@ -219,7 +219,7 @@ public static function filter_slots_for_time(array $allslots, int $range): array $slots = []; // Calculate date and time each slot happens next, and add it to the return list if within reach from today. foreach ($allslots as $slot) { - $slotdaytime = slot_helper::SCHOOL_UNITS[$slot->startunit]; + $slotdaytime = self::SCHOOL_UNITS[$slot->startunit]; $slotdatetime = DateTime::createFromFormat('Y-m-d H:i', $now->format('Y-m-d ').$slotdaytime); // Move to next day this weekday occurs (doesn't move if it's the same as today). $slotdatetime->modify('this '.WEEKDAY::name_from($slot->weekday)); diff --git a/lbplanner/services/slots/get_my_slots.php b/lbplanner/services/slots/get_my_slots.php index 84df1b3c..5198fc84 100644 --- a/lbplanner/services/slots/get_my_slots.php +++ b/lbplanner/services/slots/get_my_slots.php @@ -31,7 +31,7 @@ * @copyright 2024 necodeIT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class get_my_slots extends external_api { +class slots_get_my_slots extends external_api { /** * Parameters for get_my_slots. * @return external_function_parameters diff --git a/lbplanner/services/slots/get_student_slots.php b/lbplanner/services/slots/get_student_slots.php index 95201c43..1cde91e2 100644 --- a/lbplanner/services/slots/get_student_slots.php +++ b/lbplanner/services/slots/get_student_slots.php @@ -32,7 +32,7 @@ * @copyright 2024 necodeIT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class get_student_slots extends external_api { +class slots_get_student_slots extends external_api { /** * Parameters for get_student_slots. * @return external_function_parameters @@ -45,6 +45,7 @@ public static function get_my_slots_parameters(): external_function_parameters { /** * Returns slots of a user the supervisor can see. + * @param int $userid ID of the user in question (NOT the supervisor) */ public static function get_student_slots(int $userid): array { global $USER; From 1636705764c62137b5df5b21f863e21fadd00f4b Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Wed, 17 Apr 2024 16:22:36 +0200 Subject: [PATCH 40/92] fixed oopsie --- lbplanner/services/slots/get_student_slots.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lbplanner/services/slots/get_student_slots.php b/lbplanner/services/slots/get_student_slots.php index 1cde91e2..2a9df0e1 100644 --- a/lbplanner/services/slots/get_student_slots.php +++ b/lbplanner/services/slots/get_student_slots.php @@ -37,7 +37,7 @@ class slots_get_student_slots extends external_api { * Parameters for get_student_slots. * @return external_function_parameters */ - public static function get_my_slots_parameters(): external_function_parameters { + public static function get_student_slots_parameters(): external_function_parameters { return new external_function_parameters([ 'userid' => new external_value(PARAM_INT, 'ID of the user to query for', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), ]); @@ -50,7 +50,7 @@ public static function get_my_slots_parameters(): external_function_parameters { public static function get_student_slots(int $userid): array { global $USER; self::validate_parameters( - self::get_my_slots_parameters(), + self::get_student_slots_parameters(), ['userid' => $userid] ); From e70b78c040a782079ab5614bd874a80c23e03912 Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Wed, 17 Apr 2024 16:24:33 +0200 Subject: [PATCH 41/92] implemented get_supervisor_slots --- .../services/slots/get_supervisor_slots.php | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 lbplanner/services/slots/get_supervisor_slots.php diff --git a/lbplanner/services/slots/get_supervisor_slots.php b/lbplanner/services/slots/get_supervisor_slots.php new file mode 100644 index 00000000..2a50347a --- /dev/null +++ b/lbplanner/services/slots/get_supervisor_slots.php @@ -0,0 +1,65 @@ +. + +namespace local_lbplanner_services; + +use external_api; +use external_function_parameters; +use external_multiple_structure; +use local_lbplanner\helpers\slot_helper; +use local_lbplanner\model\slot; + +/** + * Returns all slots a supervisor can see. + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class slots_get_supervisor_slots extends external_api { + /** + * Parameters for get_supervisor_slots. + * @return external_function_parameters + */ + public static function get_supervisor_slots_parameters(): external_function_parameters { + return new external_function_parameters([]); + } + + /** + * Returns all slots a supervisor controls. + * @param int $userid ID of the user in question (NOT the supervisor) + */ + public static function get_supervisor_slots(int $userid): array { + global $USER; + self::validate_parameters( + self::get_supervisor_slots_parameters(), + ['userid' => $userid] + ); + + return slot_helper::get_supervisor_slots($USER->id); + } + + /** + * Returns the structure of the slot array + * @return external_multiple_structure + */ + public static function get_supervisor_slots_returns(): external_multiple_structure { + return new external_multiple_structure( + slot::api_structure() + ); + } +} From 23f4869fd017267881f3c10bdfa05d02d65d1a8d Mon Sep 17 00:00:00 2001 From: Lisa Magdalena Riedler Date: Sun, 21 Jul 2024 05:08:51 +0200 Subject: [PATCH 42/92] docs: fix php docs parser (#80) * try to parse return struct defs * minor refactors & fixes * removed embedded script, modify file instead of overwrite * removed unused import * a tiny bit of OO * OO for returns data * some OO for Parameter Info * big steps in getting it to work * replaced functions' fullname with shortname * various minor fixes * ensured return body to be null, not unparseable * added parsing for enums * implemented enum parsing for params * ensured params are either nonempty or null * mildly better warn system * fix: put a newline between a warning and its context * feat: parse optional external_value params in returns as well also merged the params regex and returns regex into one * fix: invalid structure definition in notifications helper * feat: capabilities are now in an array instead of a string * feat: check if default is either a valid literal or known special variable Check default values for known special vars and replace them with a more readable representation. --------- Co-authored-by: McQuenji <60017181+mcquenji@users.noreply.github.com> --- document_services.py | 485 ++++++++++-------- .../classes/helpers/notifications_helper.php | 2 +- .../notifications/update_notification.php | 3 +- 3 files changed, 271 insertions(+), 219 deletions(-) diff --git a/document_services.py b/document_services.py index be870679..51e3c663 100644 --- a/document_services.py +++ b/document_services.py @@ -3,63 +3,161 @@ import sys from os import path -def extract_function_info(file_content): +from typing import Any + +HAS_WARNED = False + +MOODLESTRUCT_REGEX = r"(?:['\"](\w+)['\"]\s*=>|return)\s*new\s*external_value\s*\(\s*(PARAM_\w+)\s*,\s*((?:(['\"]).+?\4)(?:\s*\.\s*(?:\w+::format\(\))|'.*?')*)(?:,\s*(\w+)(?:,\s*([^,]+?)(?:,\s*(\w+),?)?)?)?\s*\)" + + +SPECIAL_VARS = { + "$USER->id": "derived from token", +} +""" +A map of special variables and the value to replace them with to make them more readable. +""" + + +def warn(msg: str, *context: Any): + """Prints a warning message to the console and sets the global HAS_WARNED variable to True. + + :param str msg: The warning message to print. + """ + global HAS_WARNED + WARN = "\033[43m\033[30mWARN:\033[0m " + WARN_TAB = " \033[43m \033[0m " + + HAS_WARNED = True + + print(WARN, msg, f"\n{WARN_TAB}", *[str(c).replace('\n', '\n' + WARN_TAB) for c in context]) + +class SlotsDict: + @property + def __dict__(self): + slots = tuple() + + for cls in self.__class__.__mro__: + if cls != SlotsDict and issubclass(cls, SlotsDict): + slots = cls.__slots__ + slots + return {name: self.__getattribute__(name) for name in slots} + +class ReturnInfo(SlotsDict): + __slots__ = ('type', 'description', 'nullable') + + def __init__(self, type: str, description: str, nullable: bool): + self.type = type + self.description = description + self.nullable = nullable + +class ParamInfo(SlotsDict): + __slots__ = ('type', 'description', 'required', 'default_value', 'nullable') + + def __init__(self, + type: str, + description: str, + required: bool, + default_value: str | None, + nullable: bool): + self.type = type + self.description = description + self.required = required + self.default_value = default_value + self.nullable = nullable + +class FunctionInfo(SlotsDict): + __slots__ = ('name', 'group', 'capabilities', 'description', 'path') + + def __init__(self, name: str, group: str, capabilities: list[str], description: str, path: str): + self.name = name + self.group = group + self.capabilities = capabilities + self.description = description + self.path = path + +class FunctionInfoEx(FunctionInfo): + __slots__ = ('parameters', 'returns', 'returns_multiple') + + def __init__(self, + parent: FunctionInfo, + parameters: dict[str, ParamInfo], + returns: dict[str, ReturnInfo], + returns_multiple: bool): + super().__init__(**parent.__dict__) + + self.parameters = parameters + self.returns = returns + self.returns_multiple = returns_multiple + +def extract_function_info(file_content: str) -> list[FunctionInfo]: function_info = [] # Removing comments, PHP tags, and definitions clean_content = re.sub(r"//.*|<\?php|defined\(.*\)\s*\|\|\s*die\(\);", "", file_content) # Splitting the content based on function definition blocks - functions = re.findall(r"'(.*?)' => array\((.*?)\),", clean_content, re.DOTALL) + # https://regex101.com/r/qyzYks + functions = re.findall(r"'(local_lbplanner_(\w+?)_(\w+))' => \[(.*?)\],", clean_content, re.DOTALL) for function in functions: func_dict = {} # Extracting function name and group - func_name_match = re.match(r"local_lbplanner_(.*?)_(.*)", function[0]) - if func_name_match: - func_dict["function_name"] = function[0] - func_dict["group"] = func_name_match.group(1) - else: - continue + func_dict["name"] = function[2] + func_dict["group"] = function[1] # Extracting and adjusting capabilities - capabilities = re.search(r"'capabilities' => '.*:(.*?)'", function[1]) - func_dict["capabilities"] = capabilities.group(1) if capabilities else None + capabilities = re.search(r"'capabilities' => '.*:(.*?)'", function[3]) + if capabilities is None: + # check if call needs no capabilities + capabilities = re.search(r"'capabilities' => ''", function[3]) + func_dict["capabilities"] = [] if capabilities else None + else: + func_dict["capabilities"] = [cap.strip() for cap in capabilities.group(1).split(',') if len(cap) > 0] # Extracting description - description = re.search(r"'description' => '(.*?)'", function[1]) + description = re.search(r"'description' => '(.*?)'", function[3]) func_dict["description"] = description.group(1) if description else None # Extracting and adjusting path - classpath = re.search(r"'classpath' => 'local/(.*?)'", function[1]) + classpath = re.search(r"'classpath' => 'local/(.*?)'", function[3]) func_dict["path"] = classpath.group(1) if classpath else None # Only adding to the list if all information is present if all(value is not None for value in func_dict.values()): - function_info.append(func_dict) + function_info.append(FunctionInfo(**func_dict)) + else: + warn(f"Could not gather all info for {func_dict["function_name"]}", func_dict) + + if len(function_info) == 0: + warn("Couldn't find any functions!") return function_info -def extract_php_functions(php_code): +def extract_php_functions(php_code: str, name: str) -> tuple[str | None, str | None]: # Regular expression to match the function names and bodies - pattern = re.compile(r"(public static function \w+_(?:returns|parameters).*?{.*?})", re.DOTALL) + # https://regex101.com/r/9GtIMA + pattern = re.compile(r"(public static function (\w+_(?:returns|parameters))\W[^{}]*?{[^{}]+?})", re.DOTALL) # Find all matches in the PHP code - matches = pattern.findall(php_code) + matches: list[tuple[str, str]] = pattern.findall(php_code) parameters_function = None returns_function = None for match in matches: # Extract function name - function_name = re.search(r"public static function (\w+)", match).group(1) + function_name = match[1] if function_name.endswith("_parameters"): - parameters_function = match + parameters_function = match[0] elif function_name.endswith("_returns"): - returns_function = match + returns_function = match[0] + + if parameters_function is None: + warn(f"Couldn't find parameters function in {name}") + if returns_function is None: + warn(f"Couldn't find returns function in {name}") return parameters_function, returns_function @@ -78,7 +176,7 @@ def parse_imports(input_str: str, symbol: str) -> str: if namespace is not None: p[0] = namespace - fp_l.append(path.join("lbplanner",*p,f"{symbol}.php")) + fp_l.append(path.join("lbplanner", *p, f"{symbol}.php")) if len(fp_l) > 1: raise Exception("found import collision?") @@ -87,44 +185,141 @@ def parse_imports(input_str: str, symbol: str) -> str: else: return fp_l[0] -def parse_returns(input_str: str, file_content: str): - pattern = r"'(\w+)' => new external_value\((\w+), '([^']+)'" - redir_pattern = r"(\w+)::(\w+)\(\)" +def parse_phpstuff(inpot: str) -> str: + # https://regex101.com/r/p5FzCh + casepattern = r"const (\w+) = (\d+|true|false|(['\"]).*?\3)" + + if inpot.endswith('::format()'): + enum_name = inpot[:-10] + fullbody_pattern = f"class {enum_name} extends Enum {{.*?}}" + + with open(f"lbplanner/classes/enums/{enum_name}.php", "r") as f: + matches = re.findall(fullbody_pattern, f.read(), re.DOTALL) + if len(matches) == 1: + body = matches[0] + else: + warn(f"couldn't parse enum {enum_name}", matches) + + cases = {} + matches = re.findall(casepattern, body) + for match in matches: + # capitalizing first letter, if exists + name = "".join([match[0][0].upper(), match[0][1:].lower()]) + cases[name] = match[1].replace("'", '"') + + return "{ " + ", ".join([f"{name} = {value}" for name, value in cases.items()]) + " }" + else: + warn('unknown phpstuff', inpot) + return "" + +def parse_phpstring(inpot: str) -> str: + WHITESPACE = '. \t\n\r' # the . is for string concat in php + + out = [] + strlit = False + quotetype = '' + tmp_refarr: list[str] = [] + for char in inpot: + if char in '\'"': + if not strlit: + strlit = True + quotetype = char + if len(tmp_refarr) > 0: + out.append(parse_phpstuff("".join(tmp_refarr))) + tmp_refarr = [] + else: + if char == quotetype: + strlit = False + else: + out.append(char) + else: + if strlit: + out.append(char) + else: + if char in WHITESPACE: + continue + else: + tmp_refarr.append(char) + + if len(tmp_refarr) > 0: + out.append(parse_phpstuff("".join(tmp_refarr))) + tmp_refarr = [] + + return "".join(out) + +def parse_returns(input_str: str, file_content: str, name: str) -> tuple[dict[str, ReturnInfo], bool]: + # https://regex101.com/r/gUtsX3/ + redir_pattern = r"(\w+)::(\w+)(? 1: - raise Exception(f"Couldn't parse return values") + warn(f"Couldn't parse return values in {name}", input_str) + return ({}, False) if len(matches) == 1: match = matches[0] meth_pattern = rf"public static function {match[1]}\(\)(?: ?: ?\w+)? ?{{(?P.*?)}}" fp = parse_imports(file_content, match[0]) - with open(fp,"r") as f: + with open(fp, "r") as f: new_file_content = f.read() - matches = re.findall(meth_pattern,new_file_content,re.DOTALL) + matches = re.findall(meth_pattern, new_file_content, re.DOTALL) if len(matches) == 0: - raise Exception(f"Couldn't find {match[0]}::{match[1]}() inside {fp}") + warn(f"Couldn't find {match[0]}::{match[1]}() inside {fp} for {name}") + return ({}, False) elif len(matches) > 1: raise Exception(f"Found multiple definitions for {match[0]}::{match[1]}() inside {fp}") else: - r= parse_returns(matches[0],new_file_content) - return r + result = parse_returns(matches[0], new_file_content, fp) + + # if multiple_structure is detected here, add it + if is_multiple_structure: + return (result[0], True) + else: + return result - matches = re.findall(pattern, input_str) + matches = re.findall(MOODLESTRUCT_REGEX, input_str) output_dict = {} for match in matches: - key, value_type, description = match - output_dict[key] = {"type": convert_param_type_to_normal_type(value_type), "description": description} + key = match[0] + if key is None: + if len(matches) > 1: + warn("got empty return key name in a structure larger than 1", matches) + else: + key = '' + value_type = match[1] + description = parse_phpstring(match[2]) + required_str = match[4] + default_str = match[5] + nullable_str = match[6] + + if required_str not in ('VALUE_REQUIRED', ''): + warn(f"found optional value in returns structure for {name}", input_str) + if default_str not in ('null', ''): + warn(f"found non-null 'default value' in returns structure for {name}: {default_str}", input_str) + if nullable_str in ('', 'NULL_NOT_ALLOWED'): + nullable = False + elif nullable_str == 'NULL_ALLOWED': + nullable = True # weird, but I'll allow it + else: + warn(f"found weird value for nullable in {name}: {nullable_str}", input_str) - # Check for the presence of 'external_multiple_structure' - is_multiple_structure = "external_multiple_structure" in input_str + output_dict[key] = ReturnInfo(convert_param_type_to_normal_type(value_type), description, nullable) + + if len(output_dict) == 0: + if re.match(nullensure_pattern, input_str) is None: + warn(f"could not find any returns in non-empty {name}", input_str) return output_dict, is_multiple_structure -def convert_param_type_to_normal_type(param_type): +def convert_param_type_to_normal_type(param_type: str) -> str: CONVERSIONS = { "PARAM_INT": "int", "PARAM_TEXT": "String", @@ -135,211 +330,67 @@ def convert_param_type_to_normal_type(param_type): return CONVERSIONS.get(param_type, param_type) -def parse_params(input_text): +def parse_params(input_text: str) -> dict[str, ParamInfo]: # Regular expression to match the parameters inside the 'new external_value()' function - pattern = r"'(\w+)' => new external_value\s*\(\s*(\w+)\s*,\s*'([^']+)',\s*(\w+),\s*([\w\d]+|\w+),\s*(\w+)\s*\)" # Find all matches of the pattern in the input text - matches = re.findall(pattern, input_text) + matches = re.findall(MOODLESTRUCT_REGEX, input_text) + + if len(matches) == 0: + nullensure_pattern = r".*return new external_function_parameters(\s*\[\]\s*);.*" + if re.match(nullensure_pattern, input_text) is not None: + warn("could not parse params", input_text) + return {} result = {} for match in matches: param_name = match[0] - result[param_name] = { - "type": convert_param_type_to_normal_type(match[1]), - "description": match[2], - "required": True if match[3] == "VALUE_REQUIRED" else False, - "default_value": match[4] if match[4] != "null" else None, - "nullable": False if match[5] == "NULL_NOT_ALLOWED" else True, - } + result[param_name] = ParamInfo( + convert_param_type_to_normal_type(match[1]), + parse_phpstring(match[2]), + True if match[4] == "VALUE_REQUIRED" else False, + SPECIAL_VARS.get(match[5], match[5]) if match[5] != "null" else None, + False if match[6] == "NULL_NOT_ALLOWED" else True, + ) return result -SCRIPT = r""" - -const funcs = /* JSON data here */; - - -let groups = []; - -for (let func of funcs) { - let group = groups.find(g => g.groupName === func.group); - if (!group) { - group = { - groupName: func.group, - functions: [] - }; - groups.push(group); - } - group.functions.push(func); -} - -const sidebar = document.getElementById('sidebar'); -const content = document.getElementById('content'); - -let currentFunction = null; - - -function searchFunction() { - - const input = document.getElementById('search').value.toUpperCase(); - const functions = document.querySelectorAll('.func-name'); - - for (let i = 0; i < functions.length; i++) { - const textValue = functions[i].textContent || functions[i].innerText; - if (funcName(textValue).toUpperCase().includes(input)) { - functions[i].style.display = ""; - } else { - functions[i].style.display = "none"; - } - } - - // check for func-group and if it has any children that are visible and if not hide it - const groups = document.querySelectorAll('.func-group'); - for (let group of groups) { - let visible = false; - for (let child of group.children) { - if (!child.classList.contains('func-name')) continue; - - child.style.display !== 'none' ? visible = true : null; - - if (visible) break; - } - - visible ? group.style.display = '' : group.style.display = 'none'; - } -} - -const groupsElement = document.querySelector('#func-groups'); -const detailsPane = document.querySelector('#func-details'); - -function displayGroupsAndFunctions() { - groups.forEach(group => { - const groupElement = document.createElement('div'); - groupElement.classList.add('func-group'); - - groupName = document.createElement('h1'); - groupName.textContent = group.groupName; - - groupElement.appendChild(groupName); - groupsElement.appendChild(groupElement); - - group.functions.forEach(func => { - const funcElement = document.createElement('p'); - funcElement.classList.add('func-name'); - funcElement.textContent = func.function_name; - funcElement.onclick = () => { - if (currentFunction) { - currentFunction.removeAttribute('active'); - } - - funcElement.setAttribute('active', ''); - - currentFunction = funcElement; - - displayFunctionDetails(func); - }; - groupElement.appendChild(funcElement); - }); - }); - let bottomSpacer = document.createElement('div'); - bottomSpacer.style.height = '100px'; - groupsElement.appendChild(bottomSpacer); -} - -function funcName(fullName) { - // remove everything from the third underscore - const split = fullName.split('_'); - return split.slice(3, split.length).join(' '); -} - -function displayFunctionDetails(func) { - - detailsPane.innerHTML = ` -

${funcName(func.function_name)}

-

${func.function_name}

-
-

${func.description}

-

Capabilities

-
-

${func.capabilities}

-

Parmeters

-
- ${Object.keys(func.parameters).map(param => ` -
-
-

${param}

-

${func.parameters[param].type}

-

${func.parameters[param].required ? 'required' : 'optional'}

-
-

${func.parameters[param].description}

-
-`).join('')} -

Returns${func.returns_multiple ? '

Array

' : ""}

-
- ${Object.keys(func.returns).map(ret => ` -
-
-

${ret}

-

${func.returns[ret].type}

-
-

${func.returns[ret].description}

-
-`).join('')} - `; - - let copy = document.getElementById('copy'); - copy.onclick = () => { - navigator.clipboard.writeText(func.function_name); - } - - let returnValues = document.querySelectorAll('.value-name'); - let params = document.querySelectorAll('.param-name'); - - for (let value of returnValues){ - value.addEventListener('click', () => { - navigator.clipboard.writeText(value.innerText) - }); - } - - for (let param of params){ - param.addEventListener('click', () => { - navigator.clipboard.writeText(param.innerText) - }); - } -} - -displayGroupsAndFunctions(); - -document.getElementById('search').addEventListener('keyup', searchFunction); -""" - if __name__ == "__main__": with open("lbplanner/db/services.php", "r") as file: content = file.read() - info = extract_function_info(content) + infos = extract_function_info(content) complete_info = [] - for i, info in enumerate(info): - with open(info["path"], "r") as func_file: + for i, info in enumerate(infos): + with open(info.path, "r") as func_file: func_content = func_file.read() - params_func, returns_func = extract_php_functions(func_content) + params_func, returns_func = extract_php_functions(func_content, info.path) - returns, returns_multiple = parse_returns(returns_func,func_content) + if returns_func is None or params_func is None: + continue - incomplete_info = info + returns, returns_multiple = parse_returns(returns_func, func_content, info.path) params = parse_params(params_func) - incomplete_info["parameters"] = params - incomplete_info["returns"] = returns - incomplete_info["returns_multiple"] = returns_multiple + complete_info.append(FunctionInfoEx(info, params, returns, returns_multiple)) + + data = json.dumps(complete_info, default=lambda x: x.__dict__) + declaration = f"const funcs = {data}" - complete_info.append(incomplete_info) + script: str + with open(f"{sys.argv[1]}/script.js", "r") as f: + script = f.read() + lines = script.splitlines() + for i in range(len(lines)): + if lines[i].startswith('const funcs = '): + lines[i] = declaration + script = "\n".join(lines) - script = SCRIPT.replace("/* JSON data here */", json.dumps(complete_info)) + with open(f"{sys.argv[1]}/script.js", "w") as f: + f.write(script) - with open(f"{sys.argv[1]}/script.js", "w") as output_file: - output_file.write(script) + if HAS_WARNED: + sys.exit(1) diff --git a/lbplanner/classes/helpers/notifications_helper.php b/lbplanner/classes/helpers/notifications_helper.php index adf1c50d..706b5857 100644 --- a/lbplanner/classes/helpers/notifications_helper.php +++ b/lbplanner/classes/helpers/notifications_helper.php @@ -49,7 +49,7 @@ public static function structure(): external_single_structure { new external_value(PARAM_INT, 'The type of the event that triggered the notification ' . NOTIF_TRIGGER::format()), 'info' => new external_value(PARAM_INT, 'Additional information about the notification'), 'userid' => new external_value(PARAM_INT, 'The ID of the user for whom the notification is for'), - 'notificationid' => new external_value(PARAM_INT, 'The ID of the notification', NULL_NOT_ALLOWED), + 'notificationid' => new external_value(PARAM_INT, 'The ID of the notification', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), 'timestamp' => new external_value(PARAM_INT, 'The timestamp of the notification'), 'timestamp_read' => new external_value(PARAM_INT, 'The timestamp of the notification when it was read'), ]); diff --git a/lbplanner/services/notifications/update_notification.php b/lbplanner/services/notifications/update_notification.php index 3fdbf6d0..4362837b 100644 --- a/lbplanner/services/notifications/update_notification.php +++ b/lbplanner/services/notifications/update_notification.php @@ -19,6 +19,7 @@ use external_api; use external_function_parameters; use external_value; +use local_lbplanner\enums\NOTIF_STATUS; use local_lbplanner\helpers\notifications_helper; /** @@ -38,7 +39,7 @@ public static function update_notification_parameters(): external_function_param return new external_function_parameters([ 'status' => new external_value( PARAM_INT, - 'notification status {0: unread, 1: read}', + 'notification status ' . NOTIF_STATUS::format(), VALUE_REQUIRED, null, NULL_NOT_ALLOWED From 29dccb8ec6590bfc224065fac2b4cd121871027f Mon Sep 17 00:00:00 2001 From: Lisa Magdalena Riedler Date: Mon, 22 Jul 2024 23:52:18 +0200 Subject: [PATCH 43/92] fix: various parsing issues (#81) * correctly parse default parameter values * adjusted workflow to work in the way the new script behaviour expects * feat: warnings now print to stderr, dump json to stdout if "-" is passed * feat: doc parsing action for PRs * updated actions python to 3.12 * fix: new testing action now reads from PR, not LP-55 (oops) * refactor: minor stuff, makes LSP happy, more checking * style: minor formatting fix broke up line over 120 characters by splitting into three also added missing regex101 link to regex also removed orphaned blockcomment * more context for warnings * fix: reverted breaking webUI detection of derived userid * fix: capabilities now parsed with their namespace * refactor: better namespace handling in parse_imports --- .github/workflows/gen_docs.yaml | 6 +- .github/workflows/test_docs.yaml | 28 ++++ document_services.py | 246 +++++++++++++++++++------------ 3 files changed, 184 insertions(+), 96 deletions(-) create mode 100644 .github/workflows/test_docs.yaml diff --git a/.github/workflows/gen_docs.yaml b/.github/workflows/gen_docs.yaml index 50d2e622..702ed56f 100644 --- a/.github/workflows/gen_docs.yaml +++ b/.github/workflows/gen_docs.yaml @@ -27,11 +27,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4.7.1 with: - python-version: '3.10' - - - name: Clear old documentation in /moodle subdir - run: | - rm -f docs/moodle/script.js + python-version: '3.12' - name: Generate docs working-directory: moodle diff --git a/.github/workflows/test_docs.yaml b/.github/workflows/test_docs.yaml new file mode 100644 index 00000000..6c0dafe1 --- /dev/null +++ b/.github/workflows/test_docs.yaml @@ -0,0 +1,28 @@ +name: API Doc Parsing + +on: + pull_request: + types: + - opened + - synchronize + branches: + - LP-55-Backend-Refactor # Temporary. Will be changed to `moodle` when refactor is complete + +jobs: + generate-api-docs: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + with: + path: moodle + + - name: Setup Python + uses: actions/setup-python@v4.7.1 + with: + python-version: '3.12' + + - name: Generate docs + working-directory: moodle + run: python document_services.py - diff --git a/document_services.py b/document_services.py index 51e3c663..55c03f20 100644 --- a/document_services.py +++ b/document_services.py @@ -2,21 +2,17 @@ import re import sys from os import path +import traceback as tb from typing import Any -HAS_WARNED = False - -MOODLESTRUCT_REGEX = r"(?:['\"](\w+)['\"]\s*=>|return)\s*new\s*external_value\s*\(\s*(PARAM_\w+)\s*,\s*((?:(['\"]).+?\4)(?:\s*\.\s*(?:\w+::format\(\))|'.*?')*)(?:,\s*(\w+)(?:,\s*([^,]+?)(?:,\s*(\w+),?)?)?)?\s*\)" - - -SPECIAL_VARS = { - "$USER->id": "derived from token", -} -""" -A map of special variables and the value to replace them with to make them more readable. -""" +# https://regex101.com/r/kgCV7K +MOODLESTRUCT_REGEX = r"(?:['\"](\w+)['\"]\s*=>|return)\s*new\s*" \ + r"external_value\s*\(\s*(PARAM_\w+)\s*,\s*((?:(['\"]).+?\4)(?:\s*\.\s*(?:\w+::format\(\))|'.*?')*)" \ + r"(?:,\s*(\w+)(?:,\s*([^,]+?)(?:,\s*(\w+),?)?)?)?\s*\)" +HAS_WARNED = False +CURRENT_SERVICE: str | None = None def warn(msg: str, *context: Any): """Prints a warning message to the console and sets the global HAS_WARNED variable to True. @@ -25,11 +21,77 @@ def warn(msg: str, *context: Any): """ global HAS_WARNED WARN = "\033[43m\033[30mWARN:\033[0m " - WARN_TAB = " \033[43m \033[0m " + WARN_TAB = " \033[43m\033[33m|\033[0m " HAS_WARNED = True - print(WARN, msg, f"\n{WARN_TAB}", *[str(c).replace('\n', '\n' + WARN_TAB) for c in context]) + stack = tb.extract_stack() + stack_str = " -> ".join([f"\033[34m{frame.name}\033[0m" for frame in stack if frame != stack[-1]]) + + service_msg: str + if CURRENT_SERVICE is None: + service_msg = "outside any service" + else: + service_msg = f"in service \033[36m{CURRENT_SERVICE}\033[0m" + + print( + f"{WARN}\033[31m{msg}\033[0m {service_msg} ({stack_str})", + f"\n{WARN_TAB} " if len(context) > 0 else "", + *[f"\033[2m{c}\033[0m".replace('\n', '\n\033[0m' + WARN_TAB + " \033[2m") for c in context], + file=sys.stderr, + sep="" + ) + +def convert_php_type_to_normal_type(param_type: str) -> str: + CONVERSIONS = { + "PARAM_INT": "int", + "PARAM_TEXT": "String", + "PARAM_URL": "String", + "PARAM_BOOL": "bool", + } + + return CONVERSIONS.get(param_type, param_type) + +def explain_php_value(val: str) -> tuple[None | str | int | bool, str]: + SPECIAL_VALUES = { + "$USER->id": ("derived from token", "int"), # this exact phrase is checked for in the web UI + "null": (None, "") + } + + if val in SPECIAL_VALUES.keys(): + return SPECIAL_VALUES[val] + elif val.isnumeric(): + return (int(val), "int") + elif val.lower() in ("true", "false"): + return (val.lower() == "true", "bool") + elif val[0] + val[-1] in ("''", '""'): + + # see if the same kind of quote is within string + if val[1:-1].count(val[0]) > 0: + warn("found potentially non-literal string", val) + + return (val[1:-1], "String") + else: + warn("found unknown value", val) + return (f"unknown: {val}", "unknown") + +def parse_isrequired(inpot: str) -> bool | None: + if inpot in ('VALUE_REQUIRED', ''): + return True + elif inpot == 'VALUE_DEFAULT': + return False + else: + warn("found unparseable value for isrequired", inpot) + return None + +def parse_nullable(inpot: str) -> bool | None: + if inpot in ('', 'NULL_NOT_ALLOWED'): + return False + elif inpot == 'NULL_ALLOWED': + return True + else: + warn(f"found weird value for nullable: {inpot}") + return None class SlotsDict: @property @@ -44,10 +106,10 @@ def __dict__(self): class ReturnInfo(SlotsDict): __slots__ = ('type', 'description', 'nullable') - def __init__(self, type: str, description: str, nullable: bool): - self.type = type + def __init__(self, type: str, description: str, nullable: str): + self.type = convert_php_type_to_normal_type(type) self.description = description - self.nullable = nullable + self.nullable = parse_nullable(nullable) class ParamInfo(SlotsDict): __slots__ = ('type', 'description', 'required', 'default_value', 'nullable') @@ -55,14 +117,20 @@ class ParamInfo(SlotsDict): def __init__(self, type: str, description: str, - required: bool, - default_value: str | None, - nullable: bool): - self.type = type + required: str, + default_value: str, + nullable: str): + + self.type = convert_php_type_to_normal_type(type) + + defval, deftype = explain_php_value(default_value) + if defval is not None and deftype != self.type: + warn(f"Type of default value does not match parameter type - {deftype} != {self.type}", description) + self.description = description - self.required = required - self.default_value = default_value - self.nullable = nullable + self.required = parse_isrequired(required) + self.default_value = defval + self.nullable = parse_nullable(nullable) class FunctionInfo(SlotsDict): __slots__ = ('name', 'group', 'capabilities', 'description', 'path') @@ -106,7 +174,7 @@ def extract_function_info(file_content: str) -> list[FunctionInfo]: func_dict["group"] = function[1] # Extracting and adjusting capabilities - capabilities = re.search(r"'capabilities' => '.*:(.*?)'", function[3]) + capabilities = re.search(r"'capabilities' => '(.*?:.*?)'", function[3]) if capabilities is None: # check if call needs no capabilities capabilities = re.search(r"'capabilities' => ''", function[3]) @@ -126,7 +194,7 @@ def extract_function_info(file_content: str) -> list[FunctionInfo]: if all(value is not None for value in func_dict.values()): function_info.append(FunctionInfo(**func_dict)) else: - warn(f"Could not gather all info for {func_dict["function_name"]}", func_dict) + warn(f"Could not gather all info for {func_dict["name"]}", func_dict) if len(function_info) == 0: warn("Couldn't find any functions!") @@ -161,27 +229,27 @@ def extract_php_functions(php_code: str, name: str) -> tuple[str | None, str | N return parameters_function, returns_function -def parse_imports(input_str: str, symbol: str) -> str: +def parse_imports(input_str: str, symbol: str) -> str | None: use_pattern = fr"use ((?:\w+\\)+){symbol};" uses: list[str] = re.findall(use_pattern, input_str) - namespaces = { - "local_lbplanner": "classes"# not entirely true, but good enough for now + namespaces = { # it's technically possible to import from outside /classes/ + "local_lbplanner\\helpers": "classes/helpers", + "local_lbplanner\\enums": "classes/enums", + "local_lbplanner\\polyfill": "classes/polyfill" } fp_l: list[str] = [] for use in uses: - p = use.split('\\')[:-1] - - namespace = namespaces.get(p[0]) - if namespace is not None: - p[0] = namespace - - fp_l.append(path.join("lbplanner", *p, f"{symbol}.php")) + for namespace, p in namespaces.items(): + if use.startswith(namespace): + fp_l.append(path.join(path.dirname(__file__), "lbplanner", p, f"{symbol}.php")) if len(fp_l) > 1: - raise Exception("found import collision?") + warn(f"found potential import collision for {symbol}", input_str) + return None elif len(fp_l) == 0: - raise Exception(f"Couldn't find symbol: {symbol}") + warn(f"Couldn't find symbol: {symbol}", input_str) + return None else: return fp_l[0] @@ -193,8 +261,12 @@ def parse_phpstuff(inpot: str) -> str: enum_name = inpot[:-10] fullbody_pattern = f"class {enum_name} extends Enum {{.*?}}" - with open(f"lbplanner/classes/enums/{enum_name}.php", "r") as f: - matches = re.findall(fullbody_pattern, f.read(), re.DOTALL) + fp = f"lbplanner/classes/enums/{enum_name}.php" + if not path.exists(fp): + warn(f"Couldn't find enum file {fp}") + return "" + with open(fp, "r") as f: + matches: list[str] = re.findall(fullbody_pattern, f.read(), re.DOTALL) if len(matches) == 1: body = matches[0] else: @@ -256,26 +328,30 @@ def parse_returns(input_str: str, file_content: str, name: str) -> tuple[dict[st # Check for the presence of 'external_multiple_structure' is_multiple_structure = "external_multiple_structure" in input_str - matches = re.findall(redir_pattern, input_str) - if len(matches) > 1: + redir_matches: list[list[str]] = re.findall(redir_pattern, input_str) + if len(redir_matches) > 1: warn(f"Couldn't parse return values in {name}", input_str) return ({}, False) - if len(matches) == 1: - match = matches[0] + if len(redir_matches) == 1: + match = redir_matches[0] meth_pattern = rf"public static function {match[1]}\(\)(?: ?: ?\w+)? ?{{(?P.*?)}}" fp = parse_imports(file_content, match[0]) + if fp is None: + # already warned in parse_imports, we don't need to warn again + return {}, is_multiple_structure + with open(fp, "r") as f: new_file_content = f.read() - matches = re.findall(meth_pattern, new_file_content, re.DOTALL) - if len(matches) == 0: + meth_matches: list[str] = re.findall(meth_pattern, new_file_content, re.DOTALL) + if len(meth_matches) == 0: warn(f"Couldn't find {match[0]}::{match[1]}() inside {fp} for {name}") return ({}, False) - elif len(matches) > 1: + elif len(meth_matches) > 1: raise Exception(f"Found multiple definitions for {match[0]}::{match[1]}() inside {fp}") else: - result = parse_returns(matches[0], new_file_content, fp) + result = parse_returns(meth_matches[0], new_file_content, fp) # if multiple_structure is detected here, add it if is_multiple_structure: @@ -283,7 +359,7 @@ def parse_returns(input_str: str, file_content: str, name: str) -> tuple[dict[st else: return result - matches = re.findall(MOODLESTRUCT_REGEX, input_str) + matches: list[list[str]] = re.findall(MOODLESTRUCT_REGEX, input_str) output_dict = {} for match in matches: @@ -293,24 +369,15 @@ def parse_returns(input_str: str, file_content: str, name: str) -> tuple[dict[st warn("got empty return key name in a structure larger than 1", matches) else: key = '' - value_type = match[1] - description = parse_phpstring(match[2]) - required_str = match[4] - default_str = match[5] - nullable_str = match[6] - if required_str not in ('VALUE_REQUIRED', ''): + if not parse_isrequired(match[4]): warn(f"found optional value in returns structure for {name}", input_str) + + default_str = match[5] if default_str not in ('null', ''): warn(f"found non-null 'default value' in returns structure for {name}: {default_str}", input_str) - if nullable_str in ('', 'NULL_NOT_ALLOWED'): - nullable = False - elif nullable_str == 'NULL_ALLOWED': - nullable = True # weird, but I'll allow it - else: - warn(f"found weird value for nullable in {name}: {nullable_str}", input_str) - output_dict[key] = ReturnInfo(convert_param_type_to_normal_type(value_type), description, nullable) + output_dict[key] = ReturnInfo(match[1], parse_phpstring(match[2]), match[6]) if len(output_dict) == 0: if re.match(nullensure_pattern, input_str) is None: @@ -318,23 +385,11 @@ def parse_returns(input_str: str, file_content: str, name: str) -> tuple[dict[st return output_dict, is_multiple_structure - -def convert_param_type_to_normal_type(param_type: str) -> str: - CONVERSIONS = { - "PARAM_INT": "int", - "PARAM_TEXT": "String", - "PARAM_URL": "String", - "PARAM_BOOL": "bool", - } - - return CONVERSIONS.get(param_type, param_type) - - def parse_params(input_text: str) -> dict[str, ParamInfo]: # Regular expression to match the parameters inside the 'new external_value()' function # Find all matches of the pattern in the input text - matches = re.findall(MOODLESTRUCT_REGEX, input_text) + matches: list[list[str]] = re.findall(MOODLESTRUCT_REGEX, input_text) if len(matches) == 0: nullensure_pattern = r".*return new external_function_parameters(\s*\[\]\s*);.*" @@ -346,11 +401,11 @@ def parse_params(input_text: str) -> dict[str, ParamInfo]: for match in matches: param_name = match[0] result[param_name] = ParamInfo( - convert_param_type_to_normal_type(match[1]), + match[1], parse_phpstring(match[2]), - True if match[4] == "VALUE_REQUIRED" else False, - SPECIAL_VARS.get(match[5], match[5]) if match[5] != "null" else None, - False if match[6] == "NULL_NOT_ALLOWED" else True, + match[4], + match[5], + match[6], ) return result @@ -364,6 +419,9 @@ def parse_params(input_text: str) -> dict[str, ParamInfo]: complete_info = [] for i, info in enumerate(infos): + + CURRENT_SERVICE = info.name + with open(info.path, "r") as func_file: func_content = func_file.read() params_func, returns_func = extract_php_functions(func_content, info.path) @@ -377,20 +435,26 @@ def parse_params(input_text: str) -> dict[str, ParamInfo]: complete_info.append(FunctionInfoEx(info, params, returns, returns_multiple)) + CURRENT_SERVICE = None + data = json.dumps(complete_info, default=lambda x: x.__dict__) - declaration = f"const funcs = {data}" - - script: str - with open(f"{sys.argv[1]}/script.js", "r") as f: - script = f.read() - lines = script.splitlines() - for i in range(len(lines)): - if lines[i].startswith('const funcs = '): - lines[i] = declaration - script = "\n".join(lines) - - with open(f"{sys.argv[1]}/script.js", "w") as f: - f.write(script) + + if sys.argv[1] == "-": + print(data) + else: + declaration = f"const funcs = {data}" + + script: str + with open(f"{sys.argv[1]}/script.js", "r") as f: + script = f.read() + lines = script.splitlines() + for i in range(len(lines)): + if lines[i].startswith('const funcs = '): + lines[i] = declaration + script = "\n".join(lines) + + with open(f"{sys.argv[1]}/script.js", "w") as f: + f.write(script) if HAS_WARNED: sys.exit(1) From f60b499c23d1d4efe4b14bd79443d3756ff55c27 Mon Sep 17 00:00:00 2001 From: RiedleroD Date: Sat, 13 Jul 2024 15:20:26 +0200 Subject: [PATCH 44/92] feat: booking reservations --- lbplanner/classes/helpers/slot_helper.php | 56 +++++-- lbplanner/classes/model/reservation.php | 56 +++++++ lbplanner/db/services.php | 40 +++++ lbplanner/services/slots/book_reservation.php | 142 ++++++++++++++++++ 4 files changed, 282 insertions(+), 12 deletions(-) create mode 100644 lbplanner/services/slots/book_reservation.php diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 576d88b8..f487d4b2 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -27,7 +27,7 @@ use DateInterval; use DateTime; use DateTimeImmutable; - +use DateTimeInterface; use external_api; use local_lbplanner\enums\WEEKDAY; use local_lbplanner\model\{slot, reservation, slot_filter}; @@ -149,7 +149,7 @@ public static function get_reservations_for_slot(int $slotid): array { $reservationsobj = []; foreach ($reservations as $reservation) { - $reservation['date'] = new \DateTime($reservation['date']); + $reservation['date'] = new DateTimeImmutable($reservation['date']); array_push($reservationsobj, new reservation(...$reservation)); } @@ -175,7 +175,8 @@ public static function get_filters_for_slot(int $slotid): array { } /** - * Filters an array of slots for the slots that the user can reserve. + * Filters an array of slots for the slots that the user can theoretically reserve + * NOTE: not taking into account time or fullness, only filters i.e. users' class and courses * @param slot[] $allslots the slots to filter * @param mixed $user a user object - e.g. $USER or a user object from the database * @return slot[] the filtered slot array @@ -219,15 +220,7 @@ public static function filter_slots_for_time(array $allslots, int $range): array $slots = []; // Calculate date and time each slot happens next, and add it to the return list if within reach from today. foreach ($allslots as $slot) { - $slotdaytime = self::SCHOOL_UNITS[$slot->startunit]; - $slotdatetime = DateTime::createFromFormat('Y-m-d H:i', $now->format('Y-m-d ').$slotdaytime); - // Move to next day this weekday occurs (doesn't move if it's the same as today). - $slotdatetime->modify('this '.WEEKDAY::name_from($slot->weekday)); - - // Check if slot is before now (because time of day and such) and move it a week into the future if so. - if ($now->diff($slotdatetime)->invert === 1) { - $slotdatetime->add(new DateInterval('P1W')); - } + $slotdatetime = self::calculate_slot_datetime($slot, $now); if ($now->diff($slotdatetime)->days <= $range) { array_push($slots, $slot->prepare_for_api()); @@ -235,4 +228,43 @@ public static function filter_slots_for_time(array $allslots, int $range): array } return $slots; } + + /** + * calculates when a slot is to happen next + * @param slot $slot the slot + * @param DateTimeInterface $now the point in time representing now + * @return DateTimeImmutable the next time this slot will occur + */ + public static function calculate_slot_datetime(slot $slot, DateTimeInterface $now): DateTimeImmutable { + $slotdaytime = self::SCHOOL_UNITS[$slot->startunit]; + // NOTE: format and fromFormat use different date formatting conventions + $slotdatetime = DateTime::createFromFormat('YY-MM-DD tHH:MM', $now->format('Y-m-d ').$slotdaytime); + // Move to next day this weekday occurs (doesn't move if it's the same as today). + $slotdatetime->modify('this '.WEEKDAY::name_from($slot->weekday)); + + // Check if slot is before now (because time of day and such) and move it a week into the future if so. + if ($now->diff($slotdatetime)->invert === 1) { + $slotdatetime->add(new DateInterval('P1W')); + } + + return new DateTimeImmutable($slotdatetime); + } + + /** + * Returns a list of all slots belonging to a supervisor. + * @param int $supervisorid userid of the supervisor in question + * + * @return slot[] An array of the slots. + */ + public static function check_slot_supervisor(int $supervisorid, int $slotid): bool { + global $DB; + + $result = $DB->get_record_sql( + 'SELECT supervisor.userid FROM '.self::TABLE_SUPERVISORS.' as supervisor'. + 'WHERE supervisor.userid=? AND supervisor.slotid=?', + [$supervisorid, $slotid] + ); + + return $result !== false; + } } diff --git a/lbplanner/classes/model/reservation.php b/lbplanner/classes/model/reservation.php index 513009b0..681fc3e4 100644 --- a/lbplanner/classes/model/reservation.php +++ b/lbplanner/classes/model/reservation.php @@ -25,6 +25,10 @@ namespace local_lbplanner\model; use DateTimeImmutable; + +use external_single_structure; +use external_value; + use local_lbplanner\model\slot; use local_lbplanner\helpers\slot_helper; @@ -56,6 +60,10 @@ class reservation { * @var ?slot $slot the linked slot (gets filled in by helper functions) */ private ?slot $slot; + /** + * @var ?DateTimeImmutable $datetime the date this reservation is for, with time filled in + */ + private ?DateTimeImmutable $datetime; /** * Constructs a reservation @@ -87,4 +95,52 @@ public function get_slot(): slot { return $this->slot; } + + /** + * Prepares data for the DB endpoint. + * + * @return object a representation of this reservation and its data + */ + public function prepare_for_db(): object { + $obj = new \stdClass(); + + $obj->slotid = $this->slotid; + $obj->date = $this->date; + $obj->userid = $this->userid; + $obj->reserverid = $this->reserverid; + + return $obj; + } + + /** + * Prepares data for the API endpoint. + * + * @return array a representation of this reservation and its data + */ + public function prepare_for_api(): array { + return [ + 'id' => $this->id, + 'slotid' => $this->slotid, + 'datetime' => $this->date->format('Y-m-d'), + 'userid' => $this->userid, + 'reserverid' => $this->reserverid, + ]; + } + + /** + * Returns the data structure of a reservation for the API. + * + * @return external_single_structure The data structure of a reservation for the API. + */ + public static function api_structure(): external_single_structure { + return new external_single_structure( + [ + 'id' => new external_value(PARAM_INT, 'reservation ID'), + 'slotid' => new external_value(PARAM_INT, 'ID of associated slot'), + 'date' => new external_value(PARAM_TEXT, 'date of the reservation in YYYY-MM-DD (as per ISO-8601)'), + 'userid' => new external_value(PARAM_INT, 'ID of the user this reservation is for'), + 'reserverid' => new external_value(PARAM_INT, 'ID of the user who submitted this reservation'), + ] + ); + } } diff --git a/lbplanner/db/services.php b/lbplanner/db/services.php index 2bf60516..1c5c5859 100644 --- a/lbplanner/db/services.php +++ b/lbplanner/db/services.php @@ -286,6 +286,42 @@ 'capabilities' => '', 'ajax' => true, ], + 'local_lbplanner_slots_get_my_slot' => [ + 'classname' => 'local_lbplanner_services\slots_get_my_slot', + 'methodname' => 'get_my_slot', + 'classpath' => 'local/lbplanner/services/slots/get_my_slot.php', + 'description' => 'Get all slots the user can theoretically reserve.', + 'type' => 'read', + 'capabilities' => 'local/lb_planner:student', + 'ajax' => true, + ], + 'local_lbplanner_slots_get_student_slots' => [ + 'classname' => 'local_lbplanner_services\slots_get_student_slots', + 'methodname' => 'get_student_slots', + 'classpath' => 'local/lbplanner/services/slots/get_student_slots.php', + 'description' => 'Get all slots a supervisor can theoretically reserve for a student.', + 'type' => 'read', + 'capabilities' => 'local/lb_planner:student', + 'ajax' => true, + ], + 'local_lbplanner_slots_get_supervisor_slots' => [ + 'classname' => 'local_lbplanner_services\slots_get_supervisor_slots', + 'methodname' => 'get_supervisor_slots', + 'classpath' => 'local/lbplanner/services/slots/get_supervisor_slots.php', + 'description' => 'Get all slots belonging to the supervisor.', + 'type' => 'read', + 'capabilities' => 'local/lb_planner:student', + 'ajax' => true, + ], + 'local_lbplanner_slots_book_reservation' => [ + 'classname' => 'local_lbplanner_services\slots_book_reservation', + 'methodname' => 'book_reservation', + 'classpath' => 'local/lbplanner/services/slots/book_reservation.php', + 'description' => 'Book a reservation', + 'type' => 'write', + 'capabilities' => 'local/lb_planner:student', + 'ajax' => true, + ], ]; $services = [ @@ -321,6 +357,10 @@ 'local_lbplanner_plan_accept_invite', 'local_lbplanner_plan_decline_invite', 'local_lbplanner_config_get_version', + 'local_lbplanner_slots_get_my_slot', + 'local_lbplanner_slots_get_student_slots', + 'local_lbplanner_slots_get_supervisor_slots', + 'local_lbplanner_slots_book_reservation', ], 'restrictedusers' => 0, 'enabled' => 1, diff --git a/lbplanner/services/slots/book_reservation.php b/lbplanner/services/slots/book_reservation.php new file mode 100644 index 00000000..dab33ab3 --- /dev/null +++ b/lbplanner/services/slots/book_reservation.php @@ -0,0 +1,142 @@ +. + +namespace local_lbplanner_services; + +use DateTimeImmutable; + +use core_user; +use external_api; +use external_function_parameters; +use external_single_structure; +use external_value; + +use local_lbplanner\helpers\slot_helper; +use local_lbplanner\model\reservation; + +/** + * Returns all slots the user can theoretically reserve. + * This does not include times the user has already reserved a slot for. + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class slots_book_reservation extends external_api { + /** + * Parameters for book_reservation. + * @return external_function_parameters + */ + public static function book_reservation_parameters(): external_function_parameters { + global $USER; + return new external_function_parameters([ + 'slotid' => new external_value( + PARAM_INT, + 'ID of the slot for which a reservation is being requested', + VALUE_REQUIRED, + null, + NULL_NOT_ALLOWED + ), + 'date' => new external_value( + PARAM_TEXT, + 'date of the reservation in YYYY-MM-DD (as per ISO-8601)', + VALUE_REQUIRED, + null, + NULL_NOT_ALLOWED + ), + 'userid' => new external_value( + PARAM_INT, + 'the user to reserve this slot for', + VALUE_OPTIONAL, + $USER->id, + NULL_NOT_ALLOWED + ), + ]); + } + + /** + * Returns slots the current user is supposed to see + */ + public static function book_reservation(int $slotid, string $date, int $userid): array { + global $USER, $DB; + + $now = new DateTimeImmutable(); + $dateobj = DateTimeImmutable::createFromFormat("YY-MM-DD", $date); + $td = $dateobj->diff($now); + + if($td->invert){ + throw new \moodle_exception('Can\'t reserve date in the past'); + } + + $maxdays = null; + $student = null; + + if ($userid === $USER->id) { + // student reserving slot for themself + + $maxdays = slot_helper::RESERVATION_RANGE_USER; + $student = $USER; + } else { + // supervisor reserving slot for student + + if (!slot_helper::check_slot_supervisor($USER->id, $slotid)) { + throw new \moodle_exception('Forbidden: you\'re not a supervisor of this slot'); + } + + $maxdays = slot_helper::RESERVATION_RANGE_USER; + $student = core_user::get_user($userid, '*', MUST_EXIST); + } + + if ($td->days > $maxdays) { + throw new \moodle_exception("Date is past allowed date ({$maxdays} days in the future)"); + } + + $slot = slot_helper::get_slot($slotid); + + // check if user has access to slot + if (sizeof(slot_helper::filter_slots_for_user([$slot], $student)) === 0) { + throw new \moodle_exception('Student does not have access to this slot'); + } + + // check if user is already in slot + foreach (slot_helper::get_reservations_for_slot($slotid) as $_reservation) { + if ($_reservation->userid === $userid){ + throw new \moodle_exception('Student is already in slot'); + } + } + + // check if slot is full + if ($slot->get_fullness() > $slot->size){ + throw new \moodle_exception('Slot is already full'); + } + + $reservation = new reservation(0, $slotid, $dateobj, $userid, $USER->id); + + $id = $DB->insert_record(slot_helper::TABLE_RESERVATIONS, $reservation->prepare_for_db()); + $reservation->id = $id; + + return $reservation->prepare_for_api(); + } + + /** + * Returns the structure of the slot array + * @return external_multiple_structure + */ + public static function book_reservation_returns(): external_single_structure { + return reservation::api_structure(); + } +} From ab7f1710c9ccd39207140d1d460832204b51bf2c Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 12 Aug 2024 13:53:20 +0200 Subject: [PATCH 45/92] fix: major typo --- lbplanner/services/plan/set_deadline.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lbplanner/services/plan/set_deadline.php b/lbplanner/services/plan/set_deadline.php index 9ad07a8f..aac4d86d 100644 --- a/lbplanner/services/plan/set_deadline.php +++ b/lbplanner/services/plan/set_deadline.php @@ -34,7 +34,7 @@ class plan_set_deadline extends external_api { * Parameters for set_deadline. * @return external_function_parameters */ - public static function set_deadline_parameters() { + public static function set_deadline_parameters(): external_function_parameters { return new external_function_parameters([ 'moduleid' => new external_value( PARAM_INT, @@ -69,7 +69,7 @@ public static function set_deadline_parameters() { * @return void * @throws \moodle_exception when access denied */ - public static function set_deadline(int $moduleid, int $deadlinestart, int $deadlineend): external_function_parameters { + public static function set_deadline(int $moduleid, int $deadlinestart, int $deadlineend) { global $DB, $USER; self::validate_parameters( From 98b14242677311c7379eae69a1e08a1b2931d25b Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 12 Aug 2024 13:53:50 +0200 Subject: [PATCH 46/92] internal: add .kateproject --- .kateproject | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .kateproject diff --git a/.kateproject b/.kateproject new file mode 100644 index 00000000..b9ffc1c6 --- /dev/null +++ b/.kateproject @@ -0,0 +1,9 @@ +{ + "lspclient": { + "servers": { + "php" : { + "root": "../moodle/" + } + } + } +} \ No newline at end of file From fc99f409475075f387c264957da0c1e2c8360d48 Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 12 Aug 2024 16:05:26 +0200 Subject: [PATCH 47/92] feat: unbooking reservation --- lbplanner/classes/enums/NOTIF_TRIGGER.php | 8 ++ lbplanner/classes/helpers/slot_helper.php | 25 ++++ lbplanner/classes/model/reservation.php | 36 +++++- lbplanner/services/slots/book_reservation.php | 6 +- .../services/slots/unbook_reservation.php | 109 ++++++++++++++++++ 5 files changed, 179 insertions(+), 5 deletions(-) create mode 100644 lbplanner/services/slots/unbook_reservation.php diff --git a/lbplanner/classes/enums/NOTIF_TRIGGER.php b/lbplanner/classes/enums/NOTIF_TRIGGER.php index 3b1be9fd..ee6b4350 100644 --- a/lbplanner/classes/enums/NOTIF_TRIGGER.php +++ b/lbplanner/classes/enums/NOTIF_TRIGGER.php @@ -56,4 +56,12 @@ class NOTIF_TRIGGER extends Enum { * User registered */ const USER_REGISTERED = 5; + /** + * Unbook requested by supervisor + */ + const UNBOOK_REQUESTED = 6; + /** + * Unbook forced by supervisor + */ + const UNBOOK_FORCED = 7; } diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index f487d4b2..fd6b6a48 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -137,6 +137,25 @@ public static function get_slot(int $slotid): slot { return new slot(...$slot); } + /** + * Returns a singular reservation. + * @param int $reservationid ID of the reservation + * + * @return reservation the requested reservation + */ + public static function get_reservation(int $reservationid): reservation { + global $DB; + $reservation = $DB->get_record(self::TABLE_RESERVATIONS, ['id' => $reservationid]); + + if ($reservation === false) { + throw new \moodle_exception('requested reservation does not exist'); + } + + $reservation['date'] = new DateTimeImmutable($reservation['date']); + + return new reservation(...$reservation); + } + /** * Returns reservations for a slot. * @param int $slotid ID of the slot @@ -250,6 +269,12 @@ public static function calculate_slot_datetime(slot $slot, DateTimeInterface $no return new DateTimeImmutable($slotdatetime); } + public static function amend_date_with_unit_time(int $unit, DateTimeInterface $date): DateTimeImmutable { + $daytime = slot_helper::SCHOOL_UNITS[$unit]; + + return DateTimeImmutable::createFromFormat('YY-MM-DD tHH:MM', $date->format('Y-m-d ').$daytime); + } + /** * Returns a list of all slots belonging to a supervisor. * @param int $supervisorid userid of the supervisor in question diff --git a/lbplanner/classes/model/reservation.php b/lbplanner/classes/model/reservation.php index 681fc3e4..1ed41b6e 100644 --- a/lbplanner/classes/model/reservation.php +++ b/lbplanner/classes/model/reservation.php @@ -61,7 +61,11 @@ class reservation { */ private ?slot $slot; /** - * @var ?DateTimeImmutable $datetime the date this reservation is for, with time filled in + * @var ?DateTimeImmutable $datetime the date this reservation starts at, with time filled in + */ + private ?DateTimeImmutable $datetime; + /** + * @var ?DateTimeImmutable $datetime the date this reservation ends at, with time filled in */ private ?DateTimeImmutable $datetime; @@ -112,6 +116,34 @@ public function prepare_for_db(): object { return $obj; } + /** + * Calculates the exact time and date this reservation is supposed to start + * + * @return DateTimeImmutable + */ + public function get_datetime(): DateTimeImmutable { + if (is_null($this->datetime)) { + $slot = $this->get_slot(); + $this->datetime = slot_helper::amend_date_with_unit_time($this->date, $slot->startunit); + } + + return $this->datetime; + } + + /** + * Calculates the exact time and date this reservation is supposed to start + * + * @return DateTimeImmutable + */ + public function get_datetime_end(): DateTimeImmutable { + if (is_null($this->datetime)) { + $slot = $this->get_slot(); + $this->datetime_end = slot_helper::amend_date_with_unit_time($this->date, $slot->startunit + $slot->duration) + } + + return $this->datetime_end; + } + /** * Prepares data for the API endpoint. * @@ -121,7 +153,7 @@ public function prepare_for_api(): array { return [ 'id' => $this->id, 'slotid' => $this->slotid, - 'datetime' => $this->date->format('Y-m-d'), + 'date' => $this->date->format('Y-m-d'), 'userid' => $this->userid, 'reserverid' => $this->reserverid, ]; diff --git a/lbplanner/services/slots/book_reservation.php b/lbplanner/services/slots/book_reservation.php index dab33ab3..518567a8 100644 --- a/lbplanner/services/slots/book_reservation.php +++ b/lbplanner/services/slots/book_reservation.php @@ -69,7 +69,7 @@ public static function book_reservation_parameters(): external_function_paramete } /** - * Returns slots the current user is supposed to see + * Books a reservation */ public static function book_reservation(int $slotid, string $date, int $userid): array { global $USER, $DB; @@ -133,8 +133,8 @@ public static function book_reservation(int $slotid, string $date, int $userid): } /** - * Returns the structure of the slot array - * @return external_multiple_structure + * Returns the structure of the reservation + * @return external_single_structure */ public static function book_reservation_returns(): external_single_structure { return reservation::api_structure(); diff --git a/lbplanner/services/slots/unbook_reservation.php b/lbplanner/services/slots/unbook_reservation.php new file mode 100644 index 00000000..e495da90 --- /dev/null +++ b/lbplanner/services/slots/unbook_reservation.php @@ -0,0 +1,109 @@ +. + +namespace local_lbplanner_services; + +use DateTimeImmutable; + +use external_api; +use external_function_parameters; +use external_value; + +use local_lbplanner\helpers\slot_helper; +use local_lbplanner\helpers\notifications_helper; +use local_lbplanner\model\reservation; +use local_lbplanner\enums\NOTIF_TRIGGER; + +/** + * Returns all slots the user can theoretically reserve. + * This does not include times the user has already reserved a slot for. + * + * @package local_lbplanner + * @subpackage services_plan + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class slots_unbook_reservation extends external_api { + /** + * Parameters for unbook_reservation. + * @return external_function_parameters + */ + public static function unbook_reservation_parameters(): external_function_parameters { + return new external_function_parameters([ + 'reservationid' => new external_value( + PARAM_INT, + 'ID of the reservation for which unbooking is being requested', + VALUE_REQUIRED, + null, + NULL_NOT_ALLOWED + ), + 'nice' => new external_value( + PARAM_BOOL, + 'whether to ask the student nicely to unbook themself via a notification', + VALUE_OPTIONAL, + true, + NULL_NOT_ALLOWED + ), + ]); + } + + /** + * Tries to request unbooking + */ + public static function unbook_reservation(int $reservationid, bool $nice): void { + global $USER, $DB; + + $reservation = slot_helper::get_reservation($reservationid); + $now = new DateTimeImmutable(); + + $endpast = $now->diff($reservation->get_datetime_end())->invert === 1; + $startpast = $endpast or ($now->diff($reservation->get_datetime())->invert === 1); + + if ($USER->id === $reservation->userid){ + if ($startpast) { + throw new \moodle_exception('You can\'t unbook this reservation because it has already started'); + } + } else if(slot_helper::check_slot_supervisor($USER->id, $reservation->slotid)) { + if ($endpast) { + throw new \moodle_exception('You can\'t unbook this reservation because it has already ended'); + } + if ($nice) { + if ($startpast) { + throw new \moodle_exception('Students can\'t unbook reservations that have already started. If you want to unbook this reservation regardless, force it.'); + } + notifications_helper::notify_user($reservation->userid, $reservation->id, NOTIF_TRIGGER::UNBOOK_REQUESTED); + return; + } else { + notifications_helper::notify_user($reservation->userid, $reservation->id, NOTIF_TRIGGER::UNBOOK_FORCED); + } + } else { + throw new \moodle_exception('insufficient permission to unbook this reservation'); + } + + $DB->delete_records( + slot_helper::TABLE_RESERVATIONS, + ['id' => $reservation->id] + ); + } + + /** + * Returns nothing at all + * @return null + */ + public static function unbook_reservation_returns(): null { + return null; + } +} From d70316965d883a4cfabcc99d9343de2d0bc1fbab Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 12 Aug 2024 17:04:14 +0200 Subject: [PATCH 48/92] fixed minor bug, added major TODOs --- lbplanner/services/slots/book_reservation.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lbplanner/services/slots/book_reservation.php b/lbplanner/services/slots/book_reservation.php index 518567a8..99e0c348 100644 --- a/lbplanner/services/slots/book_reservation.php +++ b/lbplanner/services/slots/book_reservation.php @@ -119,8 +119,10 @@ public static function book_reservation(int $slotid, string $date, int $userid): } } + // TODO: check if user is already in a different slot at the same time + // check if slot is full - if ($slot->get_fullness() > $slot->size){ + if ($slot->get_fullness() >= $slot->size){ throw new \moodle_exception('Slot is already full'); } @@ -129,6 +131,8 @@ public static function book_reservation(int $slotid, string $date, int $userid): $id = $DB->insert_record(slot_helper::TABLE_RESERVATIONS, $reservation->prepare_for_db()); $reservation->id = $id; + // TODO: if userid!=USER->id → send notif to the user that the supervisor booked a reservation for them + return $reservation->prepare_for_api(); } From 26b577a857a047cfeb1804e88469d12be3b6eed4 Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 12 Aug 2024 17:47:37 +0200 Subject: [PATCH 49/92] fix typo --- lbplanner/db/services.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lbplanner/db/services.php b/lbplanner/db/services.php index 1c5c5859..87680d6a 100644 --- a/lbplanner/db/services.php +++ b/lbplanner/db/services.php @@ -286,10 +286,10 @@ 'capabilities' => '', 'ajax' => true, ], - 'local_lbplanner_slots_get_my_slot' => [ - 'classname' => 'local_lbplanner_services\slots_get_my_slot', - 'methodname' => 'get_my_slot', - 'classpath' => 'local/lbplanner/services/slots/get_my_slot.php', + 'local_lbplanner_slots_get_my_slots' => [ + 'classname' => 'local_lbplanner_services\slots_get_my_slots', + 'methodname' => 'get_my_slots', + 'classpath' => 'local/lbplanner/services/slots/get_my_slots.php', 'description' => 'Get all slots the user can theoretically reserve.', 'type' => 'read', 'capabilities' => 'local/lb_planner:student', From 88cbf71e446fe7f60edd3bd8e36b5d7b7be926b7 Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 12 Aug 2024 17:59:02 +0200 Subject: [PATCH 50/92] fixed docs --- document_services.py | 3 ++- lbplanner/services/slots/book_reservation.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/document_services.py b/document_services.py index 55c03f20..a694ac94 100644 --- a/document_services.py +++ b/document_services.py @@ -236,7 +236,8 @@ def parse_imports(input_str: str, symbol: str) -> str | None: namespaces = { # it's technically possible to import from outside /classes/ "local_lbplanner\\helpers": "classes/helpers", "local_lbplanner\\enums": "classes/enums", - "local_lbplanner\\polyfill": "classes/polyfill" + "local_lbplanner\\polyfill": "classes/polyfill", + "local_lbplanner\\model": "classes/model", } fp_l: list[str] = [] for use in uses: diff --git a/lbplanner/services/slots/book_reservation.php b/lbplanner/services/slots/book_reservation.php index 99e0c348..d976837b 100644 --- a/lbplanner/services/slots/book_reservation.php +++ b/lbplanner/services/slots/book_reservation.php @@ -61,7 +61,7 @@ public static function book_reservation_parameters(): external_function_paramete 'userid' => new external_value( PARAM_INT, 'the user to reserve this slot for', - VALUE_OPTIONAL, + VALUE_DEFAULT, $USER->id, NULL_NOT_ALLOWED ), From ad47ad80eef647ae2ec30f68ae630dde4b27ff0f Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 12 Aug 2024 18:56:47 +0200 Subject: [PATCH 51/92] fixed gh actions --- .github/workflows/download.yaml | 56 +++++--------------------------- .github/workflows/gen_docs.yaml | 25 +++++++------- .github/workflows/gha.dist.yml | 2 +- .github/workflows/test_docs.yaml | 2 +- 4 files changed, 25 insertions(+), 60 deletions(-) diff --git a/.github/workflows/download.yaml b/.github/workflows/download.yaml index aa71a827..2a6979cf 100644 --- a/.github/workflows/download.yaml +++ b/.github/workflows/download.yaml @@ -2,59 +2,20 @@ name: dl_constants.php maintainer on: release: types: [published] - branches: ["app", "moodle"] + branches: ["main"] jobs: - update-frontend-files: - name: Update app version & download url - if: github.event.release.target_commitish == 'app' && !github.event.release.prerelease - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v3 - with: - ref: web - - - name: Update linux url - run: sed -i '/linux/c\const dl_linux = "${{ github.server_url }}/${{ github.repository }}/releases/download/${{ github.event.release.tag_name }}/LB.Planner-x86_64.AppImage";' /home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/snippets/dl_constants.php - - - name: Update linux comment - run: sed -i '/Linux download url/c\ * Linux download url [@${{ github.event.release.tag_name }}](${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.event.release.tag_name }}).' /home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/snippets/dl_constants.php - - - name: Update windows url - run: sed -i '/windows/c\const dl_windows = "${{ github.server_url }}/${{ github.repository }}/releases/download/${{ github.event.release.tag_name }}/LB.Planner.Setup.exe";' /home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/snippets/dl_constants.php - - - name: Update windows comment - run: sed -i '/Windows download url/c\ * Windows download url [@${{ github.event.release.tag_name }}](${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.event.release.tag_name }}).' /home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/snippets/dl_constants.php - - - name: Update mac url - run: sed -i '/mac/c\const dl_mac = "${{ github.server_url }}/${{ github.repository }}/releases/download/${{ github.event.release.tag_name }}/LB.Planner.Setup.dmg";' /home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/snippets/dl_constants.php - - - name: Update mac comment - run: sed -i '/MacOS download url/c\ * MacOS download url [@${{ github.event.release.tag_name }}](${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.event.release.tag_name }}).' /home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/snippets/dl_constants.php - - - name: Commit & Push - uses: Andro999b/push@v1.3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - branch: web - message: "Github Actions - Updated dl_constants.php to ${{ github.event.release.tag_name }}" - - name: SFTP Upload to Webserver - uses: Dylan700/sftp-upload-action@v1.1.4 - with: - server: ${{ secrets.SFTP_HOST }} - username: ${{ secrets.SFTP_USER }} - password: ${{ secrets.SFTP_PASSWORD }} - uploads: | - snippets/dl_constants.php => /htdocs/snippets/dl_constants.php update-backend-files: name: Update plugin version & download url - if: github.event.release.target_commitish == 'moodle' && !github.event.release.prerelease + if: '!github.event.release.prerelease' runs-on: ubuntu-latest steps: - name: Checkout repo uses: actions/checkout@v3 with: - ref: web + repository: 'necodeIT/lb_planner_web' + ref: main + persist-credentials: false + fetch-depth: 0 - name: Update plugin url run: sed -i '/dl_plugin/c\const dl_plugin = "${{ github.server_url }}/${{ github.repository }}/releases/download/${{ github.event.release.tag_name }}/lb_planner.zip";' /home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/snippets/dl_constants.php @@ -65,8 +26,9 @@ jobs: - name: Commit & Push uses: Andro999b/push@v1.3 with: - github_token: ${{ secrets.GITHUB_TOKEN }} - branch: web + github_token: ${{ secrets.REPO_WEB_TOKEN }} + repository: 'necodeIT/lb_planner_web' + branch: main message: "Github Actions - Updated dl_constants.php to ${{ github.event.release.tag_name }}" - name: SFTP Upload to Webserver uses: Dylan700/sftp-upload-action@v1.1.4 diff --git a/.github/workflows/gen_docs.yaml b/.github/workflows/gen_docs.yaml index 702ed56f..a776125c 100644 --- a/.github/workflows/gen_docs.yaml +++ b/.github/workflows/gen_docs.yaml @@ -3,7 +3,7 @@ name: Generate API Docs on: push: branches: - - LP-55-Backend-Refactor # This is temporary and will be replaced by `moodle` once the refactor is complete + - LP-55-Backend-Refactor # This is temporary and will be replaced by `main` once the refactor is complete workflow_dispatch: # For manual triggering jobs: @@ -14,15 +14,18 @@ jobs: - name: Checkout Repo uses: actions/checkout@v3 with: - ref: LP-55-Backend-Refactor # This is temporary and will be replaced by `moodle` once the refactor is complete + ref: LP-55-Backend-Refactor # This is temporary and will be replaced by `main` once the refactor is complete path: moodle - - name: Checkout docs branch + - name: Checkout docs repo uses: actions/checkout@v3 with: - ref: docs + repository: 'necodeIT/lb_planner_docs' + ref: main clean: false path: docs + persist-credentials: false + fetch-depth: 0 - name: Setup Python uses: actions/setup-python@v4.7.1 @@ -33,11 +36,11 @@ jobs: working-directory: moodle run: python document_services.py ../docs/moodle - - name: Push new documentation to docs branch + - name: Push new documentation to docs repo working-directory: docs - run: | - git config user.name "GitHub Actions Bot" - git config user.email "github-actions-bot@users.noreply.github.com" - git add -A - git commit -m "GitHub Actions - Update Web Service Documentation to ${{ github.sha }}" - git push + uses: Andro999b/push@v1.3 + with: + github_token: ${{ secrets.REPO_DOCS_TOKEN }} + repository: 'necodeIT/lb_planner_docs' + branch: main + message: "GitHub Actions - Update Web Service Documentation to ${{ github.sha }}" diff --git a/.github/workflows/gha.dist.yml b/.github/workflows/gha.dist.yml index 821e97b1..cfe38c95 100644 --- a/.github/workflows/gha.dist.yml +++ b/.github/workflows/gha.dist.yml @@ -6,7 +6,7 @@ on: - opened - synchronize branches: - - LP-55-Backend-Refactor # Temporary. Will be changed to `moodle` when refactor is complete + - LP-55-Backend-Refactor # Temporary. Will be changed to `main` when refactor is complete jobs: Analysis: diff --git a/.github/workflows/test_docs.yaml b/.github/workflows/test_docs.yaml index 6c0dafe1..6637377f 100644 --- a/.github/workflows/test_docs.yaml +++ b/.github/workflows/test_docs.yaml @@ -6,7 +6,7 @@ on: - opened - synchronize branches: - - LP-55-Backend-Refactor # Temporary. Will be changed to `moodle` when refactor is complete + - LP-55-Backend-Refactor # Temporary. Will be changed to `main` when refactor is complete jobs: generate-api-docs: From a7f084b94e0276036266b0b601a5e24704e6d016 Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 20:22:02 +0200 Subject: [PATCH 52/92] implemented create_slot --- lbplanner/classes/helpers/slot_helper.php | 5 + lbplanner/classes/model/slot.php | 36 +++++- lbplanner/services/slots/create_slot.php | 130 ++++++++++++++++++++++ 3 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 lbplanner/services/slots/create_slot.php diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index fd6b6a48..572af742 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -44,6 +44,11 @@ class slot_helper { * how far into the future a supervisor can reserve a slot for a user */ const RESERVATION_RANGE_SUPERVISOR = 7; + /** + * how long the room names can be in characters + * unicode characters might count as multiple characters + */ + const ROOM_MAXLENGTH = 7; // TODO: increase to 255 or sumn /** * school units according to untis, in H:i format */ diff --git a/lbplanner/classes/model/slot.php b/lbplanner/classes/model/slot.php index 8e2fa1e0..76f0ce1b 100644 --- a/lbplanner/classes/model/slot.php +++ b/lbplanner/classes/model/slot.php @@ -83,9 +83,10 @@ public function __construct(int $id, int $startunit, int $duration, int $weekday assert($startunit > 0); $this->startunit = $startunit; assert($duration > 0); + assert($duration + $startunit < sizeof(slot_helper::SCHOOL_UNITS)); $this->duration = $duration; $this->weekday = WEEKDAY::from($weekday); - assert(strlen($room) > 0 && strlen($room) <= 7); + assert(strlen($room) > 0 && strlen($room) <= slot_helper::ROOM_MAXLENGTH); $this->room = $room; assert($size >= 0); // Make it technically possible to not allow any students in a room to temporarily disable the slot. $this->size = $size; @@ -93,6 +94,18 @@ public function __construct(int $id, int $startunit, int $duration, int $weekday $this->forcuruser = null; } + /** + * Mark the object as freshly created and sets the new ID + * @param int $id the new ID after insertint into the DB + */ + public function set_fresh(int $id) { + assert($this->id === 0); + assert($id !== 0); + $this->id = $id; + $this->fullness = 0; + $this->forcuruser = false; + } + /** * Returns how many reservations there are for this slot. * @@ -119,6 +132,27 @@ public function get_forcuruser(): bool { return $this->forcuruser; } + /** + * Prepares data for the DB endpoint. + * doesn't set ID if it's 0 + * + * @return object a representation of this slot and its data + */ + public function prepare_for_db(): object { + $obj = new \stdClass(); + + $obj->startunit = $this->startunit; + $obj->duration = $this->duration; + $obj->weekday = $this->weekday; + $obj->room = $this->room; + $obj->size = $this->size; + + if ($this->id !== 0){ + $obj->id = $this->id; + } + return $obj; + } + /** * Prepares data for the API endpoint. * diff --git a/lbplanner/services/slots/create_slot.php b/lbplanner/services/slots/create_slot.php new file mode 100644 index 00000000..841b5b06 --- /dev/null +++ b/lbplanner/services/slots/create_slot.php @@ -0,0 +1,130 @@ +. + +namespace local_lbplanner_services; + +use external_api; +use external_function_parameters; +use external_single_structure; +use external_value; +use local_lbplanner\enums\WEEKDAY; +use local_lbplanner\helpers\slot_helper; +use local_lbplanner\model\slot; +use moodle_exception; + +/** + * Returns all slots the user can theoretically reserve. + * This does not include times the user has already reserved a slot for. + * + * @package local_lbplanner + * @subpackage services_slots + * @copyright 2024 necodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class slots_create_slot extends external_api { + /** + * Parameters for create_slot. + * @return external_function_parameters + */ + public static function create_slot_parameters(): external_function_parameters { + // TODO: set hardcoded doc values with constants instead of hardcoded values + return new external_function_parameters([ + 'startunit' => new external_value( + PARAM_INT, + 'The school unit this slot starts in, starting at 1 for 8:00 and ending at 16 for 21:00', + VALUE_REQUIRED, + null, + NULL_NOT_ALLOWED + ), + 'duration' => new external_value( + PARAM_INT, + 'The amount of units this slot is long. startunit + duration may not exceed 16', + VALUE_REQUIRED, + null, + NULL_NOT_ALLOWED + ), + 'weekday' => new external_value( + PARAM_INT, + 'The weekday this slot happens on. '.WEEKDAY::format(), + VALUE_REQUIRED, + null, + NULL_NOT_ALLOWED + ), + 'room' => new external_value( + PARAM_TEXT, + 'The room this slot happens in. max. 7 characters', + VALUE_REQUIRED, + null, + NULL_NOT_ALLOWED + ), + 'size' => new external_value( + PARAM_INT, + 'How many pupils this slot can fit', + VALUE_REQUIRED, + null, + NULL_NOT_ALLOWED + ), + ]); + } + + /** + * Create a slot + */ + public static function create_slot(int $startunit, int $duration, int $weekday, string $room, int $size): array { + global $USER, $DB; + + // validating startunit + $max_unit = sizeof(slot_helper::SCHOOL_UNITS) - 1; + if ($startunit < 1) { + throw new moodle_exception('can\'t have a start unit smaller than 1'); + } else if ($startunit > $max_unit) { + throw new moodle_exception("can't have a start unit larger than {$max_unit}"); + } + // validating duration + if ($duration < 1) { + throw new moodle_exception('duration must be at least 1'); + } else if ($startunit + $duration > $max_unit) { + throw new moodle_exception("slot goes past the max unit {$max_unit}"); + } + // validating weekday + WEEKDAY::from($weekday); + // validating room + if (strlen($room) <= 1) { + throw new moodle_exception('room name has to be at least 2 characters long'); + } else if (strlen($room) > slot_helper::ROOM_MAXLENGTH) { + throw new moodle_exception('room name has a maximum of '.slot_helper::ROOM_MAXLENGTH.' characters'); + } + // validating size + if ($size < 0) { + throw new moodle_exception('can\'t have a negative size for a slot'); + } + + + $slot = new slot(0, $startunit, $duration, $weekday, $room, $size); + $id = $DB->insert_record(slot_helper::TABLE_SLOTS, $slot->prepare_for_db()); + $slot->set_fresh($id); + + return $slot->prepare_for_api(); + } + + /** + * Returns the structure of the slot + * @return external_single_structure + */ + public static function create_slot_returns(): external_single_structure { + return slot::api_structure(); + } +} From e6d966e3a547e398121008e899eeb88c7ba87a03 Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 20:23:31 +0200 Subject: [PATCH 53/92] fix: a bunch of copy-paste mistakes --- lbplanner/classes/model/reservation.php | 6 +++--- lbplanner/services/slots/book_reservation.php | 5 ++--- lbplanner/services/slots/get_my_slots.php | 2 +- lbplanner/services/slots/get_student_slots.php | 2 +- lbplanner/services/slots/get_supervisor_slots.php | 2 +- lbplanner/services/slots/unbook_reservation.php | 6 ++---- 6 files changed, 10 insertions(+), 13 deletions(-) diff --git a/lbplanner/classes/model/reservation.php b/lbplanner/classes/model/reservation.php index 1ed41b6e..f23dc56f 100644 --- a/lbplanner/classes/model/reservation.php +++ b/lbplanner/classes/model/reservation.php @@ -67,7 +67,7 @@ class reservation { /** * @var ?DateTimeImmutable $datetime the date this reservation ends at, with time filled in */ - private ?DateTimeImmutable $datetime; + private ?DateTimeImmutable $datetime_end; /** * Constructs a reservation @@ -124,7 +124,7 @@ public function prepare_for_db(): object { public function get_datetime(): DateTimeImmutable { if (is_null($this->datetime)) { $slot = $this->get_slot(); - $this->datetime = slot_helper::amend_date_with_unit_time($this->date, $slot->startunit); + $this->datetime = slot_helper::amend_date_with_unit_time($slot->startunit, $this->date); } return $this->datetime; @@ -138,7 +138,7 @@ public function get_datetime(): DateTimeImmutable { public function get_datetime_end(): DateTimeImmutable { if (is_null($this->datetime)) { $slot = $this->get_slot(); - $this->datetime_end = slot_helper::amend_date_with_unit_time($this->date, $slot->startunit + $slot->duration) + $this->datetime_end = slot_helper::amend_date_with_unit_time($slot->startunit + $slot->duration, $this->date); } return $this->datetime_end; diff --git a/lbplanner/services/slots/book_reservation.php b/lbplanner/services/slots/book_reservation.php index d976837b..ca0a6490 100644 --- a/lbplanner/services/slots/book_reservation.php +++ b/lbplanner/services/slots/book_reservation.php @@ -28,11 +28,10 @@ use local_lbplanner\model\reservation; /** - * Returns all slots the user can theoretically reserve. - * This does not include times the user has already reserved a slot for. + * Books a reservation for the user * * @package local_lbplanner - * @subpackage services_plan + * @subpackage services_slots * @copyright 2024 necodeIT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lbplanner/services/slots/get_my_slots.php b/lbplanner/services/slots/get_my_slots.php index 5198fc84..00ef28b4 100644 --- a/lbplanner/services/slots/get_my_slots.php +++ b/lbplanner/services/slots/get_my_slots.php @@ -27,7 +27,7 @@ * This does not include times the user has already reserved a slot for. * * @package local_lbplanner - * @subpackage services_plan + * @subpackage services_slots * @copyright 2024 necodeIT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lbplanner/services/slots/get_student_slots.php b/lbplanner/services/slots/get_student_slots.php index 2a9df0e1..647260a8 100644 --- a/lbplanner/services/slots/get_student_slots.php +++ b/lbplanner/services/slots/get_student_slots.php @@ -28,7 +28,7 @@ * This does not include times the user has already reserved a slot for. * * @package local_lbplanner - * @subpackage services_plan + * @subpackage services_slots * @copyright 2024 necodeIT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lbplanner/services/slots/get_supervisor_slots.php b/lbplanner/services/slots/get_supervisor_slots.php index 2a50347a..5d4d7b2f 100644 --- a/lbplanner/services/slots/get_supervisor_slots.php +++ b/lbplanner/services/slots/get_supervisor_slots.php @@ -26,7 +26,7 @@ * Returns all slots a supervisor can see. * * @package local_lbplanner - * @subpackage services_plan + * @subpackage services_slots * @copyright 2024 necodeIT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lbplanner/services/slots/unbook_reservation.php b/lbplanner/services/slots/unbook_reservation.php index e495da90..2178847c 100644 --- a/lbplanner/services/slots/unbook_reservation.php +++ b/lbplanner/services/slots/unbook_reservation.php @@ -24,15 +24,13 @@ use local_lbplanner\helpers\slot_helper; use local_lbplanner\helpers\notifications_helper; -use local_lbplanner\model\reservation; use local_lbplanner\enums\NOTIF_TRIGGER; /** - * Returns all slots the user can theoretically reserve. - * This does not include times the user has already reserved a slot for. + * Unbooks reservation * * @package local_lbplanner - * @subpackage services_plan + * @subpackage services_slots * @copyright 2024 necodeIT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ From 72b5c75134f71c47d76c49bf2363cd48b148177b Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 20:23:50 +0200 Subject: [PATCH 54/92] refactor: minor improvements --- lbplanner/classes/model/reservation.php | 60 ++++++++++++++----- lbplanner/services/slots/book_reservation.php | 2 +- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/lbplanner/classes/model/reservation.php b/lbplanner/classes/model/reservation.php index f23dc56f..82865c60 100644 --- a/lbplanner/classes/model/reservation.php +++ b/lbplanner/classes/model/reservation.php @@ -87,6 +87,29 @@ public function __construct(int $id, int $slotid, DateTimeImmutable $date, int $ $this->slot = null; } + /** + * Mark the object as freshly created and sets the new ID + * @param int $id the new ID after insertint into the DB + * @param slot $slot the cached slot object + */ + public function set_fresh(int $id, ?slot $slot) { + assert($this->id === 0); + assert($id !== 0); + $this->id = $id; + if (!is_null($slot)) { + $this->set_slot($slot); + } + } + + /** + * sets the cached slot object (mainly for deduplicating DB requests) + * @param slot $slot the cached slot object + */ + public function set_slot(slot $slot) { + assert($this->slotid === $slot->id); + $this->slot = $slot; + } + /** * Returns the associated slot. * @@ -100,22 +123,6 @@ public function get_slot(): slot { return $this->slot; } - /** - * Prepares data for the DB endpoint. - * - * @return object a representation of this reservation and its data - */ - public function prepare_for_db(): object { - $obj = new \stdClass(); - - $obj->slotid = $this->slotid; - $obj->date = $this->date; - $obj->userid = $this->userid; - $obj->reserverid = $this->reserverid; - - return $obj; - } - /** * Calculates the exact time and date this reservation is supposed to start * @@ -144,6 +151,27 @@ public function get_datetime_end(): DateTimeImmutable { return $this->datetime_end; } + /** + * Prepares data for the DB endpoint. + * doesn't set ID if it's 0 + * + * @return object a representation of this reservation and its data + */ + public function prepare_for_db(): object { + $obj = new \stdClass(); + + $obj->slotid = $this->slotid; + $obj->date = $this->date; + $obj->userid = $this->userid; + $obj->reserverid = $this->reserverid; + + if ($this->id !== 0) { + $obj->id = $this->id; + } + + return $obj; + } + /** * Prepares data for the API endpoint. * diff --git a/lbplanner/services/slots/book_reservation.php b/lbplanner/services/slots/book_reservation.php index ca0a6490..af538faa 100644 --- a/lbplanner/services/slots/book_reservation.php +++ b/lbplanner/services/slots/book_reservation.php @@ -128,7 +128,7 @@ public static function book_reservation(int $slotid, string $date, int $userid): $reservation = new reservation(0, $slotid, $dateobj, $userid, $USER->id); $id = $DB->insert_record(slot_helper::TABLE_RESERVATIONS, $reservation->prepare_for_db()); - $reservation->id = $id; + $reservation->set_fresh($id, $slot); // TODO: if userid!=USER->id → send notif to the user that the supervisor booked a reservation for them From 3e596d26fb0adb22736e8e52de729b84af3d4e63 Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 20:39:03 +0200 Subject: [PATCH 55/92] fix: temporary workaround for https://github.com/moodlehq/moodle-plugin-ci/issues/309 --- .github/workflows/gha.dist.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/gha.dist.yml b/.github/workflows/gha.dist.yml index 821e97b1..3893375f 100644 --- a/.github/workflows/gha.dist.yml +++ b/.github/workflows/gha.dist.yml @@ -64,6 +64,14 @@ jobs: sudo locale-gen en_AU.UTF-8 echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV + - name: Install NVM and Node # TODO: remove this step after https://github.com/moodlehq/moodle-plugin-ci/issues/309 is fixed + run: | + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash + export NVM_DIR="$HOME/.nvm" + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + nvm install 20 + nvm use 20 + - name: Install moodle-plugin-ci run: | moodle-plugin-ci install --plugin ./plugin/lbplanner --db-host=127.0.0.1 From fdb16be79b986f9c2998c3168000ce13f03b2b6e Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 20:47:53 +0200 Subject: [PATCH 56/92] fix: invalid type --- lbplanner/services/slots/unbook_reservation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lbplanner/services/slots/unbook_reservation.php b/lbplanner/services/slots/unbook_reservation.php index 2178847c..9c38aafe 100644 --- a/lbplanner/services/slots/unbook_reservation.php +++ b/lbplanner/services/slots/unbook_reservation.php @@ -101,7 +101,7 @@ public static function unbook_reservation(int $reservationid, bool $nice): void * Returns nothing at all * @return null */ - public static function unbook_reservation_returns(): null { + public static function unbook_reservation_returns() { return null; } } From d583ab6e7edd4e46ed95e4c40da0de07ac88180d Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 20:58:43 +0200 Subject: [PATCH 57/92] fix: code checker for create_slot --- lbplanner/services/slots/create_slot.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lbplanner/services/slots/create_slot.php b/lbplanner/services/slots/create_slot.php index 841b5b06..92f15770 100644 --- a/lbplanner/services/slots/create_slot.php +++ b/lbplanner/services/slots/create_slot.php @@ -40,7 +40,7 @@ class slots_create_slot extends external_api { * @return external_function_parameters */ public static function create_slot_parameters(): external_function_parameters { - // TODO: set hardcoded doc values with constants instead of hardcoded values + // TODO: set hardcoded doc values with constants instead of hardcoded values. return new external_function_parameters([ 'startunit' => new external_value( PARAM_INT, @@ -86,33 +86,33 @@ public static function create_slot_parameters(): external_function_parameters { public static function create_slot(int $startunit, int $duration, int $weekday, string $room, int $size): array { global $USER, $DB; - // validating startunit - $max_unit = sizeof(slot_helper::SCHOOL_UNITS) - 1; + // Validating startunit. + $maxUnit = count(slot_helper::SCHOOL_UNITS) - 1; if ($startunit < 1) { throw new moodle_exception('can\'t have a start unit smaller than 1'); - } else if ($startunit > $max_unit) { - throw new moodle_exception("can't have a start unit larger than {$max_unit}"); + } else if ($startunit > $maxUnit) { + throw new moodle_exception("can't have a start unit larger than {$maxUnit}"); } - // validating duration + // Validating duration. if ($duration < 1) { throw new moodle_exception('duration must be at least 1'); - } else if ($startunit + $duration > $max_unit) { - throw new moodle_exception("slot goes past the max unit {$max_unit}"); + } else if ($startunit + $duration > $maxUnit) { + throw new moodle_exception("slot goes past the max unit {$maxUnit}"); } - // validating weekday + // Validating weekday. WEEKDAY::from($weekday); - // validating room + // Validating room. if (strlen($room) <= 1) { throw new moodle_exception('room name has to be at least 2 characters long'); } else if (strlen($room) > slot_helper::ROOM_MAXLENGTH) { throw new moodle_exception('room name has a maximum of '.slot_helper::ROOM_MAXLENGTH.' characters'); } - // validating size + // Validating size. if ($size < 0) { throw new moodle_exception('can\'t have a negative size for a slot'); } - + // Actually inserting the slot. $slot = new slot(0, $startunit, $duration, $weekday, $room, $size); $id = $DB->insert_record(slot_helper::TABLE_SLOTS, $slot->prepare_for_db()); $slot->set_fresh($id); From 1d9915a2e876d6ffb142c2361f3d6a63bff6042a Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 21:04:06 +0200 Subject: [PATCH 58/92] fix: code checker for book_reservation and unbook_reservation --- lbplanner/services/slots/book_reservation.php | 24 +++++++++---------- .../services/slots/unbook_reservation.php | 11 +++++---- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/lbplanner/services/slots/book_reservation.php b/lbplanner/services/slots/book_reservation.php index af538faa..b9428a5d 100644 --- a/lbplanner/services/slots/book_reservation.php +++ b/lbplanner/services/slots/book_reservation.php @@ -41,7 +41,7 @@ class slots_book_reservation extends external_api { * @return external_function_parameters */ public static function book_reservation_parameters(): external_function_parameters { - global $USER; + global $USER; return new external_function_parameters([ 'slotid' => new external_value( PARAM_INT, @@ -77,7 +77,7 @@ public static function book_reservation(int $slotid, string $date, int $userid): $dateobj = DateTimeImmutable::createFromFormat("YY-MM-DD", $date); $td = $dateobj->diff($now); - if($td->invert){ + if ($td->invert) { throw new \moodle_exception('Can\'t reserve date in the past'); } @@ -85,12 +85,12 @@ public static function book_reservation(int $slotid, string $date, int $userid): $student = null; if ($userid === $USER->id) { - // student reserving slot for themself + // Student reserving slot for themself. $maxdays = slot_helper::RESERVATION_RANGE_USER; $student = $USER; } else { - // supervisor reserving slot for student + // Supervisor reserving slot for student. if (!slot_helper::check_slot_supervisor($USER->id, $slotid)) { throw new \moodle_exception('Forbidden: you\'re not a supervisor of this slot'); @@ -106,22 +106,22 @@ public static function book_reservation(int $slotid, string $date, int $userid): $slot = slot_helper::get_slot($slotid); - // check if user has access to slot - if (sizeof(slot_helper::filter_slots_for_user([$slot], $student)) === 0) { + // Check if user has access to slot. + if (count(slot_helper::filter_slots_for_user([$slot], $student)) === 0) { throw new \moodle_exception('Student does not have access to this slot'); } - // check if user is already in slot - foreach (slot_helper::get_reservations_for_slot($slotid) as $_reservation) { - if ($_reservation->userid === $userid){ + // Check if user is already in slot. + foreach (slot_helper::get_reservations_for_slot($slotid) as $tmpReservation) { + if ($tmpReservation->userid === $userid) { throw new \moodle_exception('Student is already in slot'); } } - // TODO: check if user is already in a different slot at the same time + // TODO: check if user is already in a different slot at the same time. // check if slot is full - if ($slot->get_fullness() >= $slot->size){ + if ($slot->get_fullness() >= $slot->size) { throw new \moodle_exception('Slot is already full'); } @@ -130,7 +130,7 @@ public static function book_reservation(int $slotid, string $date, int $userid): $id = $DB->insert_record(slot_helper::TABLE_RESERVATIONS, $reservation->prepare_for_db()); $reservation->set_fresh($id, $slot); - // TODO: if userid!=USER->id → send notif to the user that the supervisor booked a reservation for them + // TODO: if userid!=USER->id → send notif to the user that the supervisor booked a reservation for them. return $reservation->prepare_for_api(); } diff --git a/lbplanner/services/slots/unbook_reservation.php b/lbplanner/services/slots/unbook_reservation.php index 9c38aafe..87f30197 100644 --- a/lbplanner/services/slots/unbook_reservation.php +++ b/lbplanner/services/slots/unbook_reservation.php @@ -68,19 +68,22 @@ public static function unbook_reservation(int $reservationid, bool $nice): void $now = new DateTimeImmutable(); $endpast = $now->diff($reservation->get_datetime_end())->invert === 1; - $startpast = $endpast or ($now->diff($reservation->get_datetime())->invert === 1); + $startpast = $endpast || ($now->diff($reservation->get_datetime())->invert === 1); - if ($USER->id === $reservation->userid){ + if ($USER->id === $reservation->userid) { if ($startpast) { throw new \moodle_exception('You can\'t unbook this reservation because it has already started'); } - } else if(slot_helper::check_slot_supervisor($USER->id, $reservation->slotid)) { + } else if (slot_helper::check_slot_supervisor($USER->id, $reservation->slotid)) { if ($endpast) { throw new \moodle_exception('You can\'t unbook this reservation because it has already ended'); } if ($nice) { if ($startpast) { - throw new \moodle_exception('Students can\'t unbook reservations that have already started. If you want to unbook this reservation regardless, force it.'); + throw new \moodle_exception( + 'Students can\'t unbook reservations that have already started.' + .' If you want to unbook this reservation regardless, force it.' + ); } notifications_helper::notify_user($reservation->userid, $reservation->id, NOTIF_TRIGGER::UNBOOK_REQUESTED); return; From 619882205a3ba40b408907f8475dc743cb6016e3 Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 21:16:26 +0200 Subject: [PATCH 59/92] fix: added single blank line after boilerplate comment --- lbplanner/classes/enums/MODULE_GRADE.php | 1 + lbplanner/classes/enums/MODULE_STATUS.php | 1 + lbplanner/classes/enums/MODULE_TYPE.php | 1 + lbplanner/classes/enums/NOTIF_STATUS.php | 1 + lbplanner/classes/enums/NOTIF_TRIGGER.php | 1 + lbplanner/classes/enums/PLAN_ACCESS_TYPE.php | 1 + lbplanner/classes/enums/PLAN_EK.php | 1 + lbplanner/classes/enums/PLAN_INVITE_STATE.php | 1 + lbplanner/classes/enums/WEEKDAY.php | 1 + lbplanner/classes/helpers/modules_helper.php | 1 + lbplanner/classes/helpers/notifications_helper.php | 1 + lbplanner/classes/helpers/plan_helper.php | 1 + lbplanner/classes/helpers/slot_helper.php | 1 + lbplanner/classes/model/reservation.php | 1 + lbplanner/classes/model/slot.php | 1 + lbplanner/classes/model/slot_filter.php | 1 + lbplanner/classes/polyfill/Enum.php | 1 + lbplanner/classes/polyfill/EnumCase.php | 1 + lbplanner/db/access.php | 1 + lbplanner/db/install.php | 1 + lbplanner/db/services.php | 1 + lbplanner/db/upgrade.php | 1 + lbplanner/settings.php | 1 + lbplanner/version.php | 1 + 24 files changed, 24 insertions(+) diff --git a/lbplanner/classes/enums/MODULE_GRADE.php b/lbplanner/classes/enums/MODULE_GRADE.php index 4cbe7a47..20714e9a 100644 --- a/lbplanner/classes/enums/MODULE_GRADE.php +++ b/lbplanner/classes/enums/MODULE_GRADE.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * enum for module grade * diff --git a/lbplanner/classes/enums/MODULE_STATUS.php b/lbplanner/classes/enums/MODULE_STATUS.php index 7f0d87b1..6d78ea59 100644 --- a/lbplanner/classes/enums/MODULE_STATUS.php +++ b/lbplanner/classes/enums/MODULE_STATUS.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * enum for module status * diff --git a/lbplanner/classes/enums/MODULE_TYPE.php b/lbplanner/classes/enums/MODULE_TYPE.php index 47de6a0f..6eb68d2f 100644 --- a/lbplanner/classes/enums/MODULE_TYPE.php +++ b/lbplanner/classes/enums/MODULE_TYPE.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * enum for module type * diff --git a/lbplanner/classes/enums/NOTIF_STATUS.php b/lbplanner/classes/enums/NOTIF_STATUS.php index aef9d02f..25818738 100644 --- a/lbplanner/classes/enums/NOTIF_STATUS.php +++ b/lbplanner/classes/enums/NOTIF_STATUS.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * enum for notif status * diff --git a/lbplanner/classes/enums/NOTIF_TRIGGER.php b/lbplanner/classes/enums/NOTIF_TRIGGER.php index ee6b4350..cfdf2c17 100644 --- a/lbplanner/classes/enums/NOTIF_TRIGGER.php +++ b/lbplanner/classes/enums/NOTIF_TRIGGER.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * enum for notif trigger * diff --git a/lbplanner/classes/enums/PLAN_ACCESS_TYPE.php b/lbplanner/classes/enums/PLAN_ACCESS_TYPE.php index 3b8b07f1..71ad83cb 100644 --- a/lbplanner/classes/enums/PLAN_ACCESS_TYPE.php +++ b/lbplanner/classes/enums/PLAN_ACCESS_TYPE.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * enum for plan access type * diff --git a/lbplanner/classes/enums/PLAN_EK.php b/lbplanner/classes/enums/PLAN_EK.php index 302ecdb1..a14b7de2 100644 --- a/lbplanner/classes/enums/PLAN_EK.php +++ b/lbplanner/classes/enums/PLAN_EK.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * enum for plan EK * diff --git a/lbplanner/classes/enums/PLAN_INVITE_STATE.php b/lbplanner/classes/enums/PLAN_INVITE_STATE.php index 58a4f569..f039479d 100644 --- a/lbplanner/classes/enums/PLAN_INVITE_STATE.php +++ b/lbplanner/classes/enums/PLAN_INVITE_STATE.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * enum for plan invite state * diff --git a/lbplanner/classes/enums/WEEKDAY.php b/lbplanner/classes/enums/WEEKDAY.php index 7d5a5b3c..407c409d 100644 --- a/lbplanner/classes/enums/WEEKDAY.php +++ b/lbplanner/classes/enums/WEEKDAY.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * enum for weekdays * (cringe, ik, but we need these defined concretely) diff --git a/lbplanner/classes/helpers/modules_helper.php b/lbplanner/classes/helpers/modules_helper.php index 51b06eed..b3500e08 100644 --- a/lbplanner/classes/helpers/modules_helper.php +++ b/lbplanner/classes/helpers/modules_helper.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * Collection of helper classes for handling modules * diff --git a/lbplanner/classes/helpers/notifications_helper.php b/lbplanner/classes/helpers/notifications_helper.php index 706b5857..2d2f82e5 100644 --- a/lbplanner/classes/helpers/notifications_helper.php +++ b/lbplanner/classes/helpers/notifications_helper.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * Provides helper classes for notification related stuff * diff --git a/lbplanner/classes/helpers/plan_helper.php b/lbplanner/classes/helpers/plan_helper.php index d7a79648..ffb9ad10 100644 --- a/lbplanner/classes/helpers/plan_helper.php +++ b/lbplanner/classes/helpers/plan_helper.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * Provides helper classes for any tables related with the planning function of the app * diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 572af742..7b9138e5 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * Provides helper classes for any tables related with the slot booking function of the app * diff --git a/lbplanner/classes/model/reservation.php b/lbplanner/classes/model/reservation.php index 82865c60..6c7b1a84 100644 --- a/lbplanner/classes/model/reservation.php +++ b/lbplanner/classes/model/reservation.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * Model for a reservation * diff --git a/lbplanner/classes/model/slot.php b/lbplanner/classes/model/slot.php index 76f0ce1b..d1bcfecb 100644 --- a/lbplanner/classes/model/slot.php +++ b/lbplanner/classes/model/slot.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * Model for a slot * diff --git a/lbplanner/classes/model/slot_filter.php b/lbplanner/classes/model/slot_filter.php index d798f2c7..c732fb52 100644 --- a/lbplanner/classes/model/slot_filter.php +++ b/lbplanner/classes/model/slot_filter.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * Model for a filter for slots * diff --git a/lbplanner/classes/polyfill/Enum.php b/lbplanner/classes/polyfill/Enum.php index e5c4d2a3..693731a0 100644 --- a/lbplanner/classes/polyfill/Enum.php +++ b/lbplanner/classes/polyfill/Enum.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * polyfill for php8 enums * diff --git a/lbplanner/classes/polyfill/EnumCase.php b/lbplanner/classes/polyfill/EnumCase.php index f5e35750..3bd16b2a 100644 --- a/lbplanner/classes/polyfill/EnumCase.php +++ b/lbplanner/classes/polyfill/EnumCase.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * case for enums * diff --git a/lbplanner/db/access.php b/lbplanner/db/access.php index 0302fc56..3e29ec72 100644 --- a/lbplanner/db/access.php +++ b/lbplanner/db/access.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * contains access levels, i.e. capabilities * diff --git a/lbplanner/db/install.php b/lbplanner/db/install.php index 4cef3c56..b6ea5700 100644 --- a/lbplanner/db/install.php +++ b/lbplanner/db/install.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * contains some stuff for the first install of the module * diff --git a/lbplanner/db/services.php b/lbplanner/db/services.php index 87680d6a..c7d56110 100644 --- a/lbplanner/db/services.php +++ b/lbplanner/db/services.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * contains all service endpoints * diff --git a/lbplanner/db/upgrade.php b/lbplanner/db/upgrade.php index ee29a436..feee43e2 100644 --- a/lbplanner/db/upgrade.php +++ b/lbplanner/db/upgrade.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * for upgrading the db * diff --git a/lbplanner/settings.php b/lbplanner/settings.php index d892dec4..cccad430 100644 --- a/lbplanner/settings.php +++ b/lbplanner/settings.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * Defines some settings * diff --git a/lbplanner/version.php b/lbplanner/version.php index caab6006..69c161af 100644 --- a/lbplanner/version.php +++ b/lbplanner/version.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * Defines versioning * From e19d47088a019b0626312a5eecdf5c46582ab95e Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 21:17:40 +0200 Subject: [PATCH 60/92] fix: moodle code checker for slot_helper --- lbplanner/classes/helpers/slot_helper.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 7b9138e5..48f8a39c 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -275,8 +275,16 @@ public static function calculate_slot_datetime(slot $slot, DateTimeInterface $no return new DateTimeImmutable($slotdatetime); } + /** + * Amends a date with time of day using the units system + * @param int $unit the unit to use + * @param DateTimeInterface $date the date (time of day will be ignored) + * + * @return DateTimeImmutable the new date with time of day filled in + * @link slot_helper::SCHOOL_UNITS + */ public static function amend_date_with_unit_time(int $unit, DateTimeInterface $date): DateTimeImmutable { - $daytime = slot_helper::SCHOOL_UNITS[$unit]; + $daytime = self::SCHOOL_UNITS[$unit]; return DateTimeImmutable::createFromFormat('YY-MM-DD tHH:MM', $date->format('Y-m-d ').$daytime); } From cd4007ef52683b02d3984a6cce94f492aa4d6f76 Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 21:18:20 +0200 Subject: [PATCH 61/92] fix: moodle code checker for model/slot --- lbplanner/classes/model/slot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lbplanner/classes/model/slot.php b/lbplanner/classes/model/slot.php index d1bcfecb..1803cc95 100644 --- a/lbplanner/classes/model/slot.php +++ b/lbplanner/classes/model/slot.php @@ -84,7 +84,7 @@ public function __construct(int $id, int $startunit, int $duration, int $weekday assert($startunit > 0); $this->startunit = $startunit; assert($duration > 0); - assert($duration + $startunit < sizeof(slot_helper::SCHOOL_UNITS)); + assert($duration + $startunit < count(slot_helper::SCHOOL_UNITS)); $this->duration = $duration; $this->weekday = WEEKDAY::from($weekday); assert(strlen($room) > 0 && strlen($room) <= slot_helper::ROOM_MAXLENGTH); From cc61b9a0a2dcad995bcba412b2f08648a3ec03c3 Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 21:18:49 +0200 Subject: [PATCH 62/92] fix: moodle code checker - remaining minor issues --- lbplanner/classes/helpers/slot_helper.php | 4 ++-- lbplanner/classes/model/reservation.php | 10 +++++----- lbplanner/classes/model/slot.php | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 48f8a39c..8ebf3292 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -49,7 +49,7 @@ class slot_helper { * how long the room names can be in characters * unicode characters might count as multiple characters */ - const ROOM_MAXLENGTH = 7; // TODO: increase to 255 or sumn + const ROOM_MAXLENGTH = 7; // TODO: increase to 255 or sumn. /** * school units according to untis, in H:i format */ @@ -262,7 +262,7 @@ public static function filter_slots_for_time(array $allslots, int $range): array */ public static function calculate_slot_datetime(slot $slot, DateTimeInterface $now): DateTimeImmutable { $slotdaytime = self::SCHOOL_UNITS[$slot->startunit]; - // NOTE: format and fromFormat use different date formatting conventions + // NOTE: format and fromFormat use different date formatting conventions. $slotdatetime = DateTime::createFromFormat('YY-MM-DD tHH:MM', $now->format('Y-m-d ').$slotdaytime); // Move to next day this weekday occurs (doesn't move if it's the same as today). $slotdatetime->modify('this '.WEEKDAY::name_from($slot->weekday)); diff --git a/lbplanner/classes/model/reservation.php b/lbplanner/classes/model/reservation.php index 6c7b1a84..d945e1dd 100644 --- a/lbplanner/classes/model/reservation.php +++ b/lbplanner/classes/model/reservation.php @@ -68,7 +68,7 @@ class reservation { /** * @var ?DateTimeImmutable $datetime the date this reservation ends at, with time filled in */ - private ?DateTimeImmutable $datetime_end; + private ?DateTimeImmutable $datetimeEnd; /** * Constructs a reservation @@ -126,7 +126,7 @@ public function get_slot(): slot { /** * Calculates the exact time and date this reservation is supposed to start - * + * * @return DateTimeImmutable */ public function get_datetime(): DateTimeImmutable { @@ -140,16 +140,16 @@ public function get_datetime(): DateTimeImmutable { /** * Calculates the exact time and date this reservation is supposed to start - * + * * @return DateTimeImmutable */ public function get_datetime_end(): DateTimeImmutable { if (is_null($this->datetime)) { $slot = $this->get_slot(); - $this->datetime_end = slot_helper::amend_date_with_unit_time($slot->startunit + $slot->duration, $this->date); + $this->datetimeEnd = slot_helper::amend_date_with_unit_time($slot->startunit + $slot->duration, $this->date); } - return $this->datetime_end; + return $this->datetimeEnd; } /** diff --git a/lbplanner/classes/model/slot.php b/lbplanner/classes/model/slot.php index 1803cc95..4621d2c0 100644 --- a/lbplanner/classes/model/slot.php +++ b/lbplanner/classes/model/slot.php @@ -148,7 +148,7 @@ public function prepare_for_db(): object { $obj->room = $this->room; $obj->size = $this->size; - if ($this->id !== 0){ + if ($this->id !== 0) { $obj->id = $this->id; } return $obj; From 9baae156c44a1a20acb2ed9a123cf1f41fb098d7 Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 21:27:49 +0200 Subject: [PATCH 63/92] fix: PHPDoc checker --- lbplanner/classes/helpers/slot_helper.php | 3 ++- lbplanner/classes/model/reservation.php | 2 +- lbplanner/services/slots/book_reservation.php | 3 +++ lbplanner/services/slots/create_slot.php | 5 +++++ lbplanner/services/slots/unbook_reservation.php | 2 ++ 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 8ebf3292..5e0b007d 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -290,8 +290,9 @@ public static function amend_date_with_unit_time(int $unit, DateTimeInterface $d } /** - * Returns a list of all slots belonging to a supervisor. + * Checks whether a user is supervisor for a specific slot. * @param int $supervisorid userid of the supervisor in question + * @param int $slotid the slot to check * * @return slot[] An array of the slots. */ diff --git a/lbplanner/classes/model/reservation.php b/lbplanner/classes/model/reservation.php index d945e1dd..2a437901 100644 --- a/lbplanner/classes/model/reservation.php +++ b/lbplanner/classes/model/reservation.php @@ -91,7 +91,7 @@ public function __construct(int $id, int $slotid, DateTimeImmutable $date, int $ /** * Mark the object as freshly created and sets the new ID * @param int $id the new ID after insertint into the DB - * @param slot $slot the cached slot object + * @param ?slot $slot the cached slot object */ public function set_fresh(int $id, ?slot $slot) { assert($this->id === 0); diff --git a/lbplanner/services/slots/book_reservation.php b/lbplanner/services/slots/book_reservation.php index b9428a5d..3aa1a5f3 100644 --- a/lbplanner/services/slots/book_reservation.php +++ b/lbplanner/services/slots/book_reservation.php @@ -69,6 +69,9 @@ public static function book_reservation_parameters(): external_function_paramete /** * Books a reservation + * @param int $slotid the slot to book a reservation for + * @param string $date the day this reservation should take place + * @param int $userid the user to reserve for */ public static function book_reservation(int $slotid, string $date, int $userid): array { global $USER, $DB; diff --git a/lbplanner/services/slots/create_slot.php b/lbplanner/services/slots/create_slot.php index 92f15770..16150bfc 100644 --- a/lbplanner/services/slots/create_slot.php +++ b/lbplanner/services/slots/create_slot.php @@ -82,6 +82,11 @@ public static function create_slot_parameters(): external_function_parameters { /** * Create a slot + * @param int $startunit the unit this slot starts in + * @param int $duration how long the unit lasts for + * @param int $weekday which day of the week this slot is on + * @param string $room which room this slot is for + * @param int $size how many pupils this slot can fit */ public static function create_slot(int $startunit, int $duration, int $weekday, string $room, int $size): array { global $USER, $DB; diff --git a/lbplanner/services/slots/unbook_reservation.php b/lbplanner/services/slots/unbook_reservation.php index 87f30197..b748c1ee 100644 --- a/lbplanner/services/slots/unbook_reservation.php +++ b/lbplanner/services/slots/unbook_reservation.php @@ -60,6 +60,8 @@ public static function unbook_reservation_parameters(): external_function_parame /** * Tries to request unbooking + * @param int $reservationid which reservation to unbook + * @param bool $nice whether to ask the student to unbook themself, or force-unbook */ public static function unbook_reservation(int $reservationid, bool $nice): void { global $USER, $DB; From ea0e9f2229a703b2c0090cf00165f4d9798df96c Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 21:57:58 +0200 Subject: [PATCH 64/92] fix: unfucked services db --- lbplanner/db/services.php | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/lbplanner/db/services.php b/lbplanner/db/services.php index c7d56110..8283e024 100644 --- a/lbplanner/db/services.php +++ b/lbplanner/db/services.php @@ -323,6 +323,24 @@ 'capabilities' => 'local/lb_planner:student', 'ajax' => true, ], + 'local_lbplanner_slots_unbook_reservation' => [ + 'classname' => 'local_lbplanner_services\slots_unbook_reservation', + 'methodname' => 'unbook_reservation', + 'classpath' => 'local/lbplanner/services/slots/unbook_reservation.php', + 'description' => 'Unbook a reservation', + 'type' => 'write', + 'capabilities' => 'local/lb_planner:student', + 'ajax' => true, + ], + 'local_lbplanner_slots_create_slot' => [ + 'classname' => 'local_lbplanner_services\slots_create_slot', + 'methodname' => 'create_slot', + 'classpath' => 'local/lbplanner/services/slots/create_slot.php', + 'description' => 'Create a slot', + 'type' => 'write', + 'capabilities' => 'local/lb_planner:teacher', + 'ajax' => true, + ], ]; $services = [ @@ -358,10 +376,11 @@ 'local_lbplanner_plan_accept_invite', 'local_lbplanner_plan_decline_invite', 'local_lbplanner_config_get_version', - 'local_lbplanner_slots_get_my_slot', + 'local_lbplanner_slots_book_reservation', + 'local_lbplanner_slots_create_slot', + 'local_lbplanner_slots_get_my_slots', 'local_lbplanner_slots_get_student_slots', 'local_lbplanner_slots_get_supervisor_slots', - 'local_lbplanner_slots_book_reservation', ], 'restrictedusers' => 0, 'enabled' => 1, From 11789f3afe5f507d01245620aed65d032311fa44 Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 21:58:55 +0200 Subject: [PATCH 65/92] fix: added parameter validation to API endpoints how tf did I forget those --- lbplanner/services/slots/book_reservation.php | 8 ++++++++ lbplanner/services/slots/create_slot.php | 12 +++++++++++- lbplanner/services/slots/unbook_reservation.php | 7 +++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lbplanner/services/slots/book_reservation.php b/lbplanner/services/slots/book_reservation.php index 3aa1a5f3..65ddcf14 100644 --- a/lbplanner/services/slots/book_reservation.php +++ b/lbplanner/services/slots/book_reservation.php @@ -75,6 +75,14 @@ public static function book_reservation_parameters(): external_function_paramete */ public static function book_reservation(int $slotid, string $date, int $userid): array { global $USER, $DB; + self::validate_parameters( + self::book_reservation_parameters(), + [ + 'slotid' => $slotid, + 'date' => $date, + 'userid' => $userid, + ] + ); $now = new DateTimeImmutable(); $dateobj = DateTimeImmutable::createFromFormat("YY-MM-DD", $date); diff --git a/lbplanner/services/slots/create_slot.php b/lbplanner/services/slots/create_slot.php index 16150bfc..b3b996e7 100644 --- a/lbplanner/services/slots/create_slot.php +++ b/lbplanner/services/slots/create_slot.php @@ -89,7 +89,17 @@ public static function create_slot_parameters(): external_function_parameters { * @param int $size how many pupils this slot can fit */ public static function create_slot(int $startunit, int $duration, int $weekday, string $room, int $size): array { - global $USER, $DB; + global $DB; + self::validate_parameters( + self::create_slot_parameters(), + [ + 'startunit' => $startunit, + 'duration' => $duration, + 'weekday' => $weekday, + 'room' => $room, + 'size' => $size, + ] + ); // Validating startunit. $maxUnit = count(slot_helper::SCHOOL_UNITS) - 1; diff --git a/lbplanner/services/slots/unbook_reservation.php b/lbplanner/services/slots/unbook_reservation.php index b748c1ee..e990ce07 100644 --- a/lbplanner/services/slots/unbook_reservation.php +++ b/lbplanner/services/slots/unbook_reservation.php @@ -65,6 +65,13 @@ public static function unbook_reservation_parameters(): external_function_parame */ public static function unbook_reservation(int $reservationid, bool $nice): void { global $USER, $DB; + self::validate_parameters( + self::unbook_reservation_parameters(), + [ + 'reservationid' => $reservationid, + 'nice' => $nice, + ] + ); $reservation = slot_helper::get_reservation($reservationid); $now = new DateTimeImmutable(); From d0146bb495730e6f2a124659ecc302f6674bc4e3 Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 21:59:17 +0200 Subject: [PATCH 66/92] fix: various smaller issues --- lbplanner/services/slots/create_slot.php | 3 +-- lbplanner/services/slots/get_supervisor_slots.php | 7 +------ lbplanner/services/slots/unbook_reservation.php | 2 +- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/lbplanner/services/slots/create_slot.php b/lbplanner/services/slots/create_slot.php index b3b996e7..b4f42fe6 100644 --- a/lbplanner/services/slots/create_slot.php +++ b/lbplanner/services/slots/create_slot.php @@ -26,8 +26,7 @@ use moodle_exception; /** - * Returns all slots the user can theoretically reserve. - * This does not include times the user has already reserved a slot for. + * Create a slot * * @package local_lbplanner * @subpackage services_slots diff --git a/lbplanner/services/slots/get_supervisor_slots.php b/lbplanner/services/slots/get_supervisor_slots.php index 5d4d7b2f..59cdc753 100644 --- a/lbplanner/services/slots/get_supervisor_slots.php +++ b/lbplanner/services/slots/get_supervisor_slots.php @@ -41,14 +41,9 @@ public static function get_supervisor_slots_parameters(): external_function_para /** * Returns all slots a supervisor controls. - * @param int $userid ID of the user in question (NOT the supervisor) */ - public static function get_supervisor_slots(int $userid): array { + public static function get_supervisor_slots(): array { global $USER; - self::validate_parameters( - self::get_supervisor_slots_parameters(), - ['userid' => $userid] - ); return slot_helper::get_supervisor_slots($USER->id); } diff --git a/lbplanner/services/slots/unbook_reservation.php b/lbplanner/services/slots/unbook_reservation.php index e990ce07..2dd4da6e 100644 --- a/lbplanner/services/slots/unbook_reservation.php +++ b/lbplanner/services/slots/unbook_reservation.php @@ -51,7 +51,7 @@ public static function unbook_reservation_parameters(): external_function_parame 'nice' => new external_value( PARAM_BOOL, 'whether to ask the student nicely to unbook themself via a notification', - VALUE_OPTIONAL, + VALUE_DEFAULT, true, NULL_NOT_ALLOWED ), From abea844fff2980b0278bd7f4454334b48be98c4c Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 22:01:53 +0200 Subject: [PATCH 67/92] fix: some remaining code checker issues --- lbplanner/classes/model/reservation.php | 6 +++--- lbplanner/services/slots/book_reservation.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lbplanner/classes/model/reservation.php b/lbplanner/classes/model/reservation.php index 2a437901..7f8ac6f6 100644 --- a/lbplanner/classes/model/reservation.php +++ b/lbplanner/classes/model/reservation.php @@ -68,7 +68,7 @@ class reservation { /** * @var ?DateTimeImmutable $datetime the date this reservation ends at, with time filled in */ - private ?DateTimeImmutable $datetimeEnd; + private ?DateTimeImmutable $datetimeend; /** * Constructs a reservation @@ -146,10 +146,10 @@ public function get_datetime(): DateTimeImmutable { public function get_datetime_end(): DateTimeImmutable { if (is_null($this->datetime)) { $slot = $this->get_slot(); - $this->datetimeEnd = slot_helper::amend_date_with_unit_time($slot->startunit + $slot->duration, $this->date); + $this->datetimeend = slot_helper::amend_date_with_unit_time($slot->startunit + $slot->duration, $this->date); } - return $this->datetimeEnd; + return $this->datetimeend; } /** diff --git a/lbplanner/services/slots/book_reservation.php b/lbplanner/services/slots/book_reservation.php index 65ddcf14..d07725d7 100644 --- a/lbplanner/services/slots/book_reservation.php +++ b/lbplanner/services/slots/book_reservation.php @@ -123,15 +123,15 @@ public static function book_reservation(int $slotid, string $date, int $userid): } // Check if user is already in slot. - foreach (slot_helper::get_reservations_for_slot($slotid) as $tmpReservation) { - if ($tmpReservation->userid === $userid) { + foreach (slot_helper::get_reservations_for_slot($slotid) as $tmpreservation) { + if ($tmpreservation->userid === $userid) { throw new \moodle_exception('Student is already in slot'); } } // TODO: check if user is already in a different slot at the same time. - // check if slot is full + // Check if slot is full. if ($slot->get_fullness() >= $slot->size) { throw new \moodle_exception('Slot is already full'); } From 4a96df8977fd63466af7ee1d9e9f8ca1d6d33498 Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 22:05:26 +0200 Subject: [PATCH 68/92] fix: remaining code checker issues --- lbplanner/lang/en/local_lbplanner.php | 1 + lbplanner/services/slots/create_slot.php | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lbplanner/lang/en/local_lbplanner.php b/lbplanner/lang/en/local_lbplanner.php index c0074026..71a353f1 100644 --- a/lbplanner/lang/en/local_lbplanner.php +++ b/lbplanner/lang/en/local_lbplanner.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * Defines some translation strings in english * diff --git a/lbplanner/services/slots/create_slot.php b/lbplanner/services/slots/create_slot.php index b4f42fe6..30499923 100644 --- a/lbplanner/services/slots/create_slot.php +++ b/lbplanner/services/slots/create_slot.php @@ -101,17 +101,17 @@ public static function create_slot(int $startunit, int $duration, int $weekday, ); // Validating startunit. - $maxUnit = count(slot_helper::SCHOOL_UNITS) - 1; + $maxunit = count(slot_helper::SCHOOL_UNITS) - 1; if ($startunit < 1) { throw new moodle_exception('can\'t have a start unit smaller than 1'); - } else if ($startunit > $maxUnit) { - throw new moodle_exception("can't have a start unit larger than {$maxUnit}"); + } else if ($startunit > $maxunit) { + throw new moodle_exception("can't have a start unit larger than {$maxunit}"); } // Validating duration. if ($duration < 1) { throw new moodle_exception('duration must be at least 1'); - } else if ($startunit + $duration > $maxUnit) { - throw new moodle_exception("slot goes past the max unit {$maxUnit}"); + } else if ($startunit + $duration > $maxunit) { + throw new moodle_exception("slot goes past the max unit {$maxunit}"); } // Validating weekday. WEEKDAY::from($weekday); From cc7a20c299e33398b56ac1b789b03eae30c5da49 Mon Sep 17 00:00:00 2001 From: Riedler Date: Mon, 19 Aug 2024 23:11:12 +0200 Subject: [PATCH 69/92] fixed namespace in EnumCase --- lbplanner/classes/polyfill/Enum.php | 2 +- lbplanner/classes/polyfill/EnumCase.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lbplanner/classes/polyfill/Enum.php b/lbplanner/classes/polyfill/Enum.php index 693731a0..410c6273 100644 --- a/lbplanner/classes/polyfill/Enum.php +++ b/lbplanner/classes/polyfill/Enum.php @@ -27,7 +27,7 @@ use ReflectionClass; use ValueError; -use lb_planner_local\polyfill\EnumCase; +use local_lbplanner\polyfill\EnumCase; /** * Class which is meant to serve as a substitute for native enums. diff --git a/lbplanner/classes/polyfill/EnumCase.php b/lbplanner/classes/polyfill/EnumCase.php index 3bd16b2a..bb9c35ee 100644 --- a/lbplanner/classes/polyfill/EnumCase.php +++ b/lbplanner/classes/polyfill/EnumCase.php @@ -23,7 +23,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -namespace lb_planner_local\polyfill; +namespace local_lbplanner\polyfill; defined('MOODLE_INTERNAL') || die(); From c647b236fa425792e004e6736bd6735d58a9a7c2 Mon Sep 17 00:00:00 2001 From: Riedler Date: Tue, 20 Aug 2024 01:08:16 +0200 Subject: [PATCH 70/92] fix: php is confused by "mixed" type hint --- lbplanner/classes/polyfill/EnumCase.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lbplanner/classes/polyfill/EnumCase.php b/lbplanner/classes/polyfill/EnumCase.php index bb9c35ee..f2451977 100644 --- a/lbplanner/classes/polyfill/EnumCase.php +++ b/lbplanner/classes/polyfill/EnumCase.php @@ -36,14 +36,14 @@ class EnumCase { /** @var string the name of the case */ public string $name; /** @var string the value of the case */ - public mixed $value; + public $value; /** * Constructs an EnumCase * * @param string $name the name of the case * @param mixed $value the value of the case */ - public function __construct(string $name, mixed $value) { + public function __construct(string $name, $value) { $this->name = $name; $this->value = $value; } From d01f8c59ac3ad5c71c6da6126906f5feb36e4aa2 Mon Sep 17 00:00:00 2001 From: Riedler Date: Fri, 23 Aug 2024 15:48:13 +0200 Subject: [PATCH 71/92] refactor: hoisted get_all_course_modules and get_all_modules --- .../modules/get_all_course_modules.php | 22 ++++++++---------- .../services/modules/get_all_modules.php | 23 ++++++------------- 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/lbplanner/services/modules/get_all_course_modules.php b/lbplanner/services/modules/get_all_course_modules.php index b53ec82d..78f2a9a1 100644 --- a/lbplanner/services/modules/get_all_course_modules.php +++ b/lbplanner/services/modules/get_all_course_modules.php @@ -21,7 +21,6 @@ use external_multiple_structure; use external_value; use local_lbplanner\helpers\modules_helper; -use local_lbplanner\helpers\user_helper; /** * Get all the modules of the given course. @@ -39,13 +38,13 @@ class modules_get_all_course_modules extends external_api { public static function get_all_course_modules_parameters(): external_function_parameters { return new external_function_parameters([ 'courseid' => new external_value(PARAM_INT, 'The id of the course', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - 'userid' => new external_value(PARAM_INT, 'The id of the user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), 'ekenabled' => new external_value( - PARAM_BOOL, - 'Whether or not to include ek modules', - VALUE_REQUIRED, - false, - NULL_NOT_ALLOWED), + PARAM_BOOL, + 'Whether to include ek modules', + VALUE_DEFAULT, + false, + NULL_NOT_ALLOWED + ), ]); } @@ -58,16 +57,13 @@ public static function get_all_course_modules_parameters(): external_function_pa * @return array the modules */ public static function get_all_course_modules(int $courseid, int $userid, bool $ekenabled): array { - global $DB; - + global $USER; self::validate_parameters( self::get_all_course_modules_parameters(), - ['courseid' => $courseid, 'userid' => $userid, 'ekenabled' => $ekenabled] + ['courseid' => $courseid, 'ekenabled' => $ekenabled] ); - user_helper::assert_access($userid); - - return modules_helper::get_all_course_modules($courseid, $userid, $ekenabled); + return modules_helper::get_all_course_modules($courseid, $USER->id, $ekenabled); } /** diff --git a/lbplanner/services/modules/get_all_modules.php b/lbplanner/services/modules/get_all_modules.php index e3363765..92833d0a 100644 --- a/lbplanner/services/modules/get_all_modules.php +++ b/lbplanner/services/modules/get_all_modules.php @@ -19,10 +19,8 @@ use external_api; use external_function_parameters; use external_multiple_structure; -use external_value; use local_lbplanner\helpers\course_helper; use local_lbplanner\helpers\modules_helper; -use local_lbplanner\helpers\user_helper; use local_lbplanner\helpers\plan_helper; @@ -40,36 +38,29 @@ class modules_get_all_modules extends external_api { * @return external_function_parameters */ public static function get_all_modules_parameters(): external_function_parameters { - return new external_function_parameters([ - 'userid' => new external_value(PARAM_INT, 'The id of the user', VALUE_REQUIRED, null, NULL_NOT_ALLOWED), - ]); + return new external_function_parameters([]); } /** * Returns all the modules for a user. * - * @param int $userid The ID of the user * @return array the modules */ - public static function get_all_modules(int $userid): array { - global $DB; - - self::validate_parameters(self::get_all_modules_parameters(), ['userid' => $userid]); - - user_helper::assert_access($userid); + public static function get_all_modules(): array { + global $USER; $modules = []; - $courses = self::call_external_function('local_lbplanner_courses_get_all_courses', ['userid' => $userid]); - $plan = plan_helper::get_plan(plan_helper::get_plan_id($userid)); + $courses = self::call_external_function('local_lbplanner_courses_get_all_courses', []); + $plan = plan_helper::get_plan(plan_helper::get_plan_id($USER->id)); $ekenabled = $plan["enableek"]; foreach ($courses["data"] as $course) { - if ($course["enabled"] == course_helper::DISABLED_COURSE) { + if ($course["enabled"] === course_helper::DISABLED_COURSE) { continue; } $modules = array_merge( - modules_helper::get_all_course_modules($course['courseid'], $userid, $ekenabled), + modules_helper::get_all_course_modules($course['courseid'], $USER->id, $ekenabled), $modules ); } From b759782479250c88002948e71a6be3d1b0628e3e Mon Sep 17 00:00:00 2001 From: Riedler Date: Fri, 23 Aug 2024 16:15:06 +0200 Subject: [PATCH 72/92] feat: implemented course model object --- lbplanner/classes/model/course.php | 146 +++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 lbplanner/classes/model/course.php diff --git a/lbplanner/classes/model/course.php b/lbplanner/classes/model/course.php new file mode 100644 index 00000000..95ec0466 --- /dev/null +++ b/lbplanner/classes/model/course.php @@ -0,0 +1,146 @@ +. + +/** + * Model for a course + * + * @package local_lbplanner + * @subpackage helpers + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\model; + +use external_single_structure; +use external_value; + +/** + * Model class for course + */ +class course { + /** + * @var int $id course ID + */ + public int $id; + /** + * @var int $courseid the moodle-internal ID of the course + */ + public int $courseid; + /** + * @var int $userid the user for whom these course settings are for + */ + public int $userid; + /** + * @var string $shortname the short name of this course for this user + * maximum size: 5 chars + */ + public string $shortname; + /** + * @var string $color the color for this course + * maximum size: 10 chars + * TODO: what is the format of this ?? RRGGBB is just 6 chars + */ + public string $color; + /** + * @var bool $enabled whether the user wants to see this course + */ + public bool $enabled; + + /** + * Constructs a new course + * @param int $id ID of course + * @param int $courseid ID of the moodle course + * @param int $userid ID of the user these settings are for + * @param string $shortname the short name for this course + * @param string $color the color for this course + * @param bool $enabled whether the course is enabled + */ + public function __construct(int $id, int $courseid, int $userid, string $shortname, string $color, bool $enabled) { + $this->id = $id; + $this->courseid = $courseid; + $this->userid = $userid; + assert(strlen($shortname) <= 5); + assert(strlen($shortname) > 0); + $this->shortname = $shortname; + assert(strlen($color) <= 10); + // TODO: check color format. + $this->color = $color; + $this->enabled = $enabled; + } + + /** + * Takes data from DB and makes a new Course out of it + * + * @return object a representation of this course and its data + */ + public static function from_db(object $obj): self { + assert($obj->enabled === 0 || $obj->enabled === 1); + return new self($obj->id, $obj->courseid, $obj->userid, $obj->shortname, $obj->color, (bool) $obj->enabled); + } + + /** + * Prepares data for the DB endpoint. + * + * @return object a representation of this course and its data + */ + public function prepare_for_db(): object { + $obj = new \stdClass(); + + $obj->id = $this->id; + $obj->courseid = $this->courseid; + $obj->userid = $this->userid; + $obj->shortname = $this->shortname; + $obj->color = $this->color; + $obj->enabled = $this->enabled ? 1:0; // The DB uses int instead of bool here. + + return $obj; + } + + /** + * Prepares data for the API endpoint. + * + * @return array a representation of this course and its data + */ + public function prepare_for_api(): array { + return [ + 'id' => $this->id, + 'courseid' => $this->courseid, + 'userid' => $this->userid, + 'shortname' => $this->shortname, + 'color' => $this->color, + 'enabled' => $this->enabled ? 1:0, // Moodle's API uses int instead of bool. + ]; + } + + /** + * Returns the data structure of a course for the API. + * + * @return external_single_structure The data structure of a course for the API. + */ + public static function api_structure(): external_single_structure { + return new external_single_structure( + [ + 'id' => new external_value(PARAM_INT, 'course ID'), + 'courseid' => new external_value(PARAM_INT, 'the moodle-internal ID of the course'), + 'userid' => new external_value(PARAM_INT, 'the user for whom these course settings are for'), + 'shortname' => new external_value(PARAM_TEXT, 'the short name of this course for this user (maximum size: 5 chars)'), + 'color' => new external_value(PARAM_TEXT, 'the color for this course (maximum size: 10 chars)'), // TODO: describe format + 'enabled' => new external_value(PARAM_BOOL, 'whether the user wants to see this course'), + ] + ); + } +} From c316d8a0548b538cddd24bedd2f69cf3369d4a25 Mon Sep 17 00:00:00 2001 From: Riedler Date: Fri, 23 Aug 2024 16:26:31 +0200 Subject: [PATCH 73/92] fix: replaced dead link in code comments yeah I'm aware this is Nya! arigato so what? huh? --- lbplanner/services/courses/get_all_courses.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lbplanner/services/courses/get_all_courses.php b/lbplanner/services/courses/get_all_courses.php index 976e71d5..cd14516c 100644 --- a/lbplanner/services/courses/get_all_courses.php +++ b/lbplanner/services/courses/get_all_courses.php @@ -58,7 +58,7 @@ public static function get_all_courses(): array { $courses = enrol_get_my_courses(); // Remove Duplicates. $courses = array_unique($courses, SORT_REGULAR); - // Check this out: https://www.youtube.com/watch?v=z3Pzfi476HI . + // Check this out: https://www.youtube.com/watch?v=WmdAk2zyQkU . $catgirls = []; foreach ($courses as $course) { From ba2c820a76fc5cfd12cc56c6feaf0b0bfbb94bd0 Mon Sep 17 00:00:00 2001 From: Riedler Date: Fri, 23 Aug 2024 17:09:51 +0200 Subject: [PATCH 74/92] fix: removed incorrect ref in slots table to lbplanner_courses table I literally just today realized that 'lbplanner courses' are user-specific while 'moodle courses' are global. Perhaps in the future someone should rename our 'course' stuff to 'courseprefs' or something like that. --- lbplanner/db/install.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/lbplanner/db/install.xml b/lbplanner/db/install.xml index 13c855e2..86012c1a 100644 --- a/lbplanner/db/install.xml +++ b/lbplanner/db/install.xml @@ -152,7 +152,6 @@ - From 6c8f83eaa5027b30642fa01d835fdd220308a81b Mon Sep 17 00:00:00 2001 From: Riedler Date: Fri, 23 Aug 2024 17:45:34 +0200 Subject: [PATCH 75/92] refactor: harmonized everything with the new course model object --- lbplanner/classes/helpers/course_helper.php | 70 ++++++++--- lbplanner/classes/helpers/slot_helper.php | 1 + lbplanner/classes/model/course.php | 111 ++++++++++++++++-- .../services/courses/get_all_courses.php | 66 ++--------- lbplanner/services/courses/update_course.php | 17 ++- .../modules/get_all_course_modules.php | 2 +- .../services/modules/get_all_modules.php | 8 +- 7 files changed, 171 insertions(+), 104 deletions(-) diff --git a/lbplanner/classes/helpers/course_helper.php b/lbplanner/classes/helpers/course_helper.php index 2bbfcc40..d103d68d 100644 --- a/lbplanner/classes/helpers/course_helper.php +++ b/lbplanner/classes/helpers/course_helper.php @@ -18,7 +18,8 @@ use context_course; use dml_exception; -use stdClass; + +use local_lbplanner\model\course; /** * Helper class for courses @@ -56,14 +57,6 @@ class course_helper { "#8B37CA", "#CA37B9", ]; - /** - * constant that represents a disabled course - */ - const DISABLED_COURSE = 0; - /** - * constant that represents an enabled course - */ - const ENABLED_COURSE = 1; /** * Get the current school year from the config @@ -86,12 +79,59 @@ public static function get_current_year(): string { * @param int $courseid id of the course in lbplanner * @param int $userid id of the user * - * @return stdClass course from lbplanner + * @return course course from lbplanner * @throws dml_exception */ - public static function get_lbplanner_course(int $courseid, int $userid): stdClass { + public static function get_lbplanner_course(int $courseid, int $userid): course { global $DB; - return $DB->get_record(self::LBPLANNER_COURSE_TABLE, ['courseid' => $courseid, 'userid' => $userid]); + return course::from_db($DB->get_record(self::LBPLANNER_COURSE_TABLE, ['courseid' => $courseid, 'userid' => $userid])); + } + + /** + * Get all the courses of the current year. + * @return course[] all courses of the current year + */ + public static function get_all_lbplanner_courses(): array { + global $DB, $USER; + $userid = $USER->id; + + $mdl_courses = enrol_get_my_courses(); + // Remove Duplicates. + $mdl_courses = array_unique($mdl_courses, SORT_REGULAR); + // Check this out: https://www.youtube.com/watch?v=WmdAk2zyQkU . + $results = []; + + foreach ($mdl_courses as $mdl_course) { + $courseid = $mdl_course->id; + // Check if the course is from the current year. + // TODO: pass fullname to function instead of courseid. + if (!course_helper::check_current_year($courseid)) { + continue; + } + // Check if the course is already in the LB Planner database. + if ($DB->record_exists(course_helper::LBPLANNER_COURSE_TABLE, ['courseid' => $courseid, 'userid' => $userid])) { + $fetchedcourse = course_helper::get_lbplanner_course($courseid, $userid); + } else { + // IF not create an Object to be put into the LB Planner database. + $fetchedcourse = new course( + 0, $courseid, + course_helper::COLORS[array_rand(course_helper::COLORS)], + course::prepare_shortname($mdl_course->shortname), + false, + $userid, + ); + $fetchedcourse->set_fresh( + $DB->insert_record( + course_helper::LBPLANNER_COURSE_TABLE, + $fetchedcourse->prepare_for_db() + ) + ); + } + // Add name to fetched Course. + $fetchedcourse->set_fullname($mdl_course->fullname); + array_push($results, $fetchedcourse); + } + return $results; } /** @@ -128,10 +168,6 @@ public static function get_fullname(int $courseid): string { * @throws dml_exception */ public static function check_current_year(int $courseid): bool { - if (strpos(self::get_fullname($courseid), self::get_current_year()) !== false) { - return true; - } else { - return false; - } + return strpos(self::get_fullname($courseid), self::get_current_year()) !== false; } } diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 5e0b007d..af2dddd9 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -207,6 +207,7 @@ public static function get_filters_for_slot(int $slotid): array { * @return slot[] the filtered slot array */ public static function filter_slots_for_user(array $allslots, mixed $user): array { + // TODO: replace this with helper function $mycourses = external_api::call_external_function('local_lbplanner_courses_get_all_courses', ['userid' => $user->id]); $mycourseids = []; foreach ($mycourses as $course) { diff --git a/lbplanner/classes/model/course.php b/lbplanner/classes/model/course.php index 95ec0466..49ff9975 100644 --- a/lbplanner/classes/model/course.php +++ b/lbplanner/classes/model/course.php @@ -27,6 +27,7 @@ use external_single_structure; use external_value; +use local_lbplanner\helpers\course_helper; /** * Model class for course @@ -35,7 +36,7 @@ class course { /** * @var int $id course ID */ - public int $id; + private int $id; /** * @var int $courseid the moodle-internal ID of the course */ @@ -50,9 +51,11 @@ class course { */ public string $shortname; /** - * @var string $color the color for this course - * maximum size: 10 chars - * TODO: what is the format of this ?? RRGGBB is just 6 chars + * @var string $fullname the full name of this course + */ + private ?string $fullname; + /** + * @var string $color the color for this course as #RRGGBB */ public string $color; /** @@ -66,47 +69,127 @@ class course { * @param int $courseid ID of the moodle course * @param int $userid ID of the user these settings are for * @param string $shortname the short name for this course - * @param string $color the color for this course + * @param string $color the color for this course as #RRGGBB * @param bool $enabled whether the course is enabled */ public function __construct(int $id, int $courseid, int $userid, string $shortname, string $color, bool $enabled) { $this->id = $id; $this->courseid = $courseid; $this->userid = $userid; - assert(strlen($shortname) <= 5); - assert(strlen($shortname) > 0); - $this->shortname = $shortname; - assert(strlen($color) <= 10); - // TODO: check color format. - $this->color = $color; + $this->set_shortname($shortname); + $this->set_color($color); $this->enabled = $enabled; + $this->fullname = null; } /** * Takes data from DB and makes a new Course out of it * * @return object a representation of this course and its data + * @throws \AssertionError */ public static function from_db(object $obj): self { assert($obj->enabled === 0 || $obj->enabled === 1); return new self($obj->id, $obj->courseid, $obj->userid, $obj->shortname, $obj->color, (bool) $obj->enabled); } + /** + * Mark the object as freshly created and sets the new ID + * @param int $id the new ID after insertint into the DB + * @throws \AssertionError + */ + public function set_fresh(int $id) { + assert($this->id === 0); + assert($id !== 0); + $this->id = $id; + } + + /** + * sets the color as #RRGGBB + * @param string $color the color + * @throws \AssertionError + */ + public function set_color(string $color) { + // TODO: check color format. + assert(strlen($color) <= 10); + $this->color = $color; + } + + /** + * sets the shortname + * @param string $shortname the shortname + * @throws \AssertionError + */ + public function set_shortname(string $shortname) { + assert(strlen($shortname) <= 5); + assert(strlen($shortname) > 0); + $this->shortname = $shortname; + } + + /** + * sets whether the course is enabled + * @param bool $enabled whether to enable the course + */ + public function set_enabled(bool $enabled) { + $this->enabled = $enabled; + } + + /** + * sets the cached fullname (mainly for deduplicating DB requests) + * @param string $fullname the cached fullname + */ + public function set_fullname(string $fullname) { + // If we already have a fullname stored and it's different, then we've found data inconsistency. + assert($this->fullname === null || $this->fullname === $fullname); + $this->fullname = $fullname; + } + + /** + * get the cached fullname + * @return string the cached fullname + */ + public function get_fullname(): string { + if ($this->fullname === null) { + $this->fullname = course_helper::get_fullname($this->courseid); + } + + return $this->fullname; + } + + /** + * Prepares a string to be eligible for shortname + * @param string $shortname the shortname to be prepared + * @return string the prepared shortname + */ + public static function prepare_shortname(string $shortname): string { + if (strpos($shortname, ' ') !== false) { + $shortname = substr($shortname, 0, strpos($shortname, ' ')); + } + if (strlen($shortname) >= 5) { + $shortname = substr($shortname, 0, 5); + } + return strtoupper($shortname); + } + /** * Prepares data for the DB endpoint. + * doesn't set ID if it's 0 * * @return object a representation of this course and its data */ public function prepare_for_db(): object { $obj = new \stdClass(); - $obj->id = $this->id; $obj->courseid = $this->courseid; $obj->userid = $this->userid; $obj->shortname = $this->shortname; $obj->color = $this->color; $obj->enabled = $this->enabled ? 1:0; // The DB uses int instead of bool here. + if ($this->id !== 0) { + $obj->id = $this->id; + } + return $obj; } @@ -120,6 +203,7 @@ public function prepare_for_api(): array { 'id' => $this->id, 'courseid' => $this->courseid, 'userid' => $this->userid, + 'name' => $this->get_fullname(), 'shortname' => $this->shortname, 'color' => $this->color, 'enabled' => $this->enabled ? 1:0, // Moodle's API uses int instead of bool. @@ -137,8 +221,9 @@ public static function api_structure(): external_single_structure { 'id' => new external_value(PARAM_INT, 'course ID'), 'courseid' => new external_value(PARAM_INT, 'the moodle-internal ID of the course'), 'userid' => new external_value(PARAM_INT, 'the user for whom these course settings are for'), + 'name' => new external_value(PARAM_TEXT, 'the full name of this course'), 'shortname' => new external_value(PARAM_TEXT, 'the short name of this course for this user (maximum size: 5 chars)'), - 'color' => new external_value(PARAM_TEXT, 'the color for this course (maximum size: 10 chars)'), // TODO: describe format + 'color' => new external_value(PARAM_TEXT, 'the color for this course as #RRGGBB'), 'enabled' => new external_value(PARAM_BOOL, 'whether the user wants to see this course'), ] ); diff --git a/lbplanner/services/courses/get_all_courses.php b/lbplanner/services/courses/get_all_courses.php index cd14516c..2ee6374e 100644 --- a/lbplanner/services/courses/get_all_courses.php +++ b/lbplanner/services/courses/get_all_courses.php @@ -16,15 +16,12 @@ namespace local_lbplanner_services; -use coding_exception; -use dml_exception; use external_api; use external_function_parameters; use external_multiple_structure; -use external_single_structure; -use external_value; + use local_lbplanner\helpers\course_helper; -use moodle_exception; +use local_lbplanner\model\course; /** * Get all the courses of the current year. @@ -46,55 +43,14 @@ public static function get_all_courses_parameters(): external_function_parameter /** * Get all the courses of the current year. - * @throws coding_exception - * @throws dml_exception - * @throws moodle_exception */ public static function get_all_courses(): array { - global $DB, $USER; - - $userid = $USER->id; - - $courses = enrol_get_my_courses(); - // Remove Duplicates. - $courses = array_unique($courses, SORT_REGULAR); - // Check this out: https://www.youtube.com/watch?v=WmdAk2zyQkU . - $catgirls = []; - + $courses = course_helper::get_all_lbplanner_courses(); + $results = []; foreach ($courses as $course) { - $courseid = $course->id; - $name = $course->fullname; - $shortname = $course->shortname; - // Check if the shortname contains a space. - if (strpos($shortname, ' ') !== false) { - $shortname = substr($shortname, 0, strpos($shortname, ' ')); - } - if (strlen($shortname) >= 5) { - $shortname = substr($shortname, 0, 5); - } - // Check if the course is from the current year. - if (course_helper::check_current_year($courseid)) { - continue; - } - // Check if the course is already in the LB Planner database. - if ($DB->record_exists(course_helper::LBPLANNER_COURSE_TABLE, ['courseid' => $courseid, 'userid' => $userid])) { - $fetchedcourse = course_helper::get_lbplanner_course($courseid, $userid); - } else { - // IF not create an Object to be put into the LB Planner database. - $fetchedcourse = (object) [ - 'courseid' => $courseid, - 'color' => course_helper::COLORS[array_rand(course_helper::COLORS)], - 'shortname' => strtoupper($shortname), - 'enabled' => course_helper::DISABLED_COURSE, - 'userid' => $userid, - ]; - $DB->insert_record(course_helper::LBPLANNER_COURSE_TABLE, $fetchedcourse); - } - // Add name to fetched Course. - $fetchedcourse->name = $name; - $catgirls[] = $fetchedcourse; + array_push($results, $course->prepare_for_api()); } - return $catgirls; + return $results; } /** @@ -103,15 +59,7 @@ public static function get_all_courses(): array { */ public static function get_all_courses_returns(): external_multiple_structure { return new external_multiple_structure( - new external_single_structure( - [ - 'courseid' => new external_value(PARAM_INT, 'The id of the course'), - 'color' => new external_value(PARAM_TEXT, 'The color of the course in HEX'), - 'name' => new external_value(PARAM_TEXT, 'The name of the course'), - 'shortname' => new external_value(PARAM_TEXT, 'The shortname of the course'), - 'enabled' => new external_value(PARAM_BOOL, 'Whether the course is enabled or not'), - ] - ) + course::api_structure() ); } } diff --git a/lbplanner/services/courses/update_course.php b/lbplanner/services/courses/update_course.php index 5010779d..26ed6a87 100644 --- a/lbplanner/services/courses/update_course.php +++ b/lbplanner/services/courses/update_course.php @@ -56,14 +56,12 @@ public static function update_course_parameters(): external_function_parameters * @param int $courseid The id of the course * @param string $color The color of the course * @param string $shortname The shortname of the course - * @param bool $enabled Whether the course is enabled or not + * @param int $enabled Whether the course is enabled or not (0 or 1) * @return void - * @throws dml_exception - * @throws invalid_parameter_exception * @throws moodle_exception */ - public static function update_course($courseid, $color, $shortname, $enabled): void { - global $DB , $USER; + public static function update_course(int $courseid, string $color, string $shortname, int $enabled): void { + global $DB, $USER; self::validate_parameters( self::update_course_parameters(), @@ -82,17 +80,16 @@ public static function update_course($courseid, $color, $shortname, $enabled): v $course = course_helper::get_lbplanner_course($courseid, $USER->id); if ($color !== null) { - $course->color = $color; + $course->set_color($color); } if ($shortname !== null) { - $course->shortname = $shortname; + $course->set_shortname($shortname); } if ($enabled !== null) { - $course->enabled = $enabled; + $course->set_enabled((bool) $enabled); } - $DB->update_record(course_helper::LBPLANNER_COURSE_TABLE, $course); - + $DB->update_record(course_helper::LBPLANNER_COURSE_TABLE, $course->prepare_for_db()); } /** diff --git a/lbplanner/services/modules/get_all_course_modules.php b/lbplanner/services/modules/get_all_course_modules.php index 78f2a9a1..746d7a25 100644 --- a/lbplanner/services/modules/get_all_course_modules.php +++ b/lbplanner/services/modules/get_all_course_modules.php @@ -56,7 +56,7 @@ public static function get_all_course_modules_parameters(): external_function_pa * @param bool $ekenabled whether or not to include ek modules * @return array the modules */ - public static function get_all_course_modules(int $courseid, int $userid, bool $ekenabled): array { + public static function get_all_course_modules(int $courseid, bool $ekenabled): array { global $USER; self::validate_parameters( self::get_all_course_modules_parameters(), diff --git a/lbplanner/services/modules/get_all_modules.php b/lbplanner/services/modules/get_all_modules.php index 92833d0a..9d065dd1 100644 --- a/lbplanner/services/modules/get_all_modules.php +++ b/lbplanner/services/modules/get_all_modules.php @@ -51,16 +51,16 @@ public static function get_all_modules(): array { $modules = []; - $courses = self::call_external_function('local_lbplanner_courses_get_all_courses', []); + $courses = course_helper::get_all_lbplanner_courses(); $plan = plan_helper::get_plan(plan_helper::get_plan_id($USER->id)); $ekenabled = $plan["enableek"]; - foreach ($courses["data"] as $course) { - if ($course["enabled"] === course_helper::DISABLED_COURSE) { + foreach ($courses as $course) { + if ($course->enabled) { continue; } $modules = array_merge( - modules_helper::get_all_course_modules($course['courseid'], $USER->id, $ekenabled), + modules_helper::get_all_course_modules($course->courseid, $USER->id, $ekenabled), $modules ); } From 78c37f2adc5ae95297e3866a527a3f35b06e5306 Mon Sep 17 00:00:00 2001 From: Riedler Date: Fri, 23 Aug 2024 17:54:52 +0200 Subject: [PATCH 76/92] fix: initialization of course in course_helper::get_all_lbplanner_courses() the order was wrong. a copy-paste error on my end --- lbplanner/classes/helpers/course_helper.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lbplanner/classes/helpers/course_helper.php b/lbplanner/classes/helpers/course_helper.php index d103d68d..82a9f89e 100644 --- a/lbplanner/classes/helpers/course_helper.php +++ b/lbplanner/classes/helpers/course_helper.php @@ -114,11 +114,10 @@ public static function get_all_lbplanner_courses(): array { } else { // IF not create an Object to be put into the LB Planner database. $fetchedcourse = new course( - 0, $courseid, - course_helper::COLORS[array_rand(course_helper::COLORS)], + 0, $courseid, $userid, course::prepare_shortname($mdl_course->shortname), + course_helper::COLORS[array_rand(course_helper::COLORS)], false, - $userid, ); $fetchedcourse->set_fresh( $DB->insert_record( From a40b0f97b9c8e106b2cb3c1fcd2e5e20b5d44b8b Mon Sep 17 00:00:00 2001 From: Riedler Date: Fri, 23 Aug 2024 18:37:22 +0200 Subject: [PATCH 77/92] fix: moodle code checker --- lbplanner/classes/helpers/course_helper.php | 22 ++++++++++----------- lbplanner/classes/helpers/slot_helper.php | 2 +- lbplanner/classes/model/course.php | 16 +++++++-------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lbplanner/classes/helpers/course_helper.php b/lbplanner/classes/helpers/course_helper.php index 82a9f89e..dfce13c3 100644 --- a/lbplanner/classes/helpers/course_helper.php +++ b/lbplanner/classes/helpers/course_helper.php @@ -95,39 +95,39 @@ public static function get_all_lbplanner_courses(): array { global $DB, $USER; $userid = $USER->id; - $mdl_courses = enrol_get_my_courses(); + $mdlcourses = enrol_get_my_courses(); // Remove Duplicates. - $mdl_courses = array_unique($mdl_courses, SORT_REGULAR); + $mdlcourses = array_unique($mdlcourses, SORT_REGULAR); // Check this out: https://www.youtube.com/watch?v=WmdAk2zyQkU . $results = []; - foreach ($mdl_courses as $mdl_course) { - $courseid = $mdl_course->id; + foreach ($mdlcourses as $mdlcourse) { + $courseid = $mdlcourse->id; // Check if the course is from the current year. // TODO: pass fullname to function instead of courseid. - if (!course_helper::check_current_year($courseid)) { + if (!self::check_current_year($courseid)) { continue; } // Check if the course is already in the LB Planner database. - if ($DB->record_exists(course_helper::LBPLANNER_COURSE_TABLE, ['courseid' => $courseid, 'userid' => $userid])) { - $fetchedcourse = course_helper::get_lbplanner_course($courseid, $userid); + if ($DB->record_exists(self::LBPLANNER_COURSE_TABLE, ['courseid' => $courseid, 'userid' => $userid])) { + $fetchedcourse = self::get_lbplanner_course($courseid, $userid); } else { // IF not create an Object to be put into the LB Planner database. $fetchedcourse = new course( 0, $courseid, $userid, - course::prepare_shortname($mdl_course->shortname), - course_helper::COLORS[array_rand(course_helper::COLORS)], + course::prepare_shortname($mdlcourse->shortname), + self::COLORS[array_rand(self::COLORS)], false, ); $fetchedcourse->set_fresh( $DB->insert_record( - course_helper::LBPLANNER_COURSE_TABLE, + self::LBPLANNER_COURSE_TABLE, $fetchedcourse->prepare_for_db() ) ); } // Add name to fetched Course. - $fetchedcourse->set_fullname($mdl_course->fullname); + $fetchedcourse->set_fullname($mdlcourse->fullname); array_push($results, $fetchedcourse); } return $results; diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index af2dddd9..ea14b8a7 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -207,7 +207,7 @@ public static function get_filters_for_slot(int $slotid): array { * @return slot[] the filtered slot array */ public static function filter_slots_for_user(array $allslots, mixed $user): array { - // TODO: replace this with helper function + // TODO: replace this with helper function. $mycourses = external_api::call_external_function('local_lbplanner_courses_get_all_courses', ['userid' => $user->id]); $mycourseids = []; foreach ($mycourses as $course) { diff --git a/lbplanner/classes/model/course.php b/lbplanner/classes/model/course.php index 49ff9975..917ce2c5 100644 --- a/lbplanner/classes/model/course.php +++ b/lbplanner/classes/model/course.php @@ -184,7 +184,7 @@ public function prepare_for_db(): object { $obj->userid = $this->userid; $obj->shortname = $this->shortname; $obj->color = $this->color; - $obj->enabled = $this->enabled ? 1:0; // The DB uses int instead of bool here. + $obj->enabled = $this->enabled ? 1 : 0; // The DB uses int instead of bool here. if ($this->id !== 0) { $obj->id = $this->id; @@ -206,7 +206,7 @@ public function prepare_for_api(): array { 'name' => $this->get_fullname(), 'shortname' => $this->shortname, 'color' => $this->color, - 'enabled' => $this->enabled ? 1:0, // Moodle's API uses int instead of bool. + 'enabled' => $this->enabled ? 1 : 0, // Moodle's API uses int instead of bool. ]; } @@ -219,12 +219,12 @@ public static function api_structure(): external_single_structure { return new external_single_structure( [ 'id' => new external_value(PARAM_INT, 'course ID'), - 'courseid' => new external_value(PARAM_INT, 'the moodle-internal ID of the course'), - 'userid' => new external_value(PARAM_INT, 'the user for whom these course settings are for'), - 'name' => new external_value(PARAM_TEXT, 'the full name of this course'), - 'shortname' => new external_value(PARAM_TEXT, 'the short name of this course for this user (maximum size: 5 chars)'), - 'color' => new external_value(PARAM_TEXT, 'the color for this course as #RRGGBB'), - 'enabled' => new external_value(PARAM_BOOL, 'whether the user wants to see this course'), + 'courseid' => new external_value(PARAM_INT, 'moodle-internal course ID'), + 'userid' => new external_value(PARAM_INT, 'The user for whom these course settings are for'), + 'name' => new external_value(PARAM_TEXT, 'Full name of this course'), + 'shortname' => new external_value(PARAM_TEXT, 'Short name of this course for this user (maximum size: 5 chars)'), + 'color' => new external_value(PARAM_TEXT, 'Color for this course as #RRGGBB'), + 'enabled' => new external_value(PARAM_BOOL, 'Whether the user wants to see this course'), ] ); } From 35fced3d60d2f2442a44b2c6af652a8bf6601abc Mon Sep 17 00:00:00 2001 From: Riedler Date: Fri, 23 Aug 2024 18:40:43 +0200 Subject: [PATCH 78/92] refactor: minor code improvement --- lbplanner/classes/helpers/slot_helper.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index ea14b8a7..524ee407 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -29,7 +29,6 @@ use DateTime; use DateTimeImmutable; use DateTimeInterface; -use external_api; use local_lbplanner\enums\WEEKDAY; use local_lbplanner\model\{slot, reservation, slot_filter}; @@ -207,8 +206,7 @@ public static function get_filters_for_slot(int $slotid): array { * @return slot[] the filtered slot array */ public static function filter_slots_for_user(array $allslots, mixed $user): array { - // TODO: replace this with helper function. - $mycourses = external_api::call_external_function('local_lbplanner_courses_get_all_courses', ['userid' => $user->id]); + $mycourses = course_helper::get_all_lbplanner_courses(); $mycourseids = []; foreach ($mycourses as $course) { array_push($mycourseids, $course->courseid); From dd0f452fcf96e356c70d82b2aa949c0775e4963e Mon Sep 17 00:00:00 2001 From: Riedler Date: Fri, 23 Aug 2024 18:44:38 +0200 Subject: [PATCH 79/92] fix: PHPDoc checker --- lbplanner/classes/model/course.php | 1 + lbplanner/services/modules/get_all_course_modules.php | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/lbplanner/classes/model/course.php b/lbplanner/classes/model/course.php index 917ce2c5..2f2b8688 100644 --- a/lbplanner/classes/model/course.php +++ b/lbplanner/classes/model/course.php @@ -85,6 +85,7 @@ public function __construct(int $id, int $courseid, int $userid, string $shortna /** * Takes data from DB and makes a new Course out of it * + * @param object $obj the DB object to get data from * @return object a representation of this course and its data * @throws \AssertionError */ diff --git a/lbplanner/services/modules/get_all_course_modules.php b/lbplanner/services/modules/get_all_course_modules.php index 746d7a25..7222f68a 100644 --- a/lbplanner/services/modules/get_all_course_modules.php +++ b/lbplanner/services/modules/get_all_course_modules.php @@ -52,7 +52,6 @@ public static function get_all_course_modules_parameters(): external_function_pa * Returns all the modules inside a course. * * @param int $courseid The ID of the course - * @param int $userid The ID of the user * @param bool $ekenabled whether or not to include ek modules * @return array the modules */ From 51586ce06aafdf15c3ff508e7d211935b25b1cc4 Mon Sep 17 00:00:00 2001 From: Riedler Date: Sat, 24 Aug 2024 23:03:30 +0200 Subject: [PATCH 80/92] feat: merge get_user and register_user amended to include fixed db/services.php --- lbplanner/db/services.php | 10 -- lbplanner/services/user/get_user.php | 93 ++++++++------ lbplanner/services/user/register_user.php | 149 ---------------------- 3 files changed, 56 insertions(+), 196 deletions(-) delete mode 100644 lbplanner/services/user/register_user.php diff --git a/lbplanner/db/services.php b/lbplanner/db/services.php index 8283e024..3c6bde75 100644 --- a/lbplanner/db/services.php +++ b/lbplanner/db/services.php @@ -44,15 +44,6 @@ 'capabilities' => 'local/lb_planner:student', 'ajax' => true, ], - 'local_lbplanner_user_register_user' => [ - 'classname' => 'local_lbplanner_services\user_register_user', - 'methodname' => 'register_user', - 'classpath' => 'local/lbplanner/services/user/register_user.php', - 'description' => 'Register a new user in the lbplanner app', - 'type' => 'write', - 'capabilities' => 'local/lb_planner:student', - 'ajax' => true, - ], 'local_lbplanner_user_update_user' => [ 'classname' => 'local_lbplanner_services\user_update_user', 'methodname' => 'update_user', @@ -348,7 +339,6 @@ 'functions' => [ 'local_lbplanner_user_get_user', 'local_lbplanner_user_get_all_users', - 'local_lbplanner_user_register_user', 'local_lbplanner_user_update_user', 'local_lbplanner_courses_get_all_courses', 'local_lbplanner_courses_update_course', diff --git a/lbplanner/services/user/get_user.php b/lbplanner/services/user/get_user.php index fee2bd95..39c87772 100644 --- a/lbplanner/services/user/get_user.php +++ b/lbplanner/services/user/get_user.php @@ -22,11 +22,12 @@ use external_function_parameters; use external_single_structure; use external_value; -use local_lbplanner\helpers\plan_helper; -use local_lbplanner\helpers\user_helper; use core_user; use moodle_exception; +use local_lbplanner\helpers\{user_helper, plan_helper, notifications_helper}; +use local_lbplanner\enums\{PLAN_EK, PLAN_ACCESS_TYPE, NOTIF_TRIGGER}; + /** * Get the data for a user. * @@ -58,58 +59,76 @@ public static function get_user_parameters(): external_function_parameters { /** * Gives back the data of a user. * Default: The user who calls this function - * @param int $userid (optional) gives back the data of the given user + * @param int $userid gives back the data of the given user * @throws coding_exception * @throws dml_exception * @throws moodle_exception * @return array The data of the user */ public static function get_user(int $userid): array { - global $USER, $CFG; - include_once("$CFG->dirroot/user/lib.php"); + global $USER, $DB; self::validate_parameters(self::get_user_parameters(), ['userid' => $userid]); + // Checks if the user is enrolled in LB Planner. if (!user_helper::check_user_exists($userid)) { - throw new moodle_exception('User does not exist'); + if (!user_helper::check_access($userid)) { + throw new moodle_exception('User does not exist & you don\'t have access to create it'); + } + + // Register user if not found. + $lbplanneruser = new \stdClass(); + $lbplanneruser->userid = $userid; + $lbplanneruser->language = 'en'; + $lbplanneruser->theme = 'default'; + $lbplanneruser->colorblindness = "none"; + $lbplanneruser->displaytaskcount = 1; + $DB->insert_record(user_helper::LB_PLANNER_USER_TABLE, $lbplanneruser); + + // Create empty plan for newly registered user. + $plan = new \stdClass(); + $plan->name = 'Plan for ' . $USER->username; + $plan->enableek = PLAN_EK::ENABLED; + $planid = $DB->insert_record(plan_helper::TABLE, $plan); + + // Set user as owner of new plan. + $planaccess = new \stdClass(); + $planaccess->userid = $userid; + $planaccess->accesstype = PLAN_ACCESS_TYPE::OWNER; + $planaccess->planid = $planid; + $DB->insert_record(plan_helper::ACCESS_TABLE, $planaccess); + + // Notify the FE that this user likely hasn't used LBP before. + notifications_helper::notify_user($userid, -1, NOTIF_TRIGGER::USER_REGISTERED); + } else { + $lbplanneruser = user_helper::get_user($userid); + $planid = plan_helper::get_plan_id($userid); } - $lbplanneruser = user_helper::get_user($userid); // Check if the user is allowed to get the data for this userid. - if (user_helper::check_access($userid)) { - $mdluser = (user_get_user_details($USER)); - return [ - 'userid' => $USER->id, - 'username' => $USER->username, - 'firstname' => $USER->firstname, - 'lastname' => $USER->lastname, - 'capabilities' => user_helper::get_user_capability_bitmask($userid), - 'theme' => $lbplanneruser->theme, - 'lang' => $lbplanneruser->language, - 'profileimageurl' => $mdluser['profileimageurl'], - 'planid' => plan_helper::get_plan_id($userid), - 'colorblindness' => $lbplanneruser->colorblindness, - 'displaytaskcount' => $lbplanneruser->displaytaskcount, - 'vintage' => $USER->address, - ]; + $access = user_helper::check_access($userid); + if ($USER->id == $userid) { + $mdluser = $USER; } else { $mdluser = core_user::get_user($userid, '*', MUST_EXIST); - return [ - 'userid' => $mdluser->id, - 'username' => $mdluser->username, - 'firstname' => $mdluser->firstname, - 'lastname' => $mdluser->lastname, - 'capabilities' => null, - 'theme' => null, - 'lang' => null, - 'profileimageurl' => user_helper::get_mdl_user_picture($userid), - 'planid' => null, - 'colorblindness' => null, - 'displaytaskcount' => null, - 'vintage' => $mdluser->address, - ]; } + + return [ + 'userid' => $mdluser->id, + 'username' => $mdluser->username, + 'firstname' => $mdluser->firstname, + 'lastname' => $mdluser->lastname, + 'theme' => $access ? $lbplanneruser->theme : null, + 'lang' => $access ? $lbplanneruser->language : null, + 'profileimageurl' => user_helper::get_mdl_user_picture($userid), + 'planid' => $access ? $planid : null, + 'colorblindness' => $access ? $lbplanneruser->colorblindness : null, + 'displaytaskcount' => $access ? $lbplanneruser->displaytaskcount : null, + 'capabilities' => $access ? user_helper::get_user_capability_bitmask($userid) : null, + 'vintage' => $mdluser->address, + ]; } + /** * Returns the data of a user. * @return external_single_structure diff --git a/lbplanner/services/user/register_user.php b/lbplanner/services/user/register_user.php deleted file mode 100644 index 67e0562f..00000000 --- a/lbplanner/services/user/register_user.php +++ /dev/null @@ -1,149 +0,0 @@ -. - -namespace local_lbplanner_services; - -use dml_exception; -use external_api; -use external_function_parameters; -use external_single_structure; -use external_value; -use invalid_parameter_exception; -use local_lbplanner\helpers\{user_helper, plan_helper, notifications_helper}; -use local_lbplanner\enums\{NOTIF_TRIGGER, PLAN_ACCESS_TYPE, PLAN_EK}; -use moodle_exception; -use stdClass; - -/** - * Register a new user in the lbplanner app. - * - * @package local_lbplanner - * @subpackage services_user - * @copyright 2024 necodeIT - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class user_register_user extends external_api { - /** - * Parameters for register_user - * @return external_function_parameters - */ - public static function register_user_parameters(): external_function_parameters { - return new external_function_parameters([ - 'lang' => new external_value( - PARAM_TEXT, - 'The language the user has selected', - VALUE_DEFAULT, - 'en', - NULL_NOT_ALLOWED - ), - 'theme' => new external_value( - PARAM_TEXT, - 'The theme the user has selected', - VALUE_DEFAULT, - 'Light', - NULL_NOT_ALLOWED), - 'ekenabled' => new external_value( - PARAM_INT, - 'If the user wants to have EK-Enabled', - VALUE_DEFAULT, - 0, - NULL_NOT_ALLOWED, - ), - ]); - } - - /** - * Registers the given user to the lbplanner DB - * @param string $lang language the user choose - * @param string $theme The theme the user has selected - * @throws dml_exception - * @throws moodle_exception - * @throws invalid_parameter_exception - */ - public static function register_user(string $lang, string $theme): array { - global $DB, $USER; - - self::validate_parameters( - self::register_user_parameters(), - ['lang' => $lang, 'theme' => $theme] - ); - $userid = $USER->id; - - user_helper::assert_access($userid); - - if (user_helper::check_user_exists($userid)) { - throw new moodle_exception('User already registered'); - } - - $lbplanneruser = new stdClass(); - $lbplanneruser->userid = $userid; - $lbplanneruser->language = $lang; - $lbplanneruser->theme = $theme; - $lbplanneruser->colorblindness = "none"; - $lbplanneruser->displaytaskcount = 1; - - $DB->insert_record(user_helper::LB_PLANNER_USER_TABLE, $lbplanneruser); - $plan = new stdClass(); - $plan->name = 'Plan for ' . $USER->username; - $plan->enableek = PLAN_EK::ENABLED; - - $planid = $DB->insert_record(plan_helper::TABLE, $plan); - - $planaccess = new stdClass(); - $planaccess->userid = $userid; - $planaccess->accesstype = PLAN_ACCESS_TYPE::OWNER; - $planaccess->planid = $planid; - - $DB->insert_record(plan_helper::ACCESS_TABLE, $planaccess); - - notifications_helper::notify_user($userid, -1, NOTIF_TRIGGER::USER_REGISTERED); - - return [ - 'userid' => $lbplanneruser->userid, - 'username' => $USER->username, - 'firstname' => $USER->firstname, - 'lastname' => $USER->lastname, - 'capabilities' => user_helper::get_user_capability_bitmask($userid), - 'theme' => $lbplanneruser->theme, - 'lang' => $lbplanneruser->language, - 'profileimageurl' => user_helper::get_mdl_user_picture($userid), - 'planid' => $planid, - 'colorblindness' => $lbplanneruser->colorblindness, - 'displaytaskcount' => $lbplanneruser->displaytaskcount, - ]; - } - /** - * Returns the data of a user. - * @return external_single_structure - */ - public static function register_user_returns(): external_single_structure { - return new external_single_structure( - [ - 'userid' => new external_value(PARAM_INT, 'The id of the user'), - 'username' => new external_value(PARAM_TEXT, 'The username of the user'), - 'firstname' => new external_value(PARAM_TEXT, 'The firstname of the user'), - 'lastname' => new external_value(PARAM_TEXT, 'The lastname of the user'), - 'capabilities' => new external_value(PARAM_INT, 'The capabilities of the user represented as a bitmask value'), - 'theme' => new external_value(PARAM_TEXT, 'The theme the user has selected'), - 'lang' => new external_value(PARAM_TEXT, 'The language the user has selected'), - 'profileimageurl' => new external_value(PARAM_URL, 'The url of the profile image'), - 'planid' => new external_value(PARAM_INT, 'The id of the plan the user is assigned to'), - 'colorblindness' => new external_value(PARAM_TEXT, 'The colorblindness of the user'), - 'displaytaskcount' => new external_value(PARAM_INT, 'If the user has the taskcount-enabled 1-yes 0-no'), - ] - ); - } -} From a2ca2f24311564cda3993388e63da208717132c3 Mon Sep 17 00:00:00 2001 From: Riedler Date: Sat, 24 Aug 2024 23:24:43 +0200 Subject: [PATCH 81/92] doc: fixed spelling mistake --- lbplanner/classes/model/course.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lbplanner/classes/model/course.php b/lbplanner/classes/model/course.php index 2f2b8688..21942e66 100644 --- a/lbplanner/classes/model/course.php +++ b/lbplanner/classes/model/course.php @@ -96,7 +96,7 @@ public static function from_db(object $obj): self { /** * Mark the object as freshly created and sets the new ID - * @param int $id the new ID after insertint into the DB + * @param int $id the new ID after inserting into the DB * @throws \AssertionError */ public function set_fresh(int $id) { From 462903e320a82d70b86de3e2f37c963825cd9e62 Mon Sep 17 00:00:00 2001 From: Riedler Date: Sun, 25 Aug 2024 02:39:10 +0200 Subject: [PATCH 82/92] refactor: user model & capability enums --- lbplanner/classes/enums/CAPABILITY.php | 66 ++++ lbplanner/classes/enums/CAPABILITY_FLAG.php | 66 ++++ lbplanner/classes/helpers/feedback_helper.php | 5 +- lbplanner/classes/helpers/plan_helper.php | 10 +- lbplanner/classes/helpers/user_helper.php | 109 ++---- lbplanner/classes/model/user.php | 333 ++++++++++++++++++ .../services/slots/get_student_slots.php | 3 +- lbplanner/services/user/get_all_users.php | 42 +-- lbplanner/services/user/get_user.php | 60 +--- lbplanner/services/user/update_user.php | 55 +-- 10 files changed, 543 insertions(+), 206 deletions(-) create mode 100644 lbplanner/classes/enums/CAPABILITY.php create mode 100644 lbplanner/classes/enums/CAPABILITY_FLAG.php create mode 100644 lbplanner/classes/model/user.php diff --git a/lbplanner/classes/enums/CAPABILITY.php b/lbplanner/classes/enums/CAPABILITY.php new file mode 100644 index 00000000..2c5bf865 --- /dev/null +++ b/lbplanner/classes/enums/CAPABILITY.php @@ -0,0 +1,66 @@ +. + +/** + * capability string + * + * @package local_lbplanner + * @subpackage enums + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\enums; + +// TODO: revert to native enums once we migrate to php8. + +use local_lbplanner\polyfill\Enum; +use local_lbplanner\enums\CAPABILITY_FLAG; + +/** + * Capabilities a user can have + */ +class CAPABILITY extends Enum { + /** + * Shortname of the admin CAPABILITY. + */ + const ADMIN = 'local/lb_planner:admin'; + + /** + * Shortname of the manager CAPABILITY. + */ + const MANAGER = 'local/lb_planner:manager'; + + /** + * Shortname of the teacher CAPABILITY. + */ + const TEACHER = 'local/lb_planner:teacher'; + + /** + * Shortname of the student CAPABILITY. + */ + const STUDENT = 'local/lb_planner:student'; + + /** + * Matches a capability string to its bitmappable flag + * @param string $str the capability string + * @return int the bitmappable flag + * @link CAPABILITY_FLAG + */ + public static function to_capability(string $str): int { + return CAPABILITY_FLAG::{self::name_from($str)}; + } +} diff --git a/lbplanner/classes/enums/CAPABILITY_FLAG.php b/lbplanner/classes/enums/CAPABILITY_FLAG.php new file mode 100644 index 00000000..6f4aad54 --- /dev/null +++ b/lbplanner/classes/enums/CAPABILITY_FLAG.php @@ -0,0 +1,66 @@ +. + +/** + * capability string + * + * @package local_lbplanner + * @subpackage enums + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\enums; + +// TODO: revert to native enums once we migrate to php8. + +use local_lbplanner\polyfill\Enum; +use local_lbplanner\enums\CAPABILITY; + +/** + * Bitmappable flags for capabilities a user can have + */ +class CAPABILITY_FLAG extends Enum { + /** + * Flag of the admin CAPABILITY. + */ + const ADMIN = 1; + + /** + * Flag of the manager CAPABILITY. + */ + const MANAGER = 2; + + /** + * Flag of the teacher CAPABILITY. + */ + const TEACHER = 4; + + /** + * Flag of the student CAPABILITY. + */ + const STUDENT = 8; + + /** + * matches a flag to its capability string + * @param int $num the bitmappable flag + * @return string the capability string + * @link CAPABILITY + */ + public static function to_capability(int $num): string { + return CAPABILITY::{self::name_from($num)}; + } +} diff --git a/lbplanner/classes/helpers/feedback_helper.php b/lbplanner/classes/helpers/feedback_helper.php index 9322864e..a6931134 100644 --- a/lbplanner/classes/helpers/feedback_helper.php +++ b/lbplanner/classes/helpers/feedback_helper.php @@ -19,6 +19,7 @@ use external_function_parameters; use external_single_structure; use external_value; +use local_lbplanner\enums\CAPABILITY; use stdClass; use local_lbplanner\helpers\user_helper; @@ -89,8 +90,8 @@ public static function get_feedback(int $feedbackid): stdClass { * @throws \moodle_exception when the user has no access */ public static function assert_admin_access() { - if (!has_capability(user_helper::CAPABILITY_ADMIN, \context_system::instance()) - && !has_capability(user_helper::CAPABILITY_MANAGER, \context_system::instance()) + if (!has_capability(CAPABILITY::ADMIN, \context_system::instance()) + && !has_capability(CAPABILITY::MANAGER, \context_system::instance()) ) { throw new \moodle_exception('Acces denied'); } diff --git a/lbplanner/classes/helpers/plan_helper.php b/lbplanner/classes/helpers/plan_helper.php index ffb9ad10..45d6d293 100644 --- a/lbplanner/classes/helpers/plan_helper.php +++ b/lbplanner/classes/helpers/plan_helper.php @@ -226,17 +226,15 @@ public static function plan_structure(): external_single_structure { * Copies the given plan to the given user. * * @param int $planid The id of the plan. - * @param int $userid The id of the user. + * @param string $username Username of the user. * * @return integer The id of the new copy of the plan. */ - public static function copy_plan(int $planid, int $userid): int { + public static function copy_plan(int $planid, string $username): int { global $DB; - $user = user_helper::get_mdl_user_info($userid); // TODO: get_mdl_user_info doesn't exist anymore. - $plan = $DB->get_record(self::TABLE, ['id' => $planid]); - $plan->name = $plan->name . ' (' . $user->username . ')'; + $plan->name = $plan->name . ' (' . $username . ')'; $plan->id = null; $deadlines = self::get_deadlines($planid); @@ -277,7 +275,7 @@ public static function remove_user(int $planid, int $userid, int $removeuserid): throw new \moodle_exception('Cannot remove owner'); } - $newplanid = self::copy_plan($planid, $removeuserid); + $newplanid = self::copy_plan($planid, user_helper::get_mdluser($removeuserid)->username); $oldaccess = $DB->get_record( self::ACCESS_TABLE, diff --git a/lbplanner/classes/helpers/user_helper.php b/lbplanner/classes/helpers/user_helper.php index 23305e2c..dd87612a 100644 --- a/lbplanner/classes/helpers/user_helper.php +++ b/lbplanner/classes/helpers/user_helper.php @@ -24,6 +24,9 @@ use user_picture; use core_user; +use local_lbplanner\enums\{CAPABILITY, CAPABILITY_FLAG}; +use local_lbplanner\model\user; + /** * Provides helper methods for user related stuff. * @@ -34,37 +37,6 @@ */ class user_helper { - /** - * Shortname of the admin CAPABILITY. - */ - const CAPABILITY_ADMIN = 'local/lb_planner:admin'; - - /** - * Shortname of the manager CAPABILITY. - */ - const CAPABILITY_MANAGER = 'local/lb_planner:manager'; - - /** - * Shortname of the teacher CAPABILITY. - */ - const CAPABILITY_TEACHER = 'local/lb_planner:teacher'; - - /** - * Shortname of the student CAPABILITY. - */ - const CAPABILITY_STUDENT = 'local/lb_planner:student'; - - /** - * Maps CAPABILITY shortnames to their corresponding enum value. - */ - const CAPABILITY_ENUMS - = [ - self::CAPABILITY_ADMIN => 1, - self::CAPABILITY_MANAGER => 2, - self::CAPABILITY_TEACHER => 4, - self::CAPABILITY_STUDENT => 8, - ]; - /** * Name of the user database */ @@ -79,7 +51,7 @@ class user_helper { */ public static function check_access(int $userid): bool { global $USER; - return $USER->id == $userid; + return ((int) $USER->id) === $userid; } /** @@ -92,8 +64,7 @@ public static function check_access(int $userid): bool { * @throws moodle_exception */ public static function assert_access(int $userid): void { - global $USER; - if ($USER->id != $userid) { + if (!self::check_access($userid)) { throw new moodle_exception('Access denied'); } } @@ -108,8 +79,11 @@ public static function assert_access(int $userid): void { * @throws dml_exception */ public static function is_admin(int $userid): bool { + /** + * @var \context $context + */ $context = context_system::instance(); - return has_capability(self::CAPABILITY_ADMIN, $context, $userid, false); + return has_capability(CAPABILITY::ADMIN, $context, $userid, false); } /** @@ -140,18 +114,21 @@ public static function is_admin(int $userid): bool { */ public static function get_user_capability_bitmask(int $userid): int { $capabilities = 0; + /** + * @var \context $context + */ $context = context_system::instance(); - if (has_capability(self::CAPABILITY_ADMIN, $context, $userid, false)) { - $capabilities += self::CAPABILITY_ENUMS[self::CAPABILITY_ADMIN]; + if (has_capability(CAPABILITY::ADMIN, $context, $userid, false)) { + $capabilities += CAPABILITY_FLAG::ADMIN; } - if (has_capability(self::CAPABILITY_MANAGER, $context, $userid, false)) { - $capabilities += self::CAPABILITY_ENUMS[self::CAPABILITY_MANAGER]; + if (has_capability(CAPABILITY::MANAGER, $context, $userid, false)) { + $capabilities += CAPABILITY_FLAG::MANAGER; } - if (has_capability(self::CAPABILITY_TEACHER, $context, $userid, false)) { - $capabilities += self::CAPABILITY_ENUMS[self::CAPABILITY_TEACHER]; + if (has_capability(CAPABILITY::TEACHER, $context, $userid, false)) { + $capabilities += CAPABILITY_FLAG::TEACHER; } - if (has_capability(self::CAPABILITY_STUDENT, $context, $userid, false)) { - $capabilities += self::CAPABILITY_ENUMS[self::CAPABILITY_STUDENT]; + if (has_capability(CAPABILITY::STUDENT, $context, $userid, false)) { + $capabilities += CAPABILITY_FLAG::STUDENT; } return $capabilities; } @@ -171,50 +148,32 @@ public static function check_user_exists(int $userid): bool { /** * Retrieves the user with the given id. - * The returned object contains the following properties: - * ```php - * $user->id // The lbplanner id of the user. - * $user->userid // The moodle id of the user. - * $user->theme // The name of the theme the user has set for the app. - * $user->language // The language the user has set for the app. - * ``` * * @param int $userid The id of the user to retrieve. * - * @return stdClass The user with the given id. + * @return user The user with the given id. * @throws dml_exception */ - public static function get_user(int $userid): stdClass { + public static function get_user(int $userid): user { global $DB; - return $DB->get_record(self::LB_PLANNER_USER_TABLE, ['userid' => $userid], '*', MUST_EXIST); - } - - /** - * Retrieves the full name of the user with the given id. - * - * @return string The full name of the user with the given id. - * @deprecated not in use - */ - public static function get_complete_name(): string { - global $USER; - return $USER->firstname . ' ' . $USER->lastname; + return user::from_db($DB->get_record(self::LB_PLANNER_USER_TABLE, ['userid' => $userid], '*', MUST_EXIST)); } /** - * This Function is used to get the user picture of a user. + * Retrieves the user with the given id. * - * @param int $userid The id of the user to retrieve the picture for. + * @param int $userid The id of the user to retrieve. * - * @return string The url of the user picture. + * @return \stdClass The user with the given id. * @throws dml_exception - * @throws coding_exception */ - public static function get_mdl_user_picture(int $userid): string { - global $PAGE; - $mdluser = core_user::get_user($userid, '*', MUST_EXIST); - $userpicture = new user_picture($mdluser); - $userpicture->size = 1; // Size f1. - return $userpicture->get_url($PAGE)->out(false); + public static function get_mdluser(int $userid): \stdClass { + global $USER; + if ($userid === ((int) $USER->id)) { + $data = $USER; + } else { + $data = core_user::get_user($userid, '*', MUST_EXIST); + } + return $data; } - } diff --git a/lbplanner/classes/model/user.php b/lbplanner/classes/model/user.php new file mode 100644 index 00000000..822c5de4 --- /dev/null +++ b/lbplanner/classes/model/user.php @@ -0,0 +1,333 @@ +. + +/** + * Model for a course + * + * @package local_lbplanner + * @subpackage helpers + * @copyright 2024 NecodeIT + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_lbplanner\model; + +use coding_exception; +use core_user; +use external_single_structure; +use external_value; +use local_lbplanner\helpers\plan_helper; +use local_lbplanner\helpers\user_helper; +use user_picture; + +/** + * Model class for course + */ +class user { + /** + * @var int $lbpid our userid + */ + private int $lbpid; + + /** + * @var int $mdlid moodle's userid + */ + public int $mdlid; + + /** + * @var string $theme selected theme + */ + public string $theme; + + /** + * @var string $lang user language + */ + public string $lang; + + /** + * @var string $colorblindness the kind of color blindness of a user + */ + public string $colorblindness; + + /** + * @var int $displaytaskcount The display task count the user has selected in the app. + */ + public int $displaytaskcount; + + /** + * @var ?\stdClass $mdluser the cached moodle user + */ + private ?\stdClass $mdluser; + + /** + * @var ?string $pfp the cached pfp + */ + private ?string $pfp; + + /** + * @var ?int $planid the cached planid + */ + private ?int $planid; + + /** + * Constructs a new course + */ + public function __construct(int $lbpid, int $mdlid, string $theme, string $lang, string $colorblindness, int $displaytaskcount) { + global $USER; + $this->lbpid = $lbpid; + $this->mdlid = $mdlid; + $this->set_theme($theme); + $this->set_lang($lang); + $this->set_colorblindness($colorblindness); + $this->set_displaytaskcount($displaytaskcount); + $this->planid = null; + $this->pfp = null; + + if ($mdlid === (int) $USER->id) { + $this->mdluser = $USER; + } else { + $this->mdluser = null; + } + } + + /** + * Takes data from DB and makes a new user obj out of it + * + * @param object $obj the DB object to get data from + * @return user a representation of this user and its data + */ + public static function from_db(object $obj): self { + return new self($obj->id, $obj->userid, $obj->theme, $obj->language, $obj->colorblindness, $obj->displaytaskcount); + } + + /** + * Mark the object as freshly created and sets the new ID + * @param int $lbpid the new ID after inserting into the DB + * @throws \AssertionError + */ + public function set_fresh(int $lbpid): void { + assert($this->lbpid === 0); + assert($lbpid !== 0); + $this->lbpid = $lbpid; + } + + /** + * Sets display task count + * @param int $count display task count + * @throws \coding_exception if $count <= 0 + */ + public function set_displaytaskcount(int $count): void { + if ($count <= 0) { + throw new \coding_exception('User\'s Display Task Count cannot be <= 0'); + } + $this->displaytaskcount = $count; + } + + /** + * Sets colorblindness + * @param string $cbn colorblindness + */ + public function set_colorblindness(string $cbn): void { + $this->colorblindness = $cbn; + } + + /** + * Sets user language + * @param string $lang language + * @throws \coding_exception if $lang isn't ISO 639-1 conformant + */ + public function set_lang(string $lang): void { + if (preg_match('/^[a-z]{2}$/', $lang) !== 1) { + throw new \coding_exception('Incorrect language format - must be ISO 639-1, e.g. en or de'); + } + $this->lang = $lang; + } + + /** + * Sets user theme + * @param string $theme theme + */ + public function set_theme(string $theme): void { + $this->theme = $theme; + } + + /** + * sets the associated moodle user (for caching) + * @param \stdClass $mdluser + */ + public function set_mdluser(\stdClass $mdluser): void { + global $USER; + if ($this->mdluser !== null){ + if ($this->mdluser->id !== $USER->id) { + throw new \coding_exception('tried to set cached mdluser twice'); + } + } + $this->mdluser = $mdluser; + } + + /** + * gets the associated moodle user + * @return \stdClass mdluser + */ + public function get_mdluser(): \stdClass { + if ($this->mdluser === null) + $this->mdluser = user_helper::get_mdluser($this->mdlid); + + return $this->mdluser; + } + + /** + * sets the associated plan ID (for caching) + * @param int $planid + */ + public function set_planid(int $planid): void { + if ($this->planid !== null){ + throw new \coding_exception('tried to set cached planid twice'); + } + $this->planid = $planid; + } + + /** + * gets the associated plan ID + * @return int planid + */ + public function get_planid(): int { + if ($this->planid === null) + $this->planid = plan_helper::get_plan_id($this->mdlid); + + return $this->planid; + } + + /** + * gets the associated profile picture + * @return string pfp + */ + public function get_pfp(): string { + if ($this->pfp === null) { + global $PAGE; + $userpicture = new user_picture($this->get_mdluser()); + $userpicture->size = 1; // Size f1. + $this->pfp = $userpicture->get_url($PAGE)->out(false); + } + + return $this->pfp; + } + + /** + * Prepares data for the DB endpoint. + * doesn't set ID if it's 0 + * + * @return object a representation of this course and its data + */ + public function prepare_for_db(): object { + $obj = new \stdClass(); + + $obj->userid = $this->mdlid; + $obj->theme = $this->theme; + $obj->language = $this->lang; + $obj->colorblindness = $this->colorblindness; + $obj->displaytaskcount = $this->displaytaskcount; + + if ($this->lbpid !== 0) { + $obj->id = $this->lbpid; + } + + return $obj; + } + + /** + * Prepares shortened data for the API endpoint. + * + * @return array a shortened representation of this user and its data + */ + public function prepare_for_api_short(): array { + $mdluser = $this->get_mdluser(); + return [ + 'userid' => $this->mdlid, + 'username' => $mdluser->username, + 'firstname' => $mdluser->firstname, + 'lastname' => $mdluser->lastname, + 'profileimageurl' => $this->get_pfp(), + 'vintage' => $mdluser->address, + ]; + } + + /** + * Returns the shortened data structure of a user for the API. + * + * @return external_single_structure The shortened data structure of a user for the API. + */ + public static function api_structure_short(): external_single_structure { + return new external_single_structure( + [ + 'userid' => new external_value(PARAM_INT, 'The id of the user'), + 'username' => new external_value(PARAM_TEXT, 'The username of the user'), + 'firstname' => new external_value(PARAM_TEXT, 'The firstname of the user'), + 'lastname' => new external_value(PARAM_TEXT, 'The lastname of the user'), + 'profileimageurl' => new external_value(PARAM_URL, 'The url of the profile image'), + 'vintage' => new external_value(PARAM_TEXT, 'The vintage of the user'), + ] + ); + } + + /** + * Prepares full data for the API endpoint. + * + * @param bool $access whether the full-access data should be prepared + * @return array a full representation of this user and its data + */ + public function prepare_for_api(): array { + $mdluser = $this->get_mdluser(); + return [ + 'userid' => $mdluser->id, + 'username' => $mdluser->username, + 'firstname' => $mdluser->firstname, + 'lastname' => $mdluser->lastname, + 'theme' => $this->theme, + 'lang' => $this->lang, + 'profileimageurl' => $this->get_pfp(), + 'planid' => $this->get_planid(), + 'colorblindness' => $this->colorblindness, + 'displaytaskcount' => $this->displaytaskcount, + 'capabilities' => user_helper::get_user_capability_bitmask($this->mdlid), + 'vintage' => $mdluser->address, + ]; + } + + /** + * Returns the full data structure of a user for the API. + * + * @return external_single_structure The full data structure of a user for the API. + */ + public static function api_structure(): external_single_structure { + return new external_single_structure( + [ + 'userid' => new external_value(PARAM_INT, 'The id of the user'), + 'username' => new external_value(PARAM_TEXT, 'The username of the user'), + 'firstname' => new external_value(PARAM_TEXT, 'The firstname of the user'), + 'lastname' => new external_value(PARAM_TEXT, 'The lastname of the user'), + 'theme' => new external_value(PARAM_TEXT, 'The theme the user has selected', VALUE_DEFAULT), + 'lang' => new external_value(PARAM_TEXT, 'The language the user has selected'), + 'profileimageurl' => new external_value(PARAM_URL, 'The url of the profile image'), + 'planid' => new external_value(PARAM_INT, 'The id of the plan the user is assigned to'), + 'colorblindness' => new external_value(PARAM_TEXT, 'The colorblindness of the user'), + 'displaytaskcount' => new external_value(PARAM_INT, 'If the user has the taskcount-enabled 1-yes 0-no'), + 'capabilities' => new external_value(PARAM_INT, 'The capabilities of the user represented as a bitmask value'), + 'vintage' => new external_value(PARAM_TEXT, 'The vintage of the user'), + ] + ); + } +} diff --git a/lbplanner/services/slots/get_student_slots.php b/lbplanner/services/slots/get_student_slots.php index 647260a8..7932f62f 100644 --- a/lbplanner/services/slots/get_student_slots.php +++ b/lbplanner/services/slots/get_student_slots.php @@ -21,6 +21,7 @@ use external_multiple_structure; use external_value; use local_lbplanner\helpers\slot_helper; +use local_lbplanner\helpers\user_helper; use local_lbplanner\model\slot; /** @@ -56,7 +57,7 @@ public static function get_student_slots(int $userid): array { $superslots = slot_helper::get_supervisor_slots($USER->id); - $myslots = slot_helper::filter_slots_for_user($superslots, $userid); + $myslots = slot_helper::filter_slots_for_user($superslots, user_helper::get_mdluser($userid)); $returnslots = slot_helper::filter_slots_for_time($myslots, slot_helper::RESERVATION_RANGE_SUPERVISOR); diff --git a/lbplanner/services/user/get_all_users.php b/lbplanner/services/user/get_all_users.php index 9ab5bf8d..69ce75b6 100644 --- a/lbplanner/services/user/get_all_users.php +++ b/lbplanner/services/user/get_all_users.php @@ -16,17 +16,17 @@ namespace local_lbplanner_services; -use core_user; use dml_exception; use external_api; use external_function_parameters; use external_multiple_structure; -use external_single_structure; use external_value; use invalid_parameter_exception; -use local_lbplanner\helpers\user_helper; use moodle_exception; +use local_lbplanner\helpers\user_helper; +use local_lbplanner\model\user; + /** * Gets all users registered by the lbplanner app. * @@ -64,25 +64,16 @@ public static function get_all_users(string $vintage): array { $users = $DB->get_records(user_helper::LB_PLANNER_USER_TABLE); - $result = []; + $results = []; - foreach ($users as $user) { - $mdluser = core_user::get_user($user->userid, '*', MUST_EXIST); - $result[] = [ - 'userid' => $user->userid, - 'username' => $mdluser->username, - 'firstname' => $mdluser->firstname, - 'lastname' => $mdluser->lastname, - 'profileimageurl' => user_helper::get_mdl_user_picture($mdluser->id), - 'vintage' => $mdluser->address, - ]; + foreach ($users as $userdata) { + $user = user::from_db($userdata); + if ($vintage === null || $vintage == $user->get_mdluser()->vintage) { + array_push($results, $user->prepare_for_api_short()); + } } - if ($vintage != null) { - $result = array_filter($result, function ($user) use ($vintage) { - return $user['vintage'] == $vintage; - }); - } - return $result; + + return $results; } /** @@ -91,16 +82,7 @@ public static function get_all_users(string $vintage): array { */ public static function get_all_users_returns(): external_multiple_structure { return new external_multiple_structure( - new external_single_structure( - [ - 'userid' => new external_value(PARAM_INT, 'The id of the user'), - 'username' => new external_value(PARAM_TEXT, 'The username of the user'), - 'firstname' => new external_value(PARAM_TEXT, 'The firstname of the user'), - 'lastname' => new external_value(PARAM_TEXT, 'The lastname of the user'), - 'profileimageurl' => new external_value(PARAM_URL, 'The url of the profile image'), - 'vintage' => new external_value(PARAM_TEXT, 'The vintage of the user'), - ] - ) + user::api_structure_short() ); } } diff --git a/lbplanner/services/user/get_user.php b/lbplanner/services/user/get_user.php index 39c87772..b9abded2 100644 --- a/lbplanner/services/user/get_user.php +++ b/lbplanner/services/user/get_user.php @@ -27,6 +27,7 @@ use local_lbplanner\helpers\{user_helper, plan_helper, notifications_helper}; use local_lbplanner\enums\{PLAN_EK, PLAN_ACCESS_TYPE, NOTIF_TRIGGER}; +use local_lbplanner\model\user; /** * Get the data for a user. @@ -70,26 +71,22 @@ public static function get_user(int $userid): array { self::validate_parameters(self::get_user_parameters(), ['userid' => $userid]); + // Check if the user is allowed to get the data for this userid. + user_helper::assert_access($userid); + // Checks if the user is enrolled in LB Planner. if (!user_helper::check_user_exists($userid)) { - if (!user_helper::check_access($userid)) { - throw new moodle_exception('User does not exist & you don\'t have access to create it'); - } - // Register user if not found. - $lbplanneruser = new \stdClass(); - $lbplanneruser->userid = $userid; - $lbplanneruser->language = 'en'; - $lbplanneruser->theme = 'default'; - $lbplanneruser->colorblindness = "none"; - $lbplanneruser->displaytaskcount = 1; - $DB->insert_record(user_helper::LB_PLANNER_USER_TABLE, $lbplanneruser); + $lbplanneruser = new user(0, $userid, 'default', 'en', 'none', 1); + $lbpid = $DB->insert_record(user_helper::LB_PLANNER_USER_TABLE, $lbplanneruser->prepare_for_db()); + $lbplanneruser->set_fresh($lbpid); // Create empty plan for newly registered user. $plan = new \stdClass(); $plan->name = 'Plan for ' . $USER->username; $plan->enableek = PLAN_EK::ENABLED; $planid = $DB->insert_record(plan_helper::TABLE, $plan); + $lbplanneruser->set_planid($planid); // Set user as owner of new plan. $planaccess = new \stdClass(); @@ -102,31 +99,9 @@ public static function get_user(int $userid): array { notifications_helper::notify_user($userid, -1, NOTIF_TRIGGER::USER_REGISTERED); } else { $lbplanneruser = user_helper::get_user($userid); - $planid = plan_helper::get_plan_id($userid); - } - - // Check if the user is allowed to get the data for this userid. - $access = user_helper::check_access($userid); - if ($USER->id == $userid) { - $mdluser = $USER; - } else { - $mdluser = core_user::get_user($userid, '*', MUST_EXIST); } - return [ - 'userid' => $mdluser->id, - 'username' => $mdluser->username, - 'firstname' => $mdluser->firstname, - 'lastname' => $mdluser->lastname, - 'theme' => $access ? $lbplanneruser->theme : null, - 'lang' => $access ? $lbplanneruser->language : null, - 'profileimageurl' => user_helper::get_mdl_user_picture($userid), - 'planid' => $access ? $planid : null, - 'colorblindness' => $access ? $lbplanneruser->colorblindness : null, - 'displaytaskcount' => $access ? $lbplanneruser->displaytaskcount : null, - 'capabilities' => $access ? user_helper::get_user_capability_bitmask($userid) : null, - 'vintage' => $mdluser->address, - ]; + return $lbplanneruser->prepare_for_api(); } /** @@ -134,21 +109,6 @@ public static function get_user(int $userid): array { * @return external_single_structure */ public static function get_user_returns(): external_single_structure { - return new external_single_structure( - [ - 'userid' => new external_value(PARAM_INT, 'The id of the user'), - 'username' => new external_value(PARAM_TEXT, 'The username of the user'), - 'firstname' => new external_value(PARAM_TEXT, 'The firstname of the user'), - 'lastname' => new external_value(PARAM_TEXT, 'The lastname of the user'), - 'theme' => new external_value(PARAM_TEXT, 'The theme the user has selected'), - 'lang' => new external_value(PARAM_TEXT, 'The language the user has selected'), - 'profileimageurl' => new external_value(PARAM_URL, 'The url of the profile image'), - 'planid' => new external_value(PARAM_INT, 'The id of the plan the user is assigned to'), - 'colorblindness' => new external_value(PARAM_TEXT, 'The colorblindness of the user'), - 'displaytaskcount' => new external_value(PARAM_INT, 'If the user has the taskcount-enabled 1-yes 0-no'), - 'capabilities' => new external_value(PARAM_INT, 'The capabilities of the user represented as a bitmask value'), - 'vintage' => new external_value(PARAM_TEXT, 'The vintage of the user'), - ] - ); + return user::api_structure(); } } diff --git a/lbplanner/services/user/update_user.php b/lbplanner/services/user/update_user.php index 1a2ae9d8..cb9247e6 100644 --- a/lbplanner/services/user/update_user.php +++ b/lbplanner/services/user/update_user.php @@ -22,10 +22,11 @@ use external_single_structure; use external_value; use invalid_parameter_exception; -use local_lbplanner\helpers\user_helper; -use local_lbplanner\helpers\plan_helper; use moodle_exception; +use local_lbplanner\helpers\{plan_helper, user_helper}; +use local_lbplanner\model\user; + /** * Update the data for a user. * @@ -79,65 +80,35 @@ public static function update_user($lang, $theme, $colorblindness, $displaytaskc 'displaytaskcount' => $displaytaskcount, ] ); - $userid = $USER->id; - user_helper::assert_access($userid); + user_helper::assert_access($USER->id); // Look if User-Id is in the DB. - if (!user_helper::check_user_exists($userid)) { + if (!user_helper::check_user_exists($USER->id)) { throw new moodle_exception('User does not exist'); } - $user = user_helper::get_user($userid); + $user = user_helper::get_user($USER->id); if ($lang !== null) { - $user->language = $lang; + $user->set_lang($lang); } if ($colorblindness !== null) { - $user->colorblindness = $colorblindness; + $user->set_colorblindness($colorblindness); } if ($theme !== null) { - $user->theme = $theme; + $user->set_theme($theme); } if ($displaytaskcount !== null) { - $user->displaytaskcount = $displaytaskcount; + $user->set_displaytaskcount($displaytaskcount); } - $DB->update_record(user_helper::LB_PLANNER_USER_TABLE, $user); - - return [ - 'userid' => $userid, - 'lang' => $user->language, - 'theme' => $user->theme, - 'capabilities' => user_helper::get_user_capability_bitmask($userid), - 'username' => $USER->username, - 'firstname' => $USER->firstname, - 'lastname' => $USER->lastname, - 'profileimageurl' => user_helper::get_mdl_user_picture($userid), - 'planid' => plan_helper::get_plan_id($userid), - 'colorblindness' => $user->colorblindness, - 'displaytaskcount' => $user->displaytaskcount, - 'vintage' => $USER->address, + $DB->update_record(user_helper::LB_PLANNER_USER_TABLE, $user->prepare_for_db()); - ]; + return $user->prepare_for_api(); } /** * Returns the data of a user. * @return external_single_structure */ public static function update_user_returns(): external_single_structure { - return new external_single_structure( - [ - 'userid' => new external_value(PARAM_INT, 'The id of the user'), - 'username' => new external_value(PARAM_TEXT, 'The username of the user'), - 'firstname' => new external_value(PARAM_TEXT, 'The firstname of the user'), - 'lastname' => new external_value(PARAM_TEXT, 'The lastname of the user'), - 'capabilities' => new external_value(PARAM_INT, 'The capabilities of the user represented as a bitmask value'), - 'theme' => new external_value(PARAM_TEXT, 'The theme the user has selected'), - 'lang' => new external_value(PARAM_TEXT, 'The language the user has selected'), - 'profileimageurl' => new external_value(PARAM_URL, 'The url of the profile image'), - 'planid' => new external_value(PARAM_INT, 'The id of the plan the user is assigned to'), - 'colorblindness' => new external_value(PARAM_TEXT, 'The colorblindness the user has selected'), - 'displaytaskcount' => new external_value(PARAM_INT, 'If the user has the taskcount-enabled 1-yes 0-no'), - 'vintage' => new external_value(PARAM_TEXT, 'The vintage of the user'), - ] - ); + return user::api_structure(); } } From 32f7a50eb5861fa2d7db9cd79571e7c94967fafd Mon Sep 17 00:00:00 2001 From: Riedler Date: Sun, 25 Aug 2024 02:40:04 +0200 Subject: [PATCH 83/92] fix: various slot-related functions juggling objects incorrectly --- lbplanner/classes/helpers/slot_helper.php | 2 +- lbplanner/services/slots/get_my_slots.php | 2 +- lbplanner/services/slots/get_student_slots.php | 2 +- lbplanner/services/slots/get_supervisor_slots.php | 4 +++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 524ee407..d094f7cb 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -247,7 +247,7 @@ public static function filter_slots_for_time(array $allslots, int $range): array $slotdatetime = self::calculate_slot_datetime($slot, $now); if ($now->diff($slotdatetime)->days <= $range) { - array_push($slots, $slot->prepare_for_api()); + array_push($slots, $slot); } } return $slots; diff --git a/lbplanner/services/slots/get_my_slots.php b/lbplanner/services/slots/get_my_slots.php index 00ef28b4..e50f4206 100644 --- a/lbplanner/services/slots/get_my_slots.php +++ b/lbplanner/services/slots/get_my_slots.php @@ -52,7 +52,7 @@ public static function get_my_slots(): array { $returnslots = slot_helper::filter_slots_for_time($myslots, slot_helper::RESERVATION_RANGE_USER); - return $returnslots; + return array_map(fn(slot $slot) => $slot->prepare_for_api(), $returnslots); } /** diff --git a/lbplanner/services/slots/get_student_slots.php b/lbplanner/services/slots/get_student_slots.php index 7932f62f..c423196a 100644 --- a/lbplanner/services/slots/get_student_slots.php +++ b/lbplanner/services/slots/get_student_slots.php @@ -61,7 +61,7 @@ public static function get_student_slots(int $userid): array { $returnslots = slot_helper::filter_slots_for_time($myslots, slot_helper::RESERVATION_RANGE_SUPERVISOR); - return $returnslots; + return array_map(fn(slot $slot) => $slot->prepare_for_api(), $returnslots); } /** diff --git a/lbplanner/services/slots/get_supervisor_slots.php b/lbplanner/services/slots/get_supervisor_slots.php index 59cdc753..20278673 100644 --- a/lbplanner/services/slots/get_supervisor_slots.php +++ b/lbplanner/services/slots/get_supervisor_slots.php @@ -45,7 +45,9 @@ public static function get_supervisor_slots_parameters(): external_function_para public static function get_supervisor_slots(): array { global $USER; - return slot_helper::get_supervisor_slots($USER->id); + $slots = slot_helper::get_supervisor_slots($USER->id); + + return array_map(fn(slot $slot) => $slot->prepare_for_api(), $slots); } /** From 6e0503f8151e8af842ebf155626518bef7720777 Mon Sep 17 00:00:00 2001 From: Riedler Date: Sun, 25 Aug 2024 02:40:37 +0200 Subject: [PATCH 84/92] internal: added various todo comments where necessary --- lbplanner/classes/helpers/plan_helper.php | 4 +++- lbplanner/classes/helpers/slot_helper.php | 1 + lbplanner/services/plan/accept_invite.php | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lbplanner/classes/helpers/plan_helper.php b/lbplanner/classes/helpers/plan_helper.php index 45d6d293..63b803b6 100644 --- a/lbplanner/classes/helpers/plan_helper.php +++ b/lbplanner/classes/helpers/plan_helper.php @@ -258,7 +258,7 @@ public static function copy_plan(int $planid, string $username): int { * @return int The ID of the new plan for the removed user */ public static function remove_user(int $planid, int $userid, int $removeuserid): int { - global $DB; + global $DB; // TODO: use global user object. if (self::get_owner($planid) != $userid) { throw new \moodle_exception('Access denied'); } @@ -292,6 +292,7 @@ public static function remove_user(int $planid, int $userid, int $removeuserid): /** * Get all invites that have been sent by the user. + * TODO: move to notifications_helper * * @param int $userid ID of the sender * @@ -305,6 +306,7 @@ public static function get_invites_send(int $userid): array { /** * Get all invites that have been received by the user. + * TODO: move to notifications_helper * * @param int $userid ID of the receiver * diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index d094f7cb..16a52cbd 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -201,6 +201,7 @@ public static function get_filters_for_slot(int $slotid): array { /** * Filters an array of slots for the slots that the user can theoretically reserve * NOTE: not taking into account time or fullness, only filters i.e. users' class and courses + * TODO: replace $user with $vintage * @param slot[] $allslots the slots to filter * @param mixed $user a user object - e.g. $USER or a user object from the database * @return slot[] the filtered slot array diff --git a/lbplanner/services/plan/accept_invite.php b/lbplanner/services/plan/accept_invite.php index e3c8893c..58b80083 100644 --- a/lbplanner/services/plan/accept_invite.php +++ b/lbplanner/services/plan/accept_invite.php @@ -93,6 +93,7 @@ public static function accept_invite(int $inviteid) { ]); } } + // TODO: replace with helper function self::call_external_function('local_lbplanner_plan_clear_plan', [ 'planid' => $oldplanid, 'userid' => $USER->id, From 9a45072bbbd9c37d424aba5fd1792f130a03e6ad Mon Sep 17 00:00:00 2001 From: Riedler Date: Sun, 25 Aug 2024 02:45:26 +0200 Subject: [PATCH 85/92] fix: incorrect api structure in user --- lbplanner/classes/model/user.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lbplanner/classes/model/user.php b/lbplanner/classes/model/user.php index 822c5de4..ffcf044a 100644 --- a/lbplanner/classes/model/user.php +++ b/lbplanner/classes/model/user.php @@ -319,7 +319,7 @@ public static function api_structure(): external_single_structure { 'username' => new external_value(PARAM_TEXT, 'The username of the user'), 'firstname' => new external_value(PARAM_TEXT, 'The firstname of the user'), 'lastname' => new external_value(PARAM_TEXT, 'The lastname of the user'), - 'theme' => new external_value(PARAM_TEXT, 'The theme the user has selected', VALUE_DEFAULT), + 'theme' => new external_value(PARAM_TEXT, 'The theme the user has selected'), 'lang' => new external_value(PARAM_TEXT, 'The language the user has selected'), 'profileimageurl' => new external_value(PARAM_URL, 'The url of the profile image'), 'planid' => new external_value(PARAM_INT, 'The id of the plan the user is assigned to'), From cb4d2dc87e98ee9420571affc5a18c2bb16dc355 Mon Sep 17 00:00:00 2001 From: Riedler Date: Sun, 25 Aug 2024 17:24:08 +0200 Subject: [PATCH 86/92] fix: incorrect references to notifs table --- lbplanner/services/notifications/get_all_notifications.php | 2 +- lbplanner/services/notifications/update_notification.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lbplanner/services/notifications/get_all_notifications.php b/lbplanner/services/notifications/get_all_notifications.php index 8829ded4..36b71fb3 100644 --- a/lbplanner/services/notifications/get_all_notifications.php +++ b/lbplanner/services/notifications/get_all_notifications.php @@ -46,7 +46,7 @@ public static function get_all_notifications_parameters(): external_function_par public static function get_all_notifications(): array { global $DB, $USER; - $dbnotifications = $DB->get_records(notifications_helper::TABLE, ['userid' => $USER->id]); + $dbnotifications = $DB->get_records(notifications_helper::LBPLANNER_NOTIFICATION_TABLE, ['userid' => $USER->id]); $notifications = []; diff --git a/lbplanner/services/notifications/update_notification.php b/lbplanner/services/notifications/update_notification.php index 4362837b..a0214d2d 100644 --- a/lbplanner/services/notifications/update_notification.php +++ b/lbplanner/services/notifications/update_notification.php @@ -66,15 +66,15 @@ public static function update_notification(int $status, int $notificationid) { ['status' => $status, 'notificationid' => $notificationid] ); - if (!$DB->record_exists(notifications_helper::TABLE, ['id' => $notificationid])) { + if (!$DB->record_exists(notifications_helper::LBPLANNER_NOTIFICATION_TABLE, ['id' => $notificationid])) { throw new \moodle_exception('Notification does not exist'); } - $notification = $DB->get_record(notifications_helper::TABLE, ['id' => $notificationid], '*', MUST_EXIST); + $notification = $DB->get_record(notifications_helper::LBPLANNER_NOTIFICATION_TABLE, ['id' => $notificationid], '*', MUST_EXIST); $notification->status = $status; $notification->timestamp_read = time(); - $DB->update_record(notifications_helper::TABLE, $notification); + $DB->update_record(notifications_helper::LBPLANNER_NOTIFICATION_TABLE, $notification); } /** From b935069e8be603b38090d9573bf8af39e3d3c37f Mon Sep 17 00:00:00 2001 From: Riedler Date: Sun, 25 Aug 2024 17:45:59 +0200 Subject: [PATCH 87/92] feat: implemented proper color validation --- lbplanner/classes/model/course.php | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/lbplanner/classes/model/course.php b/lbplanner/classes/model/course.php index 21942e66..e735cc0a 100644 --- a/lbplanner/classes/model/course.php +++ b/lbplanner/classes/model/course.php @@ -106,14 +106,30 @@ public function set_fresh(int $id) { } /** - * sets the color as #RRGGBB + * sets the color as #RRGGBB or #RGB in hexadecimal notation * @param string $color the color - * @throws \AssertionError + * @throws \coding_exception when the color format is wrong */ public function set_color(string $color) { - // TODO: check color format. - assert(strlen($color) <= 10); - $this->color = $color; + if ($color[0] !== '#') + throw new \coding_exception("incorrect color format - must be either #RGB or #RRGGBB, got \"{$color}\" instead"); + $len = strlen($color); + if ($len === 4) { + // Transforming #RGB to #RRGGBB. + // This way, 0 corresponds to 00, and F to FF, meaning the full spectrum is used. + // This is also how Browsers handle it. + $rrggbb = $color[0] . $color[1] . $color[1] . $color[2] . $color[2] . $color[3] . $color[3]; + } else if ($len === 7) { + // Format #RRGGBB. + $rrggbb = $color; + } else { + throw new \coding_exception("incorrect color format - got incorrect length of {$len}"); + } + $rrggbb = strtoupper($rrggbb); + if (preg_match('/^#[1-9A-F]{6}$/', $rrggbb) === false){ + throw new \coding_exception("incorrect color format - found non-hexadecimal character in color \"{$color}\""); + } + $this->color = $rrggbb; } /** From 2d98bc700db4ab9137a1a257fe758ad8691f1cb5 Mon Sep 17 00:00:00 2001 From: Riedler Date: Sun, 25 Aug 2024 17:53:29 +0200 Subject: [PATCH 88/92] fix: moved code around in an effort to appease the linter --- lbplanner/classes/enums/CAPABILITY.php | 3 ++- lbplanner/classes/enums/CAPABILITY_FLAG.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lbplanner/classes/enums/CAPABILITY.php b/lbplanner/classes/enums/CAPABILITY.php index 2c5bf865..48227796 100644 --- a/lbplanner/classes/enums/CAPABILITY.php +++ b/lbplanner/classes/enums/CAPABILITY.php @@ -61,6 +61,7 @@ class CAPABILITY extends Enum { * @link CAPABILITY_FLAG */ public static function to_capability(string $str): int { - return CAPABILITY_FLAG::{self::name_from($str)}; + $name = self::name_from($str); + return CAPABILITY_FLAG::{$name}; } } diff --git a/lbplanner/classes/enums/CAPABILITY_FLAG.php b/lbplanner/classes/enums/CAPABILITY_FLAG.php index 6f4aad54..a858461b 100644 --- a/lbplanner/classes/enums/CAPABILITY_FLAG.php +++ b/lbplanner/classes/enums/CAPABILITY_FLAG.php @@ -61,6 +61,7 @@ class CAPABILITY_FLAG extends Enum { * @link CAPABILITY */ public static function to_capability(int $num): string { - return CAPABILITY::{self::name_from($num)}; + $name = self::name_from($num); + return CAPABILITY::{$name}; } } From 7a7bf536476b109dd74c49db54bc874e653cbcaa Mon Sep 17 00:00:00 2001 From: Riedler Date: Sun, 25 Aug 2024 18:00:15 +0200 Subject: [PATCH 89/92] fix: appeased moodle codechecker --- lbplanner/classes/helpers/user_helper.php | 6 ------ lbplanner/classes/model/course.php | 5 +++-- lbplanner/classes/model/user.php | 19 ++++++++++++++----- .../notifications/update_notification.php | 7 ++++++- lbplanner/services/plan/accept_invite.php | 2 +- 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/lbplanner/classes/helpers/user_helper.php b/lbplanner/classes/helpers/user_helper.php index dd87612a..4fe6f701 100644 --- a/lbplanner/classes/helpers/user_helper.php +++ b/lbplanner/classes/helpers/user_helper.php @@ -79,9 +79,6 @@ public static function assert_access(int $userid): void { * @throws dml_exception */ public static function is_admin(int $userid): bool { - /** - * @var \context $context - */ $context = context_system::instance(); return has_capability(CAPABILITY::ADMIN, $context, $userid, false); } @@ -114,9 +111,6 @@ public static function is_admin(int $userid): bool { */ public static function get_user_capability_bitmask(int $userid): int { $capabilities = 0; - /** - * @var \context $context - */ $context = context_system::instance(); if (has_capability(CAPABILITY::ADMIN, $context, $userid, false)) { $capabilities += CAPABILITY_FLAG::ADMIN; diff --git a/lbplanner/classes/model/course.php b/lbplanner/classes/model/course.php index e735cc0a..b0cccecd 100644 --- a/lbplanner/classes/model/course.php +++ b/lbplanner/classes/model/course.php @@ -111,8 +111,9 @@ public function set_fresh(int $id) { * @throws \coding_exception when the color format is wrong */ public function set_color(string $color) { - if ($color[0] !== '#') + if ($color[0] !== '#') { throw new \coding_exception("incorrect color format - must be either #RGB or #RRGGBB, got \"{$color}\" instead"); + } $len = strlen($color); if ($len === 4) { // Transforming #RGB to #RRGGBB. @@ -126,7 +127,7 @@ public function set_color(string $color) { throw new \coding_exception("incorrect color format - got incorrect length of {$len}"); } $rrggbb = strtoupper($rrggbb); - if (preg_match('/^#[1-9A-F]{6}$/', $rrggbb) === false){ + if (preg_match('/^#[1-9A-F]{6}$/', $rrggbb) === false) { throw new \coding_exception("incorrect color format - found non-hexadecimal character in color \"{$color}\""); } $this->color = $rrggbb; diff --git a/lbplanner/classes/model/user.php b/lbplanner/classes/model/user.php index ffcf044a..7789118a 100644 --- a/lbplanner/classes/model/user.php +++ b/lbplanner/classes/model/user.php @@ -85,7 +85,14 @@ class user { /** * Constructs a new course */ - public function __construct(int $lbpid, int $mdlid, string $theme, string $lang, string $colorblindness, int $displaytaskcount) { + public function __construct( + int $lbpid, + int $mdlid, + string $theme, + string $lang, + string $colorblindness, + int $displaytaskcount + ) { global $USER; $this->lbpid = $lbpid; $this->mdlid = $mdlid; @@ -170,7 +177,7 @@ public function set_theme(string $theme): void { */ public function set_mdluser(\stdClass $mdluser): void { global $USER; - if ($this->mdluser !== null){ + if ($this->mdluser !== null) { if ($this->mdluser->id !== $USER->id) { throw new \coding_exception('tried to set cached mdluser twice'); } @@ -183,8 +190,9 @@ public function set_mdluser(\stdClass $mdluser): void { * @return \stdClass mdluser */ public function get_mdluser(): \stdClass { - if ($this->mdluser === null) + if ($this->mdluser === null) { $this->mdluser = user_helper::get_mdluser($this->mdlid); + } return $this->mdluser; } @@ -194,7 +202,7 @@ public function get_mdluser(): \stdClass { * @param int $planid */ public function set_planid(int $planid): void { - if ($this->planid !== null){ + if ($this->planid !== null) { throw new \coding_exception('tried to set cached planid twice'); } $this->planid = $planid; @@ -205,8 +213,9 @@ public function set_planid(int $planid): void { * @return int planid */ public function get_planid(): int { - if ($this->planid === null) + if ($this->planid === null) { $this->planid = plan_helper::get_plan_id($this->mdlid); + } return $this->planid; } diff --git a/lbplanner/services/notifications/update_notification.php b/lbplanner/services/notifications/update_notification.php index a0214d2d..64262fe6 100644 --- a/lbplanner/services/notifications/update_notification.php +++ b/lbplanner/services/notifications/update_notification.php @@ -70,7 +70,12 @@ public static function update_notification(int $status, int $notificationid) { throw new \moodle_exception('Notification does not exist'); } - $notification = $DB->get_record(notifications_helper::LBPLANNER_NOTIFICATION_TABLE, ['id' => $notificationid], '*', MUST_EXIST); + $notification = $DB->get_record( + notifications_helper::LBPLANNER_NOTIFICATION_TABLE, + ['id' => $notificationid], + '*', + MUST_EXIST + ); $notification->status = $status; $notification->timestamp_read = time(); diff --git a/lbplanner/services/plan/accept_invite.php b/lbplanner/services/plan/accept_invite.php index 58b80083..7729818d 100644 --- a/lbplanner/services/plan/accept_invite.php +++ b/lbplanner/services/plan/accept_invite.php @@ -93,7 +93,7 @@ public static function accept_invite(int $inviteid) { ]); } } - // TODO: replace with helper function + // TODO: replace with helper function. self::call_external_function('local_lbplanner_plan_clear_plan', [ 'planid' => $oldplanid, 'userid' => $USER->id, From 028b1fdfa3150321c1ce89fd0cb50c4ae016f132 Mon Sep 17 00:00:00 2001 From: Riedler Date: Sun, 25 Aug 2024 18:08:55 +0200 Subject: [PATCH 90/92] docs: fixed docstrings in user model --- lbplanner/classes/model/user.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lbplanner/classes/model/user.php b/lbplanner/classes/model/user.php index 7789118a..88eefb61 100644 --- a/lbplanner/classes/model/user.php +++ b/lbplanner/classes/model/user.php @@ -26,7 +26,6 @@ namespace local_lbplanner\model; use coding_exception; -use core_user; use external_single_structure; use external_value; use local_lbplanner\helpers\plan_helper; @@ -84,6 +83,12 @@ class user { /** * Constructs a new course + * @param int $lbpid ID of the lb planner user + * @param int $mdlid ID of the moodle user + * @param string $theme user-chosen theme + * @param string $lang user language + * @param string $colorblindness user's colorblindness + * @param int $displaytaskcount user's display task count */ public function __construct( int $lbpid, @@ -295,7 +300,6 @@ public static function api_structure_short(): external_single_structure { /** * Prepares full data for the API endpoint. * - * @param bool $access whether the full-access data should be prepared * @return array a full representation of this user and its data */ public function prepare_for_api(): array { From 0262cc87c238bd7eb31658eb84c741175e201ba1 Mon Sep 17 00:00:00 2001 From: Riedler Date: Sun, 25 Aug 2024 18:17:45 +0200 Subject: [PATCH 91/92] fix: downgraded dynamic constant access for php<8.3 --- lbplanner/classes/enums/CAPABILITY.php | 2 +- lbplanner/classes/enums/CAPABILITY_FLAG.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lbplanner/classes/enums/CAPABILITY.php b/lbplanner/classes/enums/CAPABILITY.php index 48227796..22e44a83 100644 --- a/lbplanner/classes/enums/CAPABILITY.php +++ b/lbplanner/classes/enums/CAPABILITY.php @@ -62,6 +62,6 @@ class CAPABILITY extends Enum { */ public static function to_capability(string $str): int { $name = self::name_from($str); - return CAPABILITY_FLAG::{$name}; + return constant('CAPABILITY_FLAG::'.$name); } } diff --git a/lbplanner/classes/enums/CAPABILITY_FLAG.php b/lbplanner/classes/enums/CAPABILITY_FLAG.php index a858461b..5419ebf5 100644 --- a/lbplanner/classes/enums/CAPABILITY_FLAG.php +++ b/lbplanner/classes/enums/CAPABILITY_FLAG.php @@ -62,6 +62,6 @@ class CAPABILITY_FLAG extends Enum { */ public static function to_capability(int $num): string { $name = self::name_from($num); - return CAPABILITY::{$name}; + return constant('CAPABILITY::'.$name); } } From c4ce6b84d787496d4b38d0173357878b7cd32368 Mon Sep 17 00:00:00 2001 From: Riedler Date: Sun, 25 Aug 2024 19:15:30 +0200 Subject: [PATCH 92/92] fix: inverted course enabled check in get_all_modules fixes #8 --- lbplanner/services/modules/get_all_modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lbplanner/services/modules/get_all_modules.php b/lbplanner/services/modules/get_all_modules.php index 9d065dd1..67ee3932 100644 --- a/lbplanner/services/modules/get_all_modules.php +++ b/lbplanner/services/modules/get_all_modules.php @@ -56,7 +56,7 @@ public static function get_all_modules(): array { $ekenabled = $plan["enableek"]; foreach ($courses as $course) { - if ($course->enabled) { + if (!$course->enabled) { continue; } $modules = array_merge(