-
Bug
-
Resolution: Unresolved
-
Minor
-
None
-
4.2.11, 4.1.18, 4.3.9, 4.4.8, 4.5.4
-
None
-
MOODLE_401_STABLE, MOODLE_402_STABLE, MOODLE_403_STABLE, MOODLE_404_STABLE, MOODLE_405_STABLE
Issue/Bug
When deleting a category that has associated competency frameworks and/or user learning plan templates those frameworks/learning plans are 'orphaned' against the original category context.
This then results in a) errors occurring when trying to view those items on user profiles and b) the items simply disappearing from the main competency administration area.
Specific Error
The specific error is:
Can't find data record in database table context.
|
SELECT * FROM {context} WHERE id = ? [array (0 => XXX,)]
|
Error code: invalidrecord
|
This is the low level DB get error because the context held against the framework or learning plan no longer exists in the database.
Moodle Versions
Identified in v4.1 and upwards.
Steps to Reproduce
- Ensure competencies are enabled
Site Administration > Advanced Features > Enable Competencies - Create a new test category and navigate to it
- Create a new learning plan template and add users
- Category > More (secondary nav dropdown) > Learning Plan Templates
- 'Add New Learning Plan Template', complete form, Save Changes
- 'Add Competencies to Learning Plan Template', add competencies, return to the category Learning Plan page
- Select the '0' in the template 'Learning Plans' column to assign users
- Add some user learning plans to the learning plan template
- Create a new competency framework
- Category > More (secondary nav dropdown) > Competency Frameworks
- 'Add New Competency Framework', complete form, Save Changes
- To facilitate testing the issue, in new browser tabs/windows, open the following pages:
- For one of the users assigned to the learning plan: User Profile > Learning Plans. Confirm that the Learning Plan is displayed
- Site Administration > Competencies > Competency Learning Plan Templates. Confirm that the created learning plan appears in the list against the test category.
- Site Administration > Competencies > Competency Frameworks. Confirm that the created framework appears in the list against the test category.
- Return to the test category main page
- Delete the test category using the 'Manage Courses' interface in the 'More' actions menu
- Refresh your test browser tabs/windows.
- The user profile based page will display an error
- The Site Administration page tables will be missing the learning plan template and competency framework (although they still exist in the database) but no error will occur
Possible Solutions
- Warn and/or prevent the deletion of categories that have associated frameworks and/or plans
- Simply ensure that any frameworks and/or plans are deleted when the associated category is deleted*
- Move/re-assign any such frameworks/plans to another category (e.g. the immediate parent category) when the associated category is deleted**
* Similar to the automatic deletion of user grades against courses which occurs when deleting a category, however it could be argued that competency information is less visible/prominent. A list of affected users could be displayed on the final confirm deletion page
** This is the approach we have used to fix affected frameworks/plans on our own site, albeit by updating the database directly by hand (see below).
Code Inspection
course/classes/category.php : public function delete_full() |
Looking through the function above responsible for category deletion we see that a number of context related activities are carried out, just none associated with the competency framework or learning plan template context links. There is even a comment to this affect Now delete anything that may depend on course category context. The actions which are carried out:
- delete child categories
- delete courses in the category context
- delete (or move) cohorts in the category context
- grade_course_category_delete() - grade letters
- content_bank->delete_contents() - content items by type
- question_delete_course_category() - deletes all course questions and question categories
The code also provides a number of hooks etc. that may be useful in any fix for this issue as follows:
- Before deletion the user's permission to delete a category is checked using
can_delete_full()
- There is a check for any plugin callback functions against the following hook
pre_course_category_delete
- The main category deletion (and a number of the sub-steps above) create and trigger various events which could be used
Identify Issue Instances and Database Fix
To fix the issue after it has occurred (by re-assigning frameworks/plans to another category):
- Identify a new category context - simplest way is to navigate to the category 'Competency Frameworks' page and using the `pagecontextid` URL parameter
- Identify the affected frameworks/plan templates using the queries below
- Run the following SQL query substituting the IDs identified above
UPDATE mdl_competency_template SET contextid = <ctx> WHERE id IN (<x>,<x>,<x>); |
UPDATE mdl_competency_framework SET contextid = <ctx> WHERE id IN (<x>,<x>,<x>); |
The following SQL queries can be used to identify instances of this issue in the database:
-- Identify competency frameworks against non-existing category contexts.
|
SELECT
|
f.id AS frameworkid, |
f.shortname AS frameworkname, |
f.contextid AS contextid |
FROM
|
mdl_competency_framework AS f |
WHERE
|
f.contextid NOT IN (SELECT id FROM mdl_context) |
-- OR 1=1 |
;
|
|
-- Identify templates against non-existing category contexts.
|
SELECT
|
t.id AS templateid, |
t.shortname AS templatename, |
t.contextid AS contextid, |
COUNT(p.id) AS countplans, |
GROUP_CONCAT(p.id) AS planids, |
COUNT(u.id) AS countusers, |
GROUP_CONCAT(u.id) AS userids, |
p.origtemplateid,
|
ot.shortname AS origtemplatename |
FROM
|
mdl_competency_template AS t |
LEFT JOIN mdl_competency_plan AS p ON p.templateid = t.id |
LEFT JOIN mdl_competency_template AS ot ON ot.id = p.origtemplateid |
LEFT JOIN mdl_user AS u ON u.id = p.userid |
WHERE
|
t.contextid NOT IN (SELECT id FROM mdl_context) |
-- OR 1=1 |
GROUP BY |
t.id
|
;
|
|
-- Identify user plans based on templates against non-existing category contexts.
|
SELECT
|
p.id AS planid, |
p.name AS plan, |
t.contextid AS contextid, |
p.templateid,
|
t.shortname AS templatename, |
p.origtemplateid,
|
ot.shortname AS origtemplatename, |
u.id AS userid, |
CONCAT(u.lastname, ', ', u.firstname) AS user |
FROM
|
mdl_competency_plan AS p |
LEFT JOIN mdl_competency_template AS t ON t.id = p.templateid |
LEFT JOIN mdl_competency_template AS ot ON ot.id = p.origtemplateid |
LEFT JOIN mdl_user AS u ON u.id = p.userid |
WHERE
|
t.contextid NOT IN (SELECT id FROM mdl_context) |
-- OR 1=1 |
;
|
- will be (partly) resolved by
-
MDL-67548 Allow plugins to hook into course category deletion form
-
- Closed
-