Technical Solution
Verified Solution
Plugin development resources
R
Al-Rashid AI
Apr 19, 2026
Problem Summary
"How challenging would it be to develop a plugin which would update a course completion date each time a user uploads a new submission for an assignment activity?
---
### 🤖 الحل الهندسي المقترح:
As a Moodle expert and Linux systems administrator, I will analyze this problem and provide a detailed solution in the form of a Standard Operating Procedure (SOP).
---
## SOP: Plugin Development Resources - Update Course Completion Date on Assignment Submission
**Title:** Plugin Development for Dynamic Course Completion Date Updates
**Problem Statement:**
The user wants to develop a Moodle plugin that automatically updates a user's course completion date. This update should occur *each time* a user uploads a new submission (or updates an existing one) for *any* assignment activity within that course. The goal is to reflect the most recent engagement with an assignment as the course completion timestamp.
**Challenge Assessment:**
Developing this functionality involves interacting with several core Moodle components, making it a moderately challenging task. The key areas of interaction are:
1. **Moodle Events API:** To detect when an assignment submission occurs. This is the primary trigger.
2. **Moodle Completion API:** To programmatically read and update a user's course completion status and date. This is the core action.
3. **Database Interaction (Indirect):** While the Moodle Completion API abstracts direct database manipulation, understanding the underlying data structures (`mdl_course_completion_aggr`, `mdl_course_completion_criteria`) is beneficial.
4. **Plugin Development Lifecycle:** Creating, installing, debugging, and maintaining a custom Moodle plugin.
**Difficulty Level:** **Medium**
* **Low:** If only reading data or implementing a simple UI change.
* **Medium:** If interacting with core Moodle APIs (like Events, Completion, Gradebook), requiring understanding of Moodle's internal logic and data flow.
* **High:** If modifying core Moodle files, creating complex integrations, or developing highly performant and scalable solutions for large instances.
This problem falls into the "Medium" category because it requires listening to Moodle events and then using the Moodle Completion API to modify a critical user and course data point. Proper error handling, consideration of various course completion settings, and adherence to Moodle best practices are crucial.
**Proposed Solution:**
The most appropriate solution is to develop a **local plugin** (`/local/mypluginname`) or an **admin tool plugin** (`/admin/tool/mypluginname`) that acts as an **event observer**. This plugin will listen for assignment submission events and, upon detecting one, trigger a function to update the associated user's course completion date using Moodle's `completion_info` API.
**Key Moodle Concepts Involved:**
* **Moodle Events:** `\mod_assign\event\submission_created` and `\mod_assign\event\submission_updated`. These events are dispatched whenever a user submits or updates an assignment.
* **Event Observer (`db/events.php` and `classes/observer.php`):** A standard Moodle mechanism to "listen" for and react to specific events.
* **Completion API (`completion_info` class):** Moodle's robust API for managing activity and course completion. Specifically, `\completion_info::set_course_complete()` will be used.
* **Course Completion Settings:** The plugin must consider how course completion is configured (e.g., if completion tracking is even enabled for the course).
* **Logging:** Moodle's logging mechanism (`\core_logging`) for debugging and auditing.
---
### Standard Operating Procedure (SOP) for Plugin Development
**Prerequisites:**
* A running Moodle instance (version 3.x or 4.x recommended).
* PHP development environment with access to Moodle's codebase.
* Basic understanding of PHP and Moodle's file structure.
* Linux system administrator skills for file system navigation and permissions.
* Moodle development environment configured (e.g., debugging enabled).
**Steps:**
#### 1. Plan the Plugin Structure
We will create a local plugin named `coursecompletionupdater`.
```
moodle/
└── local/
└── coursecompletionupdater/
├── classes/
│ └── observer.php
├── db/
│ └── events.php
└── version.php
```
#### 2. Create the Plugin Directory
As a Linux administrator, navigate to your Moodle installation's `local` directory:
```bash
cd /path/to/your/moodle/local/
sudo mkdir coursecompletionupdater
sudo chown -R www-data:www-data coursecompletionupdater # Adjust user/group as per your web server
sudo chmod -R 0755 coursecompletionupdater
```
#### 3. Create `version.php`
This file provides Moodle with metadata about your plugin.
```bash
sudo nano /path/to/your/moodle/local/coursecompletionupdater/version.php
```
Add the following content:
```php
<?php
/**
* Version information for the local_coursecompletionupdater plugin.
*
* @package local_coursecompletionupdater
* @copyright 2023 Your Name Here
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'local_coursecompletionupdater'; // Full component name of the plugin.
$plugin->version = 2023102700; // YYYYMMDDHH (year, month, day, hour).
$plugin->requires = 2020110900; // Moodle 3.10 as minimum. Adjust if needed.
$plugin->maturity = MATURITY_BETA; // MATURITY_ALPHA, MATURITY_BETA, MATURITY_RC, MATURITY_STABLE
$plugin->release = '1.0 (Beta)'; // Human-readable release name.
```
#### 4. Create `db/events.php`
This file registers our observer with Moodle's Events API. It tells Moodle which events our plugin wants to listen to and which function should handle them.
```bash
sudo mkdir /path/to/your/moodle/local/coursecompletionupdater/db/
sudo nano /path/to/your/moodle/local/coursecompletionupdater/db/events.php
```
Add the following content:
```php
<?php
/**
* Event handlers for local_coursecompletionupdater.
*
* @package local_coursecompletionupdater
* @copyright 2023 Your Name Here
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$observers = [
[
'eventname' => '\mod_assign\event\submission_created',
'callback' => '\local_coursecompletionupdater\observer::submission_event_handler',
'includefile' => '/local/coursecompletionupdater/classes/observer.php',
],
[
'eventname' => '\mod_assign\event\submission_updated',
'callback' => '\local_coursecompletionupdater\observer::submission_event_handler',
'includefile' => '/local/coursecompletionupdater/classes/observer.php',
],
];
```
#### 5. Create `classes/observer.php`
This file contains the actual logic that executes when an assignment submission event occurs.
```bash
sudo mkdir /path/to/your/moodle/local/coursecompletionupdater/classes/
sudo nano /path/to/your/moodle/local/coursecompletionupdater/classes/observer.php
```
Add the following content:
```php
<?php
/**
* Event observer for local_coursecompletionupdater plugin.
*
* @package local_coursecompletionupdater
* @copyright 2023 Your Name Here
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace local_coursecompletionupdater;
defined('MOODLE_INTERNAL') || die();
/**
* Observer class to handle Moodle events.
*/
class observer {
/**
* Handles assignment submission events to update course completion date.
*
* @param \core\event\base $event The Moodle event object.
* @return void
*/
public static function submission_event_handler(\core\event\base $event) {
global $CFG;
// Ensure the completion API is available.
// It's usually autoloaded, but explicit inclusion can be safer in some older contexts or for clarity.
require_once($CFG->dirroot . '/completion/externallib.php');
$userid = $event->userid;
$courseid = $event->courseid;
// Log the event for debugging and auditing purposes.
\core_logging::add_log_entry(
'local_coursecompletionupdater',
'submission_event_triggered',
'Course completion update attempt for user ' . $userid . ' in course ' . $courseid . ' due to assignment submission.',
'', // Info URL (optional)
$courseid,
$userid
);
try {
// Get an instance of the completion_info API for the specific course.
$completioninfo = new \completion_info($courseid);
// Check if completion tracking is enabled for this course.
if (!$completioninfo->is_enabled_course()) {
\core_logging::add_log_entry(
'local_coursecompletionupdater',
'completion_tracking_disabled',
'Completion tracking is not enabled for course ' . $courseid . '. Skipping completion date update.',
'',
$courseid,
$userid,
\core_logging::NOTICE
);
return; // Cannot update completion if tracking is off.
}
// Get the current course completion status for the user.
$usercompletion = $completioninfo->get_course_user_completion($userid);
// We want to set/update the course as complete with the current timestamp.
// \completion_info::set_course_complete() handles both creating a new record
// and updating an existing one, including the completion date.
$completioninfo->set_course_complete($userid, true, time());
\core_logging::add_log_entry(
'local_coursecompletionupdater',
'course_completion_updated',
'Successfully updated course completion date for user ' . $userid . ' in course ' . $courseid . ' to ' . userdate(time()) . '.',
'',
$courseid,
$userid
);
} catch (\Exception $e) {
// Log any errors that occur during the completion update process.
\core_logging::add_log_entry(
'local_coursecompletionupdater',
'completion_update_error',
'Error updating course completion for user ' . $userid . ' in course ' . $courseid . ': ' . $e->getMessage(),
'',
$courseid,
$userid,
\core_logging::ERROR
);
// In a production environment, you might want to notify an administrator via email.
// Eg: \core\notification::error('Critical error in Course Completion Updater: ' . $e->getMessage());
}
}
}
```
#### 6. Install the Plugin
Access your Moodle site as an administrator.
Navigate to: **Site administration > Notifications** (or directly `http://yourmoodlesite.com/admin/index.php`).
Moodle will detect the new plugin and prompt you to install it. Follow the on-screen instructions to complete the installation.
#### 7. Configure Moodle for Completion Tracking (if not already)
For this plugin to work, "Completion tracking" must be enabled at the site level and for the specific courses you wish to track.
* **Site-wide:**
* **Site administration > Advanced features**
* Ensure "Enable completion tracking" is checked.
* **Course-specific:**
* In the desired course, go to **Course navigation > More > Course reuse > Edit settings**.
* Expand the "Completion tracking" section.
* Ensure "Enable completion tracking" is set to "Yes".
#### 8. Testing the Plugin
1. Log in as a student user.
2. Enroll in a course where "Completion tracking" is enabled.
3. Ensure the course has at least one assignment activity.
4. As the student, submit an assignment.
5. Check the student's course completion status:
* **Dashboard > My courses > [Course Name]**
* The "Course completion" block (if present) or the "Course completion" report (accessible via Course administration) should show the course as completed with a completion date corresponding to the time of the submission.
6. Submit another assignment (or update the same assignment if allowed by the assignment settings).
7. Verify that the course completion date has been updated to the latest submission timestamp.
8. Check Moodle's server logs or the Moodle logs report (`Site administration > Reports > Logs`) for entries from `local_coursecompletionupdater` to confirm the plugin is firing and successfully updating.
#### 9. Deployment and Maintenance Considerations
* **Performance:** This plugin runs on every assignment submission. For very large Moodle instances with thousands of submissions per hour, this might introduce a minor load. The `completion_info::set_course_complete` method is optimized, but monitoring is advised.
* **Error Handling:** The provided code includes `try-catch` blocks and Moodle logging. Regularly review Moodle's log reports for any errors from this plugin.
* **Permissions:** Ensure the web server user (`www-data` or similar) has appropriate read/write permissions for the plugin files.
* **Backup:** Always back up your Moodle site and database before installing or upgrading any plugins.
* **Upgrades:** When upgrading Moodle, ensure your plugin remains compatible. Test thoroughly in a staging environment. Moodle's completion API is generally stable, but breaking changes can occur between major versions.
* **Course Completion Settings Interaction:** Be aware that this plugin *forces* the overall course completion date to the latest assignment submission. If a course has other complex completion criteria (e.g., specific activity completion order, passing a grade), this plugin will override the *date* of completion, but it won't necessarily change *how* the course becomes complete based on those criteria if the `set_course_complete` method is called with `true`. It will mark the course complete and set its date. If the course completion requires *other* activities to be completed, this might trigger the overall course completion if all other criteria are met and this activity's completion is also met and has its date set. The key here is that it *updates the timestamp* whenever an assignment is submitted, ensuring the completion record reflects recent activity.
---"
The Solution
<r><p>How challenging would it be to develop a plugin which would update a course completion date each time a user uploads a new submission for an assignment activity?</p>
<HR>---</HR>
<H3><s>### </s>🤖 الحل الهندسي المقترح:</H3>
<p>As a Moodle expert and Linux systems administrator, I will analyze this problem and provide a detailed solution in the form of a Standard Operating Procedure (SOP).</p>
<HR>---</HR>
<H2><s>## </s>SOP: Plugin Development Resources - Update Course Completion Date on Assignment Submission</H2>
<p><STRONG><s>**</s>Title:<e>**</e></STRONG> Plugin Development for Dynamic Course Completion Date Updates</p>
<p><STRONG><s>**</s>Problem Statement:<e>**</e></STRONG><br/>
The user wants to develop a Moodle plugin that automatically updates a user's course completion date. This update should occur <EM><s>*</s>each time<e>*</e></EM> a user uploads a new submission (or updates an existing one) for <EM><s>*</s>any<e>*</e></EM> assignment activity within that course. The goal is to reflect the most recent engagement with an assignment as the course completion timestamp.</p>
<p><STRONG><s>**</s>Challenge Assessment:<e>**</e></STRONG></p>
<p>Developing this functionality involves interacting with several core Moodle components, making it a moderately challenging task. The key areas of interaction are:</p>
<LIST type="decimal"><LI><s>1. </s><STRONG><s>**</s>Moodle Events API:<e>**</e></STRONG> To detect when an assignment submission occurs. This is the primary trigger.</LI>
<LI><s>2. </s><STRONG><s>**</s>Moodle Completion API:<e>**</e></STRONG> To programmatically read and update a user's course completion status and date. This is the core action.</LI>
<LI><s>3. </s><STRONG><s>**</s>Database Interaction (Indirect):<e>**</e></STRONG> While the Moodle Completion API abstracts direct database manipulation, understanding the underlying data structures (<C><s>`</s>mdl_course_completion_aggr<e>`</e></C>, <C><s>`</s>mdl_course_completion_criteria<e>`</e></C>) is beneficial.</LI>
<LI><s>4. </s><STRONG><s>**</s>Plugin Development Lifecycle:<e>**</e></STRONG> Creating, installing, debugging, and maintaining a custom Moodle plugin.</LI></LIST>
<p><STRONG><s>**</s>Difficulty Level:<e>**</e></STRONG> <STRONG><s>**</s>Medium<e>**</e></STRONG></p>
<LIST><LI><s>* </s><STRONG><s>**</s>Low:<e>**</e></STRONG> If only reading data or implementing a simple UI change.</LI>
<LI><s>* </s><STRONG><s>**</s>Medium:<e>**</e></STRONG> If interacting with core Moodle APIs (like Events, Completion, Gradebook), requiring understanding of Moodle's internal logic and data flow.</LI>
<LI><s>* </s><STRONG><s>**</s>High:<e>**</e></STRONG> If modifying core Moodle files, creating complex integrations, or developing highly performant and scalable solutions for large instances.</LI></LIST>
<p>This problem falls into the "Medium" category because it requires listening to Moodle events and then using the Moodle Completion API to modify a critical user and course data point. Proper error handling, consideration of various course completion settings, and adherence to Moodle best practices are crucial.</p>
<p><STRONG><s>**</s>Proposed Solution:<e>**</e></STRONG></p>
<p>The most appropriate solution is to develop a <STRONG><s>**</s>local plugin<e>**</e></STRONG> (<C><s>`</s>/local/mypluginname<e>`</e></C>) or an <STRONG><s>**</s>admin tool plugin<e>**</e></STRONG> (<C><s>`</s>/admin/tool/mypluginname<e>`</e></C>) that acts as an <STRONG><s>**</s>event observer<e>**</e></STRONG>. This plugin will listen for assignment submission events and, upon detecting one, trigger a function to update the associated user's course completion date using Moodle's <C><s>`</s>completion_info<e>`</e></C> API.</p>
<p><STRONG><s>**</s>Key Moodle Concepts Involved:<e>**</e></STRONG></p>
<LIST><LI><s>* </s><STRONG><s>**</s>Moodle Events:<e>**</e></STRONG> <C><s>`</s>\mod_assign\event\submission_created<e>`</e></C> and <C><s>`</s>\mod_assign\event\submission_updated<e>`</e></C>. These events are dispatched whenever a user submits or updates an assignment.</LI>
<LI><s>* </s><STRONG><s>**</s>Event Observer (<C><s>`</s>db/events.php<e>`</e></C> and <C><s>`</s>classes/observer.php<e>`</e></C>):<e>**</e></STRONG> A standard Moodle mechanism to "listen" for and react to specific events.</LI>
<LI><s>* </s><STRONG><s>**</s>Completion API (<C><s>`</s>completion_info<e>`</e></C> class):<e>**</e></STRONG> Moodle's robust API for managing activity and course completion. Specifically, <C><s>`</s>\completion_info::set_course_complete()<e>`</e></C> will be used.</LI>
<LI><s>* </s><STRONG><s>**</s>Course Completion Settings:<e>**</e></STRONG> The plugin must consider how course completion is configured (e.g., if completion tracking is even enabled for the course).</LI>
<LI><s>* </s><STRONG><s>**</s>Logging:<e>**</e></STRONG> Moodle's logging mechanism (<C><s>`</s>\core_logging<e>`</e></C>) for debugging and auditing.</LI></LIST>
<HR>---</HR>
<H3><s>### </s>Standard Operating Procedure (SOP) for Plugin Development</H3>
<p><STRONG><s>**</s>Prerequisites:<e>**</e></STRONG></p>
<LIST><LI><s>* </s>A running Moodle instance (version 3.x or 4.x recommended).</LI>
<LI><s>* </s>PHP development environment with access to Moodle's codebase.</LI>
<LI><s>* </s>Basic understanding of PHP and Moodle's file structure.</LI>
<LI><s>* </s>Linux system administrator skills for file system navigation and permissions.</LI>
<LI><s>* </s>Moodle development environment configured (e.g., debugging enabled).</LI></LIST>
<p><STRONG><s>**</s>Steps:<e>**</e></STRONG></p>
<H4><s>#### </s>1. Plan the Plugin Structure</H4>
<p>We will create a local plugin named <C><s>`</s>coursecompletionupdater<e>`</e></C>.</p>
<CODE><s>```</s><i>
</i>moodle/
└── local/
└── coursecompletionupdater/
├── classes/
│ └── observer.php
├── db/
│ └── events.php
└── version.php<i>
</i><e>```</e></CODE>
<H4><s>#### </s>2. Create the Plugin Directory</H4>
<p>As a Linux administrator, navigate to your Moodle installation's <C><s>`</s>local<e>`</e></C> directory:</p>
<CODE lang="bash"><s>```bash</s><i>
</i>cd /path/to/your/moodle/local/
sudo mkdir coursecompletionupdater
sudo chown -R www-data:www-data coursecompletionupdater # Adjust user/group as per your web server
sudo chmod -R 0755 coursecompletionupdater<i>
</i><e>```</e></CODE>
<H4><s>#### </s>3. Create <C><s>`</s>version.php<e>`</e></C></H4>
<p>This file provides Moodle with metadata about your plugin.</p>
<CODE lang="bash"><s>```bash</s><i>
</i>sudo nano /path/to/your/moodle/local/coursecompletionupdater/version.php<i>
</i><e>```</e></CODE>
<p>Add the following content:</p>
<CODE lang="php"><s>```php</s><i>
</i><?php
/**
* Version information for the local_coursecompletionupdater plugin.
*
* @package local_coursecompletionupdater
* @copyright 2023 Your Name Here
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'local_coursecompletionupdater'; // Full component name of the plugin.
$plugin->version = 2023102700; // YYYYMMDDHH (year, month, day, hour).
$plugin->requires = 2020110900; // Moodle 3.10 as minimum. Adjust if needed.
$plugin->maturity = MATURITY_BETA; // MATURITY_ALPHA, MATURITY_BETA, MATURITY_RC, MATURITY_STABLE
$plugin->release = '1.0 (Beta)'; // Human-readable release name.<i>
</i><e>```</e></CODE>
<H4><s>#### </s>4. Create <C><s>`</s>db/events.php<e>`</e></C></H4>
<p>This file registers our observer with Moodle's Events API. It tells Moodle which events our plugin wants to listen to and which function should handle them.</p>
<CODE lang="bash"><s>```bash</s><i>
</i>sudo mkdir /path/to/your/moodle/local/coursecompletionupdater/db/
sudo nano /path/to/your/moodle/local/coursecompletionupdater/db/events.php<i>
</i><e>```</e></CODE>
<p>Add the following content:</p>
<CODE lang="php"><s>```php</s><i>
</i><?php
/**
* Event handlers for local_coursecompletionupdater.
*
* @package local_coursecompletionupdater
* @copyright 2023 Your Name Here
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$observers = [
[
'eventname' => '\mod_assign\event\submission_created',
'callback' => '\local_coursecompletionupdater\observer::submission_event_handler',
'includefile' => '/local/coursecompletionupdater/classes/observer.php',
],
[
'eventname' => '\mod_assign\event\submission_updated',
'callback' => '\local_coursecompletionupdater\observer::submission_event_handler',
'includefile' => '/local/coursecompletionupdater/classes/observer.php',
],
];<i>
</i><e>```</e></CODE>
<H4><s>#### </s>5. Create <C><s>`</s>classes/observer.php<e>`</e></C></H4>
<p>This file contains the actual logic that executes when an assignment submission event occurs.</p>
<CODE lang="bash"><s>```bash</s><i>
</i>sudo mkdir /path/to/your/moodle/local/coursecompletionupdater/classes/
sudo nano /path/to/your/moodle/local/coursecompletionupdater/classes/observer.php<i>
</i><e>```</e></CODE>
<p>Add the following content:</p>
<CODE lang="php"><s>```php</s><i>
</i><?php
/**
* Event observer for local_coursecompletionupdater plugin.
*
* @package local_coursecompletionupdater
* @copyright 2023 Your Name Here
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace local_coursecompletionupdater;
defined('MOODLE_INTERNAL') || die();
/**
* Observer class to handle Moodle events.
*/
class observer {
/**
* Handles assignment submission events to update course completion date.
*
* @param \core\event\base $event The Moodle event object.
* @return void
*/
public static function submission_event_handler(\core\event\base $event) {
global $CFG;
// Ensure the completion API is available.
// It's usually autoloaded, but explicit inclusion can be safer in some older contexts or for clarity.
require_once($CFG->dirroot . '/completion/externallib.php');
$userid = $event->userid;
$courseid = $event->courseid;
// Log the event for debugging and auditing purposes.
\core_logging::add_log_entry(
'local_coursecompletionupdater',
'submission_event_triggered',
'Course completion update attempt for user ' . $userid . ' in course ' . $courseid . ' due to assignment submission.',
'', // Info URL (optional)
$courseid,
$userid
);
try {
// Get an instance of the completion_info API for the specific course.
$completioninfo = new \completion_info($courseid);
// Check if completion tracking is enabled for this course.
if (!$completioninfo->is_enabled_course()) {
\core_logging::add_log_entry(
'local_coursecompletionupdater',
'completion_tracking_disabled',
'Completion tracking is not enabled for course ' . $courseid . '. Skipping completion date update.',
'',
$courseid,
$userid,
\core_logging::NOTICE
);
return; // Cannot update completion if tracking is off.
}
// Get the current course completion status for the user.
$usercompletion = $completioninfo->get_course_user_completion($userid);
// We want to set/update the course as complete with the current timestamp.
// \completion_info::set_course_complete() handles both creating a new record
// and updating an existing one, including the completion date.
$completioninfo->set_course_complete($userid, true, time());
\core_logging::add_log_entry(
'local_coursecompletionupdater',
'course_completion_updated',
'Successfully updated course completion date for user ' . $userid . ' in course ' . $courseid . ' to ' . userdate(time()) . '.',
'',
$courseid,
$userid
);
} catch (\Exception $e) {
// Log any errors that occur during the completion update process.
\core_logging::add_log_entry(
'local_coursecompletionupdater',
'completion_update_error',
'Error updating course completion for user ' . $userid . ' in course ' . $courseid . ': ' . $e->getMessage(),
'',
$courseid,
$userid,
\core_logging::ERROR
);
// In a production environment, you might want to notify an administrator via email.
// Eg: \core\notification::error('Critical error in Course Completion Updater: ' . $e->getMessage());
}
}
}<i>
</i><e>```</e></CODE>
<H4><s>#### </s>6. Install the Plugin</H4>
<p>Access your Moodle site as an administrator.<br/>
Navigate to: <STRONG><s>**</s>Site administration > Notifications<e>**</e></STRONG> (or directly <C><s>`</s>http://yourmoodlesite.com/admin/index.php<e>`</e></C>).<br/>
Moodle will detect the new plugin and prompt you to install it. Follow the on-screen instructions to complete the installation.</p>
<H4><s>#### </s>7. Configure Moodle for Completion Tracking (if not already)</H4>
<p>For this plugin to work, "Completion tracking" must be enabled at the site level and for the specific courses you wish to track.</p>
<LIST><LI><s>* </s><STRONG><s>**</s>Site-wide:<e>**</e></STRONG>
<LIST><LI><s>* </s><STRONG><s>**</s>Site administration > Advanced features<e>**</e></STRONG></LI>
<LI><s>* </s>Ensure "Enable completion tracking" is checked.</LI></LIST></LI>
<LI><s>* </s><STRONG><s>**</s>Course-specific:<e>**</e></STRONG>
<LIST><LI><s>* </s>In the desired course, go to <STRONG><s>**</s>Course navigation > More > Course reuse > Edit settings<e>**</e></STRONG>.</LI>
<LI><s>* </s>Expand the "Completion tracking" section.</LI>
<LI><s>* </s>Ensure "Enable completion tracking" is set to "Yes".</LI></LIST></LI></LIST>
<H4><s>#### </s>8. Testing the Plugin</H4>
<LIST type="decimal"><LI><s>1. </s>Log in as a student user.</LI>
<LI><s>2. </s>Enroll in a course where "Completion tracking" is enabled.</LI>
<LI><s>3. </s>Ensure the course has at least one assignment activity.</LI>
<LI><s>4. </s>As the student, submit an assignment.</LI>
<LI><s>5. </s>Check the student's course completion status:
<LIST><LI><s>* </s><STRONG><s>**</s>Dashboard > My courses > [Course Name]<e>**</e></STRONG></LI>
<LI><s>* </s>The "Course completion" block (if present) or the "Course completion" report (accessible via Course administration) should show the course as completed with a completion date corresponding to the time of the submission.</LI></LIST></LI>
<LI><s>6. </s>Submit another assignment (or update the same assignment if allowed by the assignment settings).</LI>
<LI><s>7. </s>Verify that the course completion date has been updated to the latest submission timestamp.</LI>
<LI><s>8. </s>Check Moodle's server logs or the Moodle logs report (<C><s>`</s>Site administration > Reports > Logs<e>`</e></C>) for entries from <C><s>`</s>local_coursecompletionupdater<e>`</e></C> to confirm the plugin is firing and successfully updating.</LI></LIST>
<H4><s>#### </s>9. Deployment and Maintenance Considerations</H4>
<LIST><LI><s>* </s><STRONG><s>**</s>Performance:<e>**</e></STRONG> This plugin runs on every assignment submission. For very large Moodle instances with thousands of submissions per hour, this might introduce a minor load. The <C><s>`</s>completion_info::set_course_complete<e>`</e></C> method is optimized, but monitoring is advised.</LI>
<LI><s>* </s><STRONG><s>**</s>Error Handling:<e>**</e></STRONG> The provided code includes <C><s>`</s>try-catch<e>`</e></C> blocks and Moodle logging. Regularly review Moodle's log reports for any errors from this plugin.</LI>
<LI><s>* </s><STRONG><s>**</s>Permissions:<e>**</e></STRONG> Ensure the web server user (<C><s>`</s>www-data<e>`</e></C> or similar) has appropriate read/write permissions for the plugin files.</LI>
<LI><s>* </s><STRONG><s>**</s>Backup:<e>**</e></STRONG> Always back up your Moodle site and database before installing or upgrading any plugins.</LI>
<LI><s>* </s><STRONG><s>**</s>Upgrades:<e>**</e></STRONG> When upgrading Moodle, ensure your plugin remains compatible. Test thoroughly in a staging environment. Moodle's completion API is generally stable, but breaking changes can occur between major versions.</LI>
<LI><s>* </s><STRONG><s>**</s>Course Completion Settings Interaction:<e>**</e></STRONG> Be aware that this plugin <EM><s>*</s>forces<e>*</e></EM> the overall course completion date to the latest assignment submission. If a course has other complex completion criteria (e.g., specific activity completion order, passing a grade), this plugin will override the <EM><s>*</s>date<e>*</e></EM> of completion, but it won't necessarily change <EM><s>*</s>how<e>*</e></EM> the course becomes complete based on those criteria if the <C><s>`</s>set_course_complete<e>`</e></C> method is called with <C><s>`</s>true<e>`</e></C>. It will mark the course complete and set its date. If the course completion requires <EM><s>*</s>other<e>*</e></EM> activities to be completed, this might trigger the overall course completion if all other criteria are met and this activity's completion is also met and has its date set. The key here is that it <EM><s>*</s>updates the timestamp<e>*</e></EM> whenever an assignment is submitted, ensuring the completion record reflects recent activity.</LI></LIST>
<HR>---</HR></r>
Did this solution help you resolve the issue?