Ensure every user completes their profile before accessing the platform. Regex and checksum validation, self-registration checks, per-field messages, event logging, admin dashboard, and completion tracking.
Everything you need to enforce profile completion on your Moodle site.
Moodle doesn't natively support a "complete your profile" gate for custom fields.
Often with only name, email, and password — missing important custom fields like tax code or profession.
Making fields required prevents admins from creating accounts without that data. A catch-22.
Without enforcement, users never fill in their profile. Data stays incomplete forever.
A seamless two-step flow: admin creates, user completes.
The plugin hooks into Moodle's after_require_login callback, which fires on every protected page load. Users cannot bypass the check by navigating directly to any URL.
Two ways to install — pick your favorite.
Download the latest .zip from GitHub Releases and extract into local/forceprofile/.
Everything is managed from the admin settings panel.
| Setting | Description | Default |
|---|---|---|
| Enable | Activate or deactivate the plugin | Disabled |
| Fields to check | Custom profile field shortnames, one per line | (empty) |
| Validation patterns | Optional regex per field: shortname:/pattern/ | (empty) |
| Field validators v2.2 | Optional named validator per field: shortname:validatorname | (empty) |
| Validate on self-registration v2.2 | Also check the configured fields on the signup form | Enabled |
| Message | Warning message shown on redirect, followed by the list of fields to correct | "You must complete your profile…" |
| Redirect URL | Local path for profile completion | /user/edit.php |
Optionally enforce a format for specific fields using regex. One pattern per line:
Fields without a pattern only need to be non-empty. Fields with a pattern must match the regex. Invalid patterns are silently skipped.
0–9 become L M N P Q R S T U V). A pattern that only allows digits in those positions rejects perfectly legitimate codes — hence the character classes above.
Some rules cannot be expressed as a regular expression. A tax code such as ADRNLT79P41D969B has a flawless shape, yet it is invalid: its control character should be C. Validators cover exactly that gap. One assignment per line:
| Validator | What it checks |
|---|---|
codicefiscale |
Italian tax code: 16 character layout, valid month letter, omocodia substitutions, and the recomputed control character. The value is trimmed and uppercased first, so codes stored in lower case still validate. |
A validator can be combined with a regex on the same field — the value then has to satisfy both. Unknown validator names are skipped with a developer notice, so a typo never locks users out.
Sites needing their own rule can write a class implementing \local_forceprofile\validator\validator_interface and reference it by its fully qualified name, for example vat:\local_myplugin\validator\vatnumber. No change to this plugin is required.
Until v2.1 a blocked user only saw a generic "complete your profile" warning — a dead end when the field looked filled in but held an invalid value. The warning now lists every field that needs attention and says whether it is missing or invalid:
The same wording is reused as the tooltip on the profile edit form and in the admin status dashboard. All of it comes from the language packs — nothing is hardcoded.
When self-registration is open, the configured fields are validated on the signup form itself, through Moodle's supported validate_extend_signup_form callback. A user can no longer create an account with a malformed value and discover it only at the next page load, locked out of the site.
Only fields actually published on the signup form are checked (Display on signup page in the profile field settings); anything else is left alone. Turn the behaviour off with the Validate on self-registration setting.
core_auth_signup_user web service bypass it — core does not offer a hook there. Those users are still caught by the profile check at their first login.
Monitor profile completion across your entire user base.
Total users, incomplete profiles, and complete profiles at a glance with colored badges.
Username, full name, email, missing fields as badges, and last access date.
Direct links to view and edit each user's profile. Pagination for large sites.
Navigate to Site administration → Plugins → Local plugins → Profile Completion Status. Requires local/forceprofile:viewstatus capability.
Smart UX improvements on the profile edit page — no theme modifications needed.
A red exclamation icon is injected next to the fields that are actually empty or invalid — and only those. Its tooltip carries the same explanation as the warning, so the user reads why the value was rejected.
Dropdown menus (<select>) that hold no value get an empty "Choose…" option prepended, forcing users to make an explicit choice instead of accidentally submitting the first option.
Works automatically on /user/edit.php and /user/editadvanced.php. Uses Moodle's AMD module system — no theme hacks, no custom CSS.
Full audit trail in Moodle's standard log system.
| Event | When | Data |
|---|---|---|
profile_blocked |
User is redirected to complete profile | User ID, list of incomplete fields |
profile_completed |
User fills in all required fields | User ID, completion record ID |
When a user completes all fields, a timestamp is recorded in local_forceprofile_compl. This data can be queried for reports or exported via the Moodle privacy API.
Fine-grained access control for exemptions and dashboard access.
| Capability | Description | Default Roles |
|---|---|---|
local/forceprofile:exempt | Exempt from forced profile completion | Manager, Editing Teacher |
local/forceprofile:viewstatus | Access the status dashboard | Manager |
Site administrators are always exempt. Assign capabilities to additional roles via Site administration → Users → Permissions → Define roles.
Security, performance, and architecture.
Once complete, cached in $SESSION. Zero DB queries for the rest of the session.
Parameterized queries via Moodle's $DB API. No raw SQL anywhere.
All messages sanitized via format_string() before rendering.
Redirect URL validated as PARAM_LOCALURL. External URLs rejected.
Non-existent fields and invalid patterns are skipped with debug notices. No loops.
34 tests covering fields, regex and checksum validation, signup, events, completion, and edge cases.
| Path | Reason |
|---|---|
/user/edit.php | Profile edit (where users fill in fields) |
/user/editadvanced.php | Advanced profile edit |
/login/logout.php | Users must always be able to log out |
/login/change_password.php | Password change flow |
/lib/ajax/service.php | AJAX web services |
/lib/ajax/service-nologin.php | AJAX (no login) |
All notable changes to this project.
shortname:validatorname setting for checks a regex cannot express; sites can register their own class implementing validator_interfacecodicefiscale) — layout, month letter, omocodia substitutions and recomputed control character; values are trimmed and uppercased before checkingvalidate_extend_signup_form callback, so a bad value is refused before the account exists❗) next to configured field labels on profile edit page<select> fields that are incompleteformenhancer.js using Moodle's module systembefore_standard_html_head to inject JS only on edit pagesprofile_blocked and profile_completed events in Moodle logslocal_forceprofile_compl tablelocal/forceprofile:viewstatusPARAM_LOCALURL) — prevents open redirectformat_string()$PAGE->url access wrapped in try/catch for early page lifecycle safetystrposnull_provider)after_require_login callback for profile enforcementlocal/forceprofile:exempt for managers and editing teachers