Merge user accounts
Versions
Current version
(2026052700: Focus on stability and extensibility) (2026052700)
(2026052700: Focus on stability and extensibility)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2026052700
Version release name: (2026052700: Focus on stability and extensibility)
Maturity: Stable
Supported Moodle versions: 4.5, 5.0, 5.1, 5.2
Repository URL (Git): https://github.com/jpahullo/moodle-tool_mergeusers
Repository branch:
Repository tag: 2026052700
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
If not specified, each change is performed in the version date.
It means that if version is YYYYMMDDOO, the change was performed on YYYY-MM-DD.
2026052700
- fix: #411: regrading after merging users: prevent errors when plugin is uninstalled or
plugin table is missing. Thanks to @terryaulenbach for reporting the issue.
- Skipped grade records from uninstalled plugins at database level, improving performance.
- Aborting merge when plugin is installed but table is missing, treating it as critical database corruption consistent with other data integrity checks.
- Added tests covering all edge cases.
2026050500
- task: #407: add support for Moodle 5.2.
- fix: #405: remove execution permissions for db/install.xml and db/upgrade.php.
- fix: #399: fix suspended image path. Thanks @matheus1002 for reporting.
2025102100
- bug: #379: remove table lines for >= Moodle 5.0 and Bootstrap 5.0. Thanks @lucaboesch.
2025101701
- task: #383: Moodle 5.1 compatible.
2025101700
- fix: #381: add all user-related compound indexes into default plugin settings.
- default_db_config.php updated manually with structured section about compound indexes.
- listuserfields.php CLI script improved to list all user-related compound indexes. This script must help administrators to identify other compound indexes that affect their Moodle instances.
2025101400
- fix: #382: ensure grade_grades table is merged properly. Thanks Daniel Tomé.
- Added tests for the new grade_grades table merger.
- Improved some existing tests.
- Improve Makefile to let run phpcs/phpcbf more easily.
2025092100
- improvement: #372: add output from last steps of regrading and reaggregation of course completions.
Also, reaggregation of course completion now happens inside the time of the merge process, and not after as before. - task: #362: remove YUI code. Simplified javascript code to the maximum.
2025091800
- fix: #371: listuserfields.php CLI scripts supports tables that does not exist on the XML database schema.
2025090401
- fix: #367: database settings tab did no show properly
the default nor calculated settings. - fix: #369: add PHP attributes to hook.
2025082301
- improvement: #360: new class added to manage session-based
users selection when merging users from web administration. - improvement: #358: add "suspended" tag besides the
user detail on all pages (including user search, user review and logs).
Single log page now shows the full user detail, as in the rest of pages. - fix: #358: users selection table showed always the user
detail of the user to remove. Now, it shows properly both users.
It was detected while working on the improvement of #358.
2025082200
- improvement: #356: code reorganization on the whole plugin.
- Placed all suitable file under
/classes/for autoloading. - Revisited all files (except
/tests/) with phpcs (usinglocal_codechecker) - Removed content from
lib.phpin favour ofsettingslib.phpand
a new classdatabase_transactions::are_supported(). - Added a
Makefilewith some targets for helping while developing. - All tests passes again.
- All clicks on the web work again.
- Moved the link to see merge logs into the
Reportsadministration menu.
- Placed all suitable file under
UPGRADING
When upgrading to this version, you have to choose one of these paths:
- In case you have local plugin customizations: you must check twice
the new plugin structure since there has been a major refactor
of the whole plugin. Thelib/directory was removed, and
most of the plugin classes were moved inside theclasses/directory
for a better code organization and with the benefit of autoloading.
Also, we removed the vast majority of functions from thelib.php,
leaving there only the necessary Moodle callbacks.
Update your local customizations appropriately according to new
classes and file structure. - In case you DO NOT have local plugin customizations: you can freely
upgrade the plugin without worrying.
2025082000
- #354: ensure that setting
tool_mergeusers/uniquekeynewidtomaintain
applies.
2025081900
- improvement: #350: added hook to proceed with operations after
all tables have been merged, and before registering the end of the merge.
- If these hook's callbacks are invoked, it means that all went ok
and table mergers processed the merge with success till now. - The callbacks for this hook are meant to process any kind of operations
from Moodle internals or plugin specific tasks, that are transversal,
(operations not specific for a single table) or any kind of
aggregation operation, not updated by the table mergers. - To provide you an example, we have moved the regrading of the users and
the course recompletions into callbacks for this hook. - We think this hook will help Moodle and plugin developers to adjust the
merge users tool to better fit any Moodle instance (with a variable
number of custom Moodle changes and plugins).
- If these hook's callbacks are invoked, it means that all went ok
NOTE
Actually, with callbacks for both hooks, Moodle core and plugins
can make work this plugin as they need to merge users properly. Why?
This plugin provides a generic way to merge users, but internals from
Moodle core (subsystems, and so) and plugins really know how user's
information is managed. So, their maintainers have the full knowledge
and they can provide callbacks for both hooks:
- Callbacks for
add_settings_before_merginghook may help providing specific
database-related settings: mainly table mergers (settingtablemergers),
compound indexes (settingcompoundindexes) or user-related table columns
(settinguserfieldnames). - Callbacks for
after_merged_all_tableshook may help providing specific
post-processes.
UPGRADING
Just as a clarification: The inclusion of the hooks does not alter the
way of using this plugin at all. It will behave as it did.
However, these two hooks provide you as a developer and maintainer of your
plugin or Moodle instance powerful tools to customize the behaviour of the merge,
just placing the necessary callbacks and related stuff in your own
code, to ensure merge users is processed properly.
2025081800
- improvement: #348: added hook to load database-related settings.
- This is though to help Moodle and plugin developers to adjust their code to help
this plugin merge users properly. - The settings that are loaded by this hook are those populated on the old
config/config.phpandconfig/config.local.phpfiles. These files are not supported any more. - The content of the old
config/config.phpis now placed onclasses/local/default_db_config.php.
This must help this plugin maintainers to keep in a single place the default behaviour. - Added tests to ensure the database-related settings are kept properly.
- Priority of the settings (more priority settings are kept, in front of subsequent settings):
- Custom admin setting: the set of settings with the highest priority.
This must let administrators adjusting plugin behaviour at any time. - Hook settings: settings populated from this hook's callbacks are the second set of
settings in priority. - Default settings: the plugin's default settings are kept as with the lowest priority.
Any existing setting from hooks and custom settings will replace default ones.
- Custom admin setting: the set of settings with the highest priority.
- This is though to help Moodle and plugin developers to adjust their code to help
2025081700
- fix: #308: reportedly, extension
pcntlseems to be loaded sometimes but itspcntl_*functions
are not available. We have removed support for aborting forCtrl+C(SIGINT) usingpcntlextension.
No panic: in several instances we have, we can cancel the CLI script execution withCtrl+Cwithout
thepcntlextension loaded. It was necessary on initial version of this plugin. Nowadays it seems unnecessary. - improvement: #308: updated the CLI script help to show that when using
--alwaysrollbackoption
there is no loop for merging pairs of users.
2025081603
- improvement: #244: allow resetting web user selection. Unified search and review tables.
Added extra column on search table to show whether a user is already suspended (probably already merged). - improvement: #345: move config.local.php into a new admin setting, in JSON format, for being human-readable.
- Also, consider that setting with name
alwaysRollbackwas renamed toalwaysrollbackto unify the case insensitiveness
of the rest of the configuration settings. It applies within the code and also on the CLI script parameters.
- Also, consider that setting with name
UPGRADING
Recommendation when upgrading: Keep your config/config.local.php in place. It will help
updating the value of the new admin setting tool_mergeusers/customdbsettings automatically,
without the need to convert your old config/config.local.php to JSON.
But, it is only a recommendation.
Otherwise, you will have to update that admin setting manually with the content of your previous
config/config.local.php on the new admin setting. To help you, you can use the
tool_mergeusers\local\jsonizer::to_json($customsettings) with an array with all your
$customsettings, and it will provide you the JSON content to place.
If you did not have any customization or file on config/config.local.php, you have to do nothing
with this upgrading step.
2025081500
- improvement: #328: added support for Moodle 5.0.
2025081402
- fix: #336: deleted users are excluded from everywhere when searching by and merging users.
- improvement: #281: add debug info into log when no course module is found when regrading. Thanks to @Richardvi.
- fix: #277: revisit all Moodle tables and user-related fields to
update config.php settings. Provide a CLI script to help.
2025081300
- fix: #275: make web user search work on any database engine. Thanks to @leonstr.
- fix: #273: exclude deleted users from the web search. Thanks to @leonstr.
2025081205
- fix: #329: set renumber quiz attempts as the default setting.
- fix: #331: prevents web browser alert from leaving form page on the summary page.
- improvement: #311: use Catalyst CI. Thanks to @matthewhilton.
- improvement: #306: remove user profile fields; use profile page hook to show merging detail. Thanks to @matthewhilton.
- fix: #68: move logger to proper namespace. Thanks to @matthewhilton.
- improvement: #306: define new capability to see logs, either as admin or from user profile. Thanks to @matthewhilton.
- improvement: #306: add information about whether a user is deletable from this plugin viewpoint.
- improvement: #306: add settings item to inform that prior custom user profile fields added by this plugin still exist and should be deleted.
There are no longer used nor updated. - improvement: #306: add PHP API to list deletable users.
UPGRADING
Before upgrading to this version, please check your own automatization processes in case they use the plugin profile fields.
You should adapt them to use the logs from the plugin table tool_mergeusers. In this case,
we provide a PHP API on tool_mergeusers\local\last_merge::list_all_deletable_users()
to list all candidate users to be deletable. You can adapt your scripts starting from
this new API.
2025081100
- fix: #315: replaced print_error() functions for moodle_exception. Thanks to @ManaElmountasir and @minhduchoang195.
- bump version and update CHANGES.md
- fix: #326: remove deprecation warnings on CLI script and tests. Thanks to @matthewhilton.
2025020505
- bump version to make a new plugin version available for M4.5.
2025020503
- fix: URL on old and new user profile fields definition.
- improvement: CLI script now shows better log of merging operations.
2025020502
- fix: #295: remove deprecation warning on CLIGathering, related to Iterator. Thanks to @CatSema.
2025020501
- bump version, update CHANGES.md, and kept support only for M4.1.
2025020500
- bump version and update CHANGES.md
- new feature: #283: use custom profile fields to identify merged old and new users (to both users). Partly contributed thanks to @sampraxis and @ClausSchmidtPraxis on 2024-11-14. PHPUnit test ensures the behaviour is the expected.
- fix: #294: pass tests on mod_assign again. Thanks to @leonstr.
- fix: #304: set up again suspended image to merged source user.
- fix: #253: CRLF codification passed to LF.
- fix: #299: file content to get them properly uploaded into AMOS.
2025012300
- #299: make lang file compatible with AMOS to be translatable.
- #299: add $plugin->release property as releasing new plugin version warns it.
2025012200
- #295: CliGathering: remove deprecation warnings from Iterator implementation.
- #292: Bump plugin version and requires Moodle 4.5 onwards.
- CI passes on green, as before, for PHP 8.1, 8.2 and 8.3 only for core MOODLE_405_STABLE.
- version.php updated.
- Improve type detection on IDE.
- Uses new trait on the assign_test class.
- #291: Make web administration work on merge users.
- Removed lines requiring "lib/outputcomponents.php" from two files.
2024060300
- #268: CI: verify it is working from M4.1 to M4.4 and master. Solves #263 too.
- #268: Fixed PHPDoc issues and revisited output from merger when running from CLI.
2023061900
- #245: Add list of incremental changes on file CHANGES.md.
- #247: Fix proper support for Moodle 4.2, thanks to Matthias Opitz.
2023040402
- #243: remove unused class with API inconsistence.
2023040401
- #211: add CSV export for merged user logs; added mergedbyuserid field, thanks to Mark Johnson.
2023040400
- 2023-04-04 Fix CI to run only for supported versions, supporting Moodle 3.11 and up.
- 2022-12-15 #228: Add compound indexes for customcert_issues table, thanks to Leon Stringer.
- 2021-08-01 #197: Use Github Actions, remove Travis CI usage.
2021072200
- 2021-07-23 #193: Allow automatic Moodle Plugins release when defining git tab.
- 2021-07-14 #175: Reaggregate completion for target user, thanks to Andrew Hancox.
- 2021-07-14 #194: Update unit tests for Moodle 3.10+, thanks to Alistair Spark.
- 2021-07-02 #177: Move observer functions into classes to bypass include file error, thanks to Andrew Madden.
- 2021-06-10 #181: Guarantee processing any grade item.
- 2020-02-23 #169: Fix wrong entries deleted in case of conflict, thanks to Tim Schroeder.
- 2019-08-18 #166: Support for duplicated assign submissions and other fixes.
- 2019-08-16 #67: Improve and clean up settings.php.
- 2019-08-16 #163: Force user to keep not to be suspended.
- 2019-08-16 #161: Split in chunks the list of record ids to delete/update to prevent buffer overflow on SQL sentences.
- 2019-08-15 #147: Config: Add logstore_standard_log columns related to user.id.
- 2019-08-15 #151: Config: Add composed keys for wikis.
- 2019-08-15 #146: Fix searching by user.id on pgsql.
- 2019-08-15 #152: Support any supported Moodle database.
Older changes
For a more extense list of changes, see git logs for changes before April 2019.
Contributors
Maintained by:
(Focus on stability and extensibility) (2026050500)
(Focus on stability and extensibility)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2026050500
Version release name: (Focus on stability and extensibility)
Maturity: Stable
Supported Moodle versions: 4.5, 5.0, 5.1, 5.2
Repository URL (Git): https://github.com/jpahullo/moodle-tool_mergeusers
Repository branch:
Repository tag: 2026050500
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
If not specified, each change is performed in the version date.
It means that if version is YYYYMMDDOO, the change was performed on YYYY-MM-DD.
2026050500
- task: #407: add support for Moodle 5.2.
- fix: #405: remove execution permissions for db/install.xml and db/upgrade.php.
- fix: #399: fix suspended image path. Thanks @matheus1002 for reporting.
2025102100
- bug: #379: remove table lines for >= Moodle 5.0 and Bootstrap 5.0. Thanks @lucaboesch.
2025101701
- task: #383: Moodle 5.1 compatible.
2025101700
- fix: #381: add all user-related compound indexes into default plugin settings.
- default_db_config.php updated manually with structured section about compound indexes.
- listuserfields.php CLI script improved to list all user-related compound indexes. This script must help administrators to identify other compound indexes that affect their Moodle instances.
2025101400
- fix: #382: ensure grade_grades table is merged properly. Thanks Daniel Tomé.
- Added tests for the new grade_grades table merger.
- Improved some existing tests.
- Improve Makefile to let run phpcs/phpcbf more easily.
2025092100
- improvement: #372: add output from last steps of regrading and reaggregation of course completions.
Also, reaggregation of course completion now happens inside the time of the merge process, and not after as before. - task: #362: remove YUI code. Simplified javascript code to the maximum.
2025091800
- fix: #371: listuserfields.php CLI scripts supports tables that does not exist on the XML database schema.
2025090401
- fix: #367: database settings tab did no show properly
the default nor calculated settings. - fix: #369: add PHP attributes to hook.
2025082301
- improvement: #360: new class added to manage session-based
users selection when merging users from web administration. - improvement: #358: add "suspended" tag besides the
user detail on all pages (including user search, user review and logs).
Single log page now shows the full user detail, as in the rest of pages. - fix: #358: users selection table showed always the user
detail of the user to remove. Now, it shows properly both users.
It was detected while working on the improvement of #358.
2025082200
- improvement: #356: code reorganization on the whole plugin.
- Placed all suitable file under
/classes/for autoloading. - Revisited all files (except
/tests/) with phpcs (usinglocal_codechecker) - Removed content from
lib.phpin favour ofsettingslib.phpand
a new classdatabase_transactions::are_supported(). - Added a
Makefilewith some targets for helping while developing. - All tests passes again.
- All clicks on the web work again.
- Moved the link to see merge logs into the
Reportsadministration menu.
- Placed all suitable file under
UPGRADING
When upgrading to this version, you have to choose one of these paths:
- In case you have local plugin customizations: you must check twice
the new plugin structure since there has been a major refactor
of the whole plugin. Thelib/directory was removed, and
most of the plugin classes were moved inside theclasses/directory
for a better code organization and with the benefit of autoloading.
Also, we removed the vast majority of functions from thelib.php,
leaving there only the necessary Moodle callbacks.
Update your local customizations appropriately according to new
classes and file structure. - In case you DO NOT have local plugin customizations: you can freely
upgrade the plugin without worrying.
2025082000
- #354: ensure that setting
tool_mergeusers/uniquekeynewidtomaintain
applies.
2025081900
- improvement: #350: added hook to proceed with operations after
all tables have been merged, and before registering the end of the merge.
- If these hook's callbacks are invoked, it means that all went ok
and table mergers processed the merge with success till now. - The callbacks for this hook are meant to process any kind of operations
from Moodle internals or plugin specific tasks, that are transversal,
(operations not specific for a single table) or any kind of
aggregation operation, not updated by the table mergers. - To provide you an example, we have moved the regrading of the users and
the course recompletions into callbacks for this hook. - We think this hook will help Moodle and plugin developers to adjust the
merge users tool to better fit any Moodle instance (with a variable
number of custom Moodle changes and plugins).
- If these hook's callbacks are invoked, it means that all went ok
NOTE
Actually, with callbacks for both hooks, Moodle core and plugins
can make work this plugin as they need to merge users properly. Why?
This plugin provides a generic way to merge users, but internals from
Moodle core (subsystems, and so) and plugins really know how user's
information is managed. So, their maintainers have the full knowledge
and they can provide callbacks for both hooks:
- Callbacks for
add_settings_before_merginghook may help providing specific
database-related settings: mainly table mergers (settingtablemergers),
compound indexes (settingcompoundindexes) or user-related table columns
(settinguserfieldnames). - Callbacks for
after_merged_all_tableshook may help providing specific
post-processes.
UPGRADING
Just as a clarification: The inclusion of the hooks does not alter the
way of using this plugin at all. It will behave as it did.
However, these two hooks provide you as a developer and maintainer of your
plugin or Moodle instance powerful tools to customize the behaviour of the merge,
just placing the necessary callbacks and related stuff in your own
code, to ensure merge users is processed properly.
2025081800
- improvement: #348: added hook to load database-related settings.
- This is though to help Moodle and plugin developers to adjust their code to help
this plugin merge users properly. - The settings that are loaded by this hook are those populated on the old
config/config.phpandconfig/config.local.phpfiles. These files are not supported any more. - The content of the old
config/config.phpis now placed onclasses/local/default_db_config.php.
This must help this plugin maintainers to keep in a single place the default behaviour. - Added tests to ensure the database-related settings are kept properly.
- Priority of the settings (more priority settings are kept, in front of subsequent settings):
- Custom admin setting: the set of settings with the highest priority.
This must let administrators adjusting plugin behaviour at any time. - Hook settings: settings populated from this hook's callbacks are the second set of
settings in priority. - Default settings: the plugin's default settings are kept as with the lowest priority.
Any existing setting from hooks and custom settings will replace default ones.
- Custom admin setting: the set of settings with the highest priority.
- This is though to help Moodle and plugin developers to adjust their code to help
2025081700
- fix: #308: reportedly, extension
pcntlseems to be loaded sometimes but itspcntl_*functions
are not available. We have removed support for aborting forCtrl+C(SIGINT) usingpcntlextension.
No panic: in several instances we have, we can cancel the CLI script execution withCtrl+Cwithout
thepcntlextension loaded. It was necessary on initial version of this plugin. Nowadays it seems unnecessary. - improvement: #308: updated the CLI script help to show that when using
--alwaysrollbackoption
there is no loop for merging pairs of users.
2025081603
- improvement: #244: allow resetting web user selection. Unified search and review tables.
Added extra column on search table to show whether a user is already suspended (probably already merged). - improvement: #345: move config.local.php into a new admin setting, in JSON format, for being human-readable.
- Also, consider that setting with name
alwaysRollbackwas renamed toalwaysrollbackto unify the case insensitiveness
of the rest of the configuration settings. It applies within the code and also on the CLI script parameters.
- Also, consider that setting with name
UPGRADING
Recommendation when upgrading: Keep your config/config.local.php in place. It will help
updating the value of the new admin setting tool_mergeusers/customdbsettings automatically,
without the need to convert your old config/config.local.php to JSON.
But, it is only a recommendation.
Otherwise, you will have to update that admin setting manually with the content of your previous
config/config.local.php on the new admin setting. To help you, you can use the
tool_mergeusers\local\jsonizer::to_json($customsettings) with an array with all your
$customsettings, and it will provide you the JSON content to place.
If you did not have any customization or file on config/config.local.php, you have to do nothing
with this upgrading step.
2025081500
- improvement: #328: added support for Moodle 5.0.
2025081402
- fix: #336: deleted users are excluded from everywhere when searching by and merging users.
- improvement: #281: add debug info into log when no course module is found when regrading. Thanks to @Richardvi.
- fix: #277: revisit all Moodle tables and user-related fields to
update config.php settings. Provide a CLI script to help.
2025081300
- fix: #275: make web user search work on any database engine. Thanks to @leonstr.
- fix: #273: exclude deleted users from the web search. Thanks to @leonstr.
2025081205
- fix: #329: set renumber quiz attempts as the default setting.
- fix: #331: prevents web browser alert from leaving form page on the summary page.
- improvement: #311: use Catalyst CI. Thanks to @matthewhilton.
- improvement: #306: remove user profile fields; use profile page hook to show merging detail. Thanks to @matthewhilton.
- fix: #68: move logger to proper namespace. Thanks to @matthewhilton.
- improvement: #306: define new capability to see logs, either as admin or from user profile. Thanks to @matthewhilton.
- improvement: #306: add information about whether a user is deletable from this plugin viewpoint.
- improvement: #306: add settings item to inform that prior custom user profile fields added by this plugin still exist and should be deleted.
There are no longer used nor updated. - improvement: #306: add PHP API to list deletable users.
UPGRADING
Before upgrading to this version, please check your own automatization processes in case they use the plugin profile fields.
You should adapt them to use the logs from the plugin table tool_mergeusers. In this case,
we provide a PHP API on tool_mergeusers\local\last_merge::list_all_deletable_users()
to list all candidate users to be deletable. You can adapt your scripts starting from
this new API.
2025081100
- fix: #315: replaced print_error() functions for moodle_exception. Thanks to @ManaElmountasir and @minhduchoang195.
- bump version and update CHANGES.md
- fix: #326: remove deprecation warnings on CLI script and tests. Thanks to @matthewhilton.
2025020505
- bump version to make a new plugin version available for M4.5.
2025020503
- fix: URL on old and new user profile fields definition.
- improvement: CLI script now shows better log of merging operations.
2025020502
- fix: #295: remove deprecation warning on CLIGathering, related to Iterator. Thanks to @CatSema.
2025020501
- bump version, update CHANGES.md, and kept support only for M4.1.
2025020500
- bump version and update CHANGES.md
- new feature: #283: use custom profile fields to identify merged old and new users (to both users). Partly contributed thanks to @sampraxis and @ClausSchmidtPraxis on 2024-11-14. PHPUnit test ensures the behaviour is the expected.
- fix: #294: pass tests on mod_assign again. Thanks to @leonstr.
- fix: #304: set up again suspended image to merged source user.
- fix: #253: CRLF codification passed to LF.
- fix: #299: file content to get them properly uploaded into AMOS.
2025012300
- #299: make lang file compatible with AMOS to be translatable.
- #299: add $plugin->release property as releasing new plugin version warns it.
2025012200
- #295: CliGathering: remove deprecation warnings from Iterator implementation.
- #292: Bump plugin version and requires Moodle 4.5 onwards.
- CI passes on green, as before, for PHP 8.1, 8.2 and 8.3 only for core MOODLE_405_STABLE.
- version.php updated.
- Improve type detection on IDE.
- Uses new trait on the assign_test class.
- #291: Make web administration work on merge users.
- Removed lines requiring "lib/outputcomponents.php" from two files.
2024060300
- #268: CI: verify it is working from M4.1 to M4.4 and master. Solves #263 too.
- #268: Fixed PHPDoc issues and revisited output from merger when running from CLI.
2023061900
- #245: Add list of incremental changes on file CHANGES.md.
- #247: Fix proper support for Moodle 4.2, thanks to Matthias Opitz.
2023040402
- #243: remove unused class with API inconsistence.
2023040401
- #211: add CSV export for merged user logs; added mergedbyuserid field, thanks to Mark Johnson.
2023040400
- 2023-04-04 Fix CI to run only for supported versions, supporting Moodle 3.11 and up.
- 2022-12-15 #228: Add compound indexes for customcert_issues table, thanks to Leon Stringer.
- 2021-08-01 #197: Use Github Actions, remove Travis CI usage.
2021072200
- 2021-07-23 #193: Allow automatic Moodle Plugins release when defining git tab.
- 2021-07-14 #175: Reaggregate completion for target user, thanks to Andrew Hancox.
- 2021-07-14 #194: Update unit tests for Moodle 3.10+, thanks to Alistair Spark.
- 2021-07-02 #177: Move observer functions into classes to bypass include file error, thanks to Andrew Madden.
- 2021-06-10 #181: Guarantee processing any grade item.
- 2020-02-23 #169: Fix wrong entries deleted in case of conflict, thanks to Tim Schroeder.
- 2019-08-18 #166: Support for duplicated assign submissions and other fixes.
- 2019-08-16 #67: Improve and clean up settings.php.
- 2019-08-16 #163: Force user to keep not to be suspended.
- 2019-08-16 #161: Split in chunks the list of record ids to delete/update to prevent buffer overflow on SQL sentences.
- 2019-08-15 #147: Config: Add logstore_standard_log columns related to user.id.
- 2019-08-15 #151: Config: Add composed keys for wikis.
- 2019-08-15 #146: Fix searching by user.id on pgsql.
- 2019-08-15 #152: Support any supported Moodle database.
Older changes
For a more extense list of changes, see git logs for changes before April 2019.
Contributors
Maintained by:
(Focus on stability and extensibility) (2025102100)
(Focus on stability and extensibility)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2025102100
Version release name: (Focus on stability and extensibility)
Maturity: Stable
Supported Moodle versions: 4.5, 5.0, 5.1
Repository URL (Git): https://github.com/jpahullo/moodle-tool_mergeusers
Repository branch:
Repository tag: 2025102100
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
2025102100
- 2025-10-21: bug: #379: remove table lines for >= Moodle 5.0 and Bootstrap 5.0. Thanks @lucaboesch.
2025101701
- 2025-10-17: task: #383: Moodle 5.1 compatible.
2025101700
- 2025-10-17: fix: #381: add all user-related compound indexes into default plugin settings.
- default_db_config.php updated manually with structured section about compound indexes.
- listuserfields.php CLI script improved to list all user-related compound indexes. This script must help administrators to identify other compound indexes that affect their Moodle instances.
2025101400
- 2025-10-14: fix: #382: ensure grade_grades table is merged properly. Thanks Daniel Tomé.
- Added tests for the new grade_grades table merger.
- Improved some existing tests.
- Improve Makefile to let run phpcs/phpcbf more easily.
2025092100
- 2025-09-21: improvement: #372: add output from last steps of regrading and reaggregation of course completions.
Also, reaggregation of course completion now happens inside the time of the merge process, and not after as before. - 2025-09-21: task: #362: remove YUI code. Simplified javascript code to the maximum.
2025091800
- 2025-09-18: fix: #371: listuserfields.php CLI scripts supports tables that does not exist on the XML database schema.
2025090401
- 2025-09-04: fix: #367: database settings tab did no show properly
the default nor calculated settings. - 2025-09-04: fix: #369: add PHP attributes to hook.
2025082301
- 2025-08-23: improvement: #360: new class added to manage session-based
users selection when merging users from web administration. - 2025-08-23: improvement: #358: add "suspended" tag besides the
user detail on all pages (including user search, user review and logs).
Single log page now shows the full user detail, as in the rest of pages. - 2025-08-23: fix: #358: users selection table showed always the user
detail of the user to remove. Now, it shows properly both users.
It was detected while working on the improvement of #358.
2025082200
- 2025-08-22: improvement: #356: code reorganization on the whole plugin.
- Placed all suitable file under
/classes/for autoloading. - Revisited all files (except
/tests/) with phpcs (usinglocal_codechecker) - Removed content from
lib.phpin favour ofsettingslib.phpand
a new classdatabase_transactions::are_supported(). - Added a
Makefilewith some targets for helping while developing. - All tests passes again.
- All clicks on the web work again.
- Moved the link to see merge logs into the
Reportsadministration menu.
- Placed all suitable file under
UPGRADING
When upgrading to this version, you have to choose one of these paths:
- In case you have local plugin customizations: you must check twice
the new plugin structure since there has been a major refactor
of the whole plugin. Thelib/directory was removed, and
most of the plugin classes were moved inside theclasses/directory
for a better code organization and with the benefit of autoloading.
Also, we removed the vast majority of functions from thelib.php,
leaving there only the necessary Moodle callbacks.
Update your local customizations appropriately according to new
classes and file structure. - In case you DO NOT have local plugin customizations: you can freely
upgrade the plugin without worrying.
2025082000
- 2025-08-20: fix: #354: ensure that setting
tool_mergeusers/uniquekeynewidtomaintain
applies.
2025081900
- 2025-08-19: improvement: #350: added hook to proceed with operations after
all tables have been merged, and before registering the end of the merge.
- If these hook's callbacks are invoked, it means that all went ok
and table mergers processed the merge with success till now. - The callbacks for this hook are meant to process any kind of operations
from Moodle internals or plugin specific tasks, that are transversal,
(operations not specific for a single table) or any kind of
aggregation operation, not updated by the table mergers. - To provide you an example, we have moved the regrading of the users and
the course recompletions into callbacks for this hook. - We think this hook will help Moodle and plugin developers to adjust the
merge users tool to better fit any Moodle instance (with a variable
number of custom Moodle changes and plugins).
- If these hook's callbacks are invoked, it means that all went ok
NOTE
Actually, with callbacks for both hooks, Moodle core and plugins
can make work this plugin as they need to merge users properly. Why?
This plugin provides a generic way to merge users, but internals from
Moodle core (subsystems, and so) and plugins really know how user's
information is managed. So, their maintainers have the full knowledge
and they can provide callbacks for both hooks:
- Callbacks for
add_settings_before_merginghook may help providing specific
database-related settings: mainly table mergers (settingtablemergers),
compound indexes (settingcompoundindexes) or user-related table columns
(settinguserfieldnames). - Callbacks for
after_merged_all_tableshook may help providing specific
post-processes.
UPGRADING
Just as a clarification: The inclusion of the hooks does not alter the
way of using this plugin at all. It will behave as it did.
However, these two hooks provide you as a developer and maintainer of your
plugin or Moodle instance powerful tools to customize the behaviour of the merge,
just placing the necessary callbacks and related stuff in your own
code, to ensure merge users is processed properly.
2025081800
- 2025-08-18: improvement: #348: added hook to load database-related settings.
- This is though to help Moodle and plugin developers to adjust their code to help
this plugin merge users properly. - The settings that are loaded by this hook are those populated on the old
config/config.phpandconfig/config.local.phpfiles. These files are not supported any more. - The content of the old
config/config.phpis now placed onclasses/local/default_db_config.php.
This must help this plugin maintainers to keep in a single place the default behaviour. - Added tests to ensure the database-related settings are kept properly.
- Priority of the settings (more priority settings are kept, in front of subsequent settings):
- Custom admin setting: the set of settings with the highest priority.
This must let administrators adjusting plugin behaviour at any time. - Hook settings: settings populated from this hook's callbacks are the second set of
settings in priority. - Default settings: the plugin's default settings are kept as with the lowest priority.
Any existing setting from hooks and custom settings will replace default ones.
- Custom admin setting: the set of settings with the highest priority.
- This is though to help Moodle and plugin developers to adjust their code to help
2025081700
- 2025-08-17: fix: #308: reportedly, extension
pcntlseems to be loaded sometimes but itspcntl_*functions
are not available. We have removed support for aborting forCtrl+C(SIGINT) usingpcntlextension.
No panic: in several instances we have, we can cancel the CLI script execution withCtrl+Cwithout
thepcntlextension loaded. It was necessary on initial version of this plugin. Nowadays it seems unnecessary. - 2025-08-17: improvement: #308: updated the CLI script help to show that when using
--alwaysrollbackoption
there is no loop for merging pairs of users.
2025081603
- 2025-0816: improvement: #244: allow resetting web user selection. Unified search and review tables.
Added extra column on search table to show whether a user is already suspended (probably already merged). - 2025-08-16: improvement: #345: move config.local.php into a new admin setting, in JSON format, for being human-readable.
- Also, consider that setting with name
alwaysRollbackwas renamed toalwaysrollbackto unify the case insensitiveness
of the rest of the configuration settings. It applies within the code and also on the CLI script parameters.
- Also, consider that setting with name
UPGRADING
Recommendation when upgrading: Keep your config/config.local.php in place. It will help
updating the value of the new admin setting tool_mergeusers/customdbsettings automatically,
without the need to convert your old config/config.local.php to JSON.
But, it is only a recommendation.
Otherwise, you will have to update that admin setting manually with the content of your previous
config/config.local.php on the new admin setting. To help you, you can use the
tool_mergeusers\local\jsonizer::to_json($customsettings) with an array with all your
$customsettings, and it will provide you the JSON content to place.
If you did not have any customization or file on config/config.local.php, you have to do nothing
with this upgrading step.
2025081500
- 2025-08-15: improvement: #328: added support for Moodle 5.0.
2025081402
- 2025-08-14: fix: #336: deleted users are excluded from everywhere when searching by and merging users.
- 2025-08-14: improvement: #281: add debug info into log when no course module is found when regrading. Thanks to @Richardvi.
- 2025-08-14: fix: #277: revisit all Moodle tables and user-related fields to
update config.php settings. Provide a CLI script to help.
2025081300
- 2025-08-13 - fix: #275: make web user search work on any database engine. Thanks to @leonstr.
- 2025-08-13 - fix: #273: exclude deleted users from the web search. Thanks to @leonstr.
2025081205
- 2025-08-12 - fix: #329: set renumber quiz attempts as the default setting.
- 2025-08-12 - fix: #331: prevents web browser alert from leaving form page on the summary page.
- 2025-08-12 - improvement: #311: use Catalyst CI. Thanks to @matthewhilton.
- 2025-08-12 - improvement: #306: remove user profile fields; use profile page hook to show merging detail. Thanks to @matthewhilton.
- 2025-08-12 - fix: #68: move logger to proper namespace. Thanks to @matthewhilton.
- 2025-08-12 - improvement: #306: define new capability to see logs, either as admin or from user profile. Thanks to @matthewhilton.
- 2025-08-12 - improvement: #306: add information about whether a user is deletable from this plugin viewpoint.
- 2025-08-12 - improvement: #306: add settings item to inform that prior custom user profile fields added by this plugin still exist and should be deleted.
There are no longer used nor updated. - 2025-08-12 - improvement: #306: add PHP API to list deletable users.
UPGRADING
Before upgrading to this version, please check your own automatization processes in case they use the plugin profile fields.
You should adapt them to use the logs from the plugin table tool_mergeusers. In this case,
we provide a PHP API on tool_mergeusers\local\last_merge::list_all_deletable_users()
to list all candidate users to be deletable. You can adapt your scripts starting from
this new API.
2025081100
- 2025-08-11 - fix: #315: replaced print_error() functions for moodle_exception. Thanks to @ManaElmountasir and @minhduchoang195.
- 2025-02-11 - bump version and update CHANGES.md
- 2025-08-11 - fix: #326: remove deprecation warnings on CLI script and tests. Thanks to @matthewhilton.
2025020505
- 2025-02-05 - bump version to make a new plugin version available for M4.5.
2025020503
- 2025-02-05 - fix: URL on old and new user profile fields definition.
- 2025-02-05 - improvement: CLI script now shows better log of merging operations.
2025020502
- 2025-02-05 #295 - fix: remove deprecation warning on CLIGathering, related to Iterator. Thanks to @CatSema.
2025020501
- 2025-02-05 - bump version, update CHANGES.md, and kept support only for M4.1.
2025020500
- 2025-02-05 - bump version and update CHANGES.md
- 2025-02-05 #283 - new feature: use custom profile fields to identify merged old and new users (to both users). Partly contributed thanks to @sampraxis and @ClausSchmidtPraxis on 2024-11-14. PHPUnit test ensures the behaviour is the expected.
- 2025-02-05 #294 - fix: pass tests on mod_assign again. Thanks to @leonstr.
- 2025-02-04 #304 - fix: set up again suspended image to merged source user.
- 2025-02-04 #253 - fix: CRLF codification passed to LF.
- 2025-01-23 #299 - fix: fix file content to get them properly uploaded into AMOS.
2025012300
- 2025-01-23 #299 - make lang file compatible with AMOS to be translatable.
- 2025-01-23 #299 - add $plugin->release property as releasing new plugin version warns it.
2025012200
- 2025-01-22 #295 - CliGathering: remove deprecation warnings from Iterator implementation.
- 2025-01-22 #292 - Bump plugin version and requires Moodle 4.5 onwards.
- CI passes on green, as before, for PHP 8.1, 8.2 and 8.3 only for core MOODLE_405_STABLE.
- version.php updated.
- Improve type detection on IDE.
- Uses new trait on the assign_test class.
- 2025-01-17 #291 - Make web administration work on merge users.
- Removed lines requiring "lib/outputcomponents.php" from two files.
2024060300
- 2024-06-03 #268 - CI: verify it is working from M4.1 to M4.4 and master. Solves #263 too.
- 2024-06-03 #268 - Fixed PHPDoc issues and revisited output from merger when running from CLI.
2023061900
- 2023-06-19 #245 - Add list of incremental changes on file CHANGES.md.
- 2023-06-19 #247 - Fix proper support for Moodle 4.2, thanks to Matthias Opitz.
2023040402
- 2023-04-13 #243 - remove unused class with API inconsistence.
2023040401
- 2023-04-04 #211 - add CSV export for merged user logs; added mergedbyuserid field, thanks to Mark Johnson.
2023040400
- 2023-04-04 Fix CI to run only for supported versions, supporting Moodle 3.11 and up.
- 2022-12-15 #228 - Add compound indexes for customcert_issues table, thanks to Leon Stringer.
- 2021-08-01 #197 - Use Github Actions, remove Travis CI usage.
2021072200
- 2021-07-23 #193 - Allow automatic Moodle Plugins release when defining git tab.
- 2021-07-14 #175 - Reaggregate completion for target user, thanks to Andrew Hancox.
- 2021-07-14 #194 - Update unit tests for Moodle 3.10+, thanks to Alistair Spark.
- 2021-07-02 #177 - Move observer functions into classes to bypass include file error, thanks to Andrew Madden.
- 2021-06-10 #181 - Guarantee processing any grade item.
- 2020-02-23 #169 - Fix wrong entries deleted in case of conflict, thanks to Tim Schroeder.
- 2019-08-18 #166 - Support for duplicated assign submissions and other fixes.
- 2019-08-16 #67 - Improve and clean up settings.php.
- 2019-08-16 #163 - Force user to keep not to be suspended.
- 2019-08-16 #161 - Split in chunks the list of record ids to delete/update to prevent buffer overflow on SQL sentences.
- 2019-08-15 #147 - Config: Add logstore_standard_log columns related to user.id.
- 2019-08-15 #151 - Config: Add composed keys for wikis.
- 2019-08-15 #146 - Fix searching by user.id on pgsql.
- 2019-08-15 #152 - Support any supported Moodle database.
Older changes
For a more extense list of changes, see git logs for changes before April 2019.
Contributors
Maintained by:
(Focus on stability and extensibility) (2025101701)
(Focus on stability and extensibility)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2025101701
Version release name: (Focus on stability and extensibility)
Maturity: Stable
Supported Moodle versions: 4.5, 5.0, 5.1
Repository URL (Git): https://github.com/jpahullo/moodle-tool_mergeusers
Repository branch:
Repository tag: 2025101701
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
2025101701
- 2025-10-17: task: #383: Moodle 5.1 compatible.
2025101700
- 2025-10-17: fix: #381: add all user-related compound indexes into default plugin settings.
- default_db_config.php updated manually with structured section about compound indexes.
- listuserfields.php CLI script improved to list all user-related compound indexes. This script must help administrators to identify other compound indexes that affect their Moodle instances.
2025101400
- 2025-10-14: fix: #382: ensure grade_grades table is merged properly. Thanks Daniel Tomé.
- Added tests for the new grade_grades table merger.
- Improved some existing tests.
- Improve Makefile to let run phpcs/phpcbf more easily.
2025092100
- 2025-09-21: improvement: #372: add output from last steps of regrading and reaggregation of course completions.
Also, reaggregation of course completion now happens inside the time of the merge process, and not after as before. - 2025-09-21: task: #362: remove YUI code. Simplified javascript code to the maximum.
2025091800
- 2025-09-18: fix: #371: listuserfields.php CLI scripts supports tables that does not exist on the XML database schema.
2025090401
- 2025-09-04: fix: #367: database settings tab did no show properly
the default nor calculated settings. - 2025-09-04: fix: #369: add PHP attributes to hook.
2025082301
- 2025-08-23: improvement: #360: new class added to manage session-based
users selection when merging users from web administration. - 2025-08-23: improvement: #358: add "suspended" tag besides the
user detail on all pages (including user search, user review and logs).
Single log page now shows the full user detail, as in the rest of pages. - 2025-08-23: fix: #358: users selection table showed always the user
detail of the user to remove. Now, it shows properly both users.
It was detected while working on the improvement of #358.
2025082200
- 2025-08-22: improvement: #356: code reorganization on the whole plugin.
- Placed all suitable file under
/classes/for autoloading. - Revisited all files (except
/tests/) with phpcs (usinglocal_codechecker) - Removed content from
lib.phpin favour ofsettingslib.phpand
a new classdatabase_transactions::are_supported(). - Added a
Makefilewith some targets for helping while developing. - All tests passes again.
- All clicks on the web work again.
- Moved the link to see merge logs into the
Reportsadministration menu.
- Placed all suitable file under
UPGRADING
When upgrading to this version, you have to choose one of these paths:
- In case you have local plugin customizations: you must check twice
the new plugin structure since there has been a major refactor
of the whole plugin. Thelib/directory was removed, and
most of the plugin classes were moved inside theclasses/directory
for a better code organization and with the benefit of autoloading.
Also, we removed the vast majority of functions from thelib.php,
leaving there only the necessary Moodle callbacks.
Update your local customizations appropriately according to new
classes and file structure. - In case you DO NOT have local plugin customizations: you can freely
upgrade the plugin without worrying.
2025082000
- 2025-08-20: fix: #354: ensure that setting
tool_mergeusers/uniquekeynewidtomaintain
applies.
2025081900
- 2025-08-19: improvement: #350: added hook to proceed with operations after
all tables have been merged, and before registering the end of the merge.
- If these hook's callbacks are invoked, it means that all went ok
and table mergers processed the merge with success till now. - The callbacks for this hook are meant to process any kind of operations
from Moodle internals or plugin specific tasks, that are transversal,
(operations not specific for a single table) or any kind of
aggregation operation, not updated by the table mergers. - To provide you an example, we have moved the regrading of the users and
the course recompletions into callbacks for this hook. - We think this hook will help Moodle and plugin developers to adjust the
merge users tool to better fit any Moodle instance (with a variable
number of custom Moodle changes and plugins).
- If these hook's callbacks are invoked, it means that all went ok
NOTE
Actually, with callbacks for both hooks, Moodle core and plugins
can make work this plugin as they need to merge users properly. Why?
This plugin provides a generic way to merge users, but internals from
Moodle core (subsystems, and so) and plugins really know how user's
information is managed. So, their maintainers have the full knowledge
and they can provide callbacks for both hooks:
- Callbacks for
add_settings_before_merginghook may help providing specific
database-related settings: mainly table mergers (settingtablemergers),
compound indexes (settingcompoundindexes) or user-related table columns
(settinguserfieldnames). - Callbacks for
after_merged_all_tableshook may help providing specific
post-processes.
UPGRADING
Just as a clarification: The inclusion of the hooks does not alter the
way of using this plugin at all. It will behave as it did.
However, these two hooks provide you as a developer and maintainer of your
plugin or Moodle instance powerful tools to customize the behaviour of the merge,
just placing the necessary callbacks and related stuff in your own
code, to ensure merge users is processed properly.
2025081800
- 2025-08-18: improvement: #348: added hook to load database-related settings.
- This is though to help Moodle and plugin developers to adjust their code to help
this plugin merge users properly. - The settings that are loaded by this hook are those populated on the old
config/config.phpandconfig/config.local.phpfiles. These files are not supported any more. - The content of the old
config/config.phpis now placed onclasses/local/default_db_config.php.
This must help this plugin maintainers to keep in a single place the default behaviour. - Added tests to ensure the database-related settings are kept properly.
- Priority of the settings (more priority settings are kept, in front of subsequent settings):
- Custom admin setting: the set of settings with the highest priority.
This must let administrators adjusting plugin behaviour at any time. - Hook settings: settings populated from this hook's callbacks are the second set of
settings in priority. - Default settings: the plugin's default settings are kept as with the lowest priority.
Any existing setting from hooks and custom settings will replace default ones.
- Custom admin setting: the set of settings with the highest priority.
- This is though to help Moodle and plugin developers to adjust their code to help
2025081700
- 2025-08-17: fix: #308: reportedly, extension
pcntlseems to be loaded sometimes but itspcntl_*functions
are not available. We have removed support for aborting forCtrl+C(SIGINT) usingpcntlextension.
No panic: in several instances we have, we can cancel the CLI script execution withCtrl+Cwithout
thepcntlextension loaded. It was necessary on initial version of this plugin. Nowadays it seems unnecessary. - 2025-08-17: improvement: #308: updated the CLI script help to show that when using
--alwaysrollbackoption
there is no loop for merging pairs of users.
2025081603
- 2025-0816: improvement: #244: allow resetting web user selection. Unified search and review tables.
Added extra column on search table to show whether a user is already suspended (probably already merged). - 2025-08-16: improvement: #345: move config.local.php into a new admin setting, in JSON format, for being human-readable.
- Also, consider that setting with name
alwaysRollbackwas renamed toalwaysrollbackto unify the case insensitiveness
of the rest of the configuration settings. It applies within the code and also on the CLI script parameters.
- Also, consider that setting with name
UPGRADING
Recommendation when upgrading: Keep your config/config.local.php in place. It will help
updating the value of the new admin setting tool_mergeusers/customdbsettings automatically,
without the need to convert your old config/config.local.php to JSON.
But, it is only a recommendation.
Otherwise, you will have to update that admin setting manually with the content of your previous
config/config.local.php on the new admin setting. To help you, you can use the
tool_mergeusers\local\jsonizer::to_json($customsettings) with an array with all your
$customsettings, and it will provide you the JSON content to place.
If you did not have any customization or file on config/config.local.php, you have to do nothing
with this upgrading step.
2025081500
- 2025-08-15: improvement: #328: added support for Moodle 5.0.
2025081402
- 2025-08-14: fix: #336: deleted users are excluded from everywhere when searching by and merging users.
- 2025-08-14: improvement: #281: add debug info into log when no course module is found when regrading. Thanks to @Richardvi.
- 2025-08-14: fix: #277: revisit all Moodle tables and user-related fields to
update config.php settings. Provide a CLI script to help.
2025081300
- 2025-08-13 - fix: #275: make web user search work on any database engine. Thanks to @leonstr.
- 2025-08-13 - fix: #273: exclude deleted users from the web search. Thanks to @leonstr.
2025081205
- 2025-08-12 - fix: #329: set renumber quiz attempts as the default setting.
- 2025-08-12 - fix: #331: prevents web browser alert from leaving form page on the summary page.
- 2025-08-12 - improvement: #311: use Catalyst CI. Thanks to @matthewhilton.
- 2025-08-12 - improvement: #306: remove user profile fields; use profile page hook to show merging detail. Thanks to @matthewhilton.
- 2025-08-12 - fix: #68: move logger to proper namespace. Thanks to @matthewhilton.
- 2025-08-12 - improvement: #306: define new capability to see logs, either as admin or from user profile. Thanks to @matthewhilton.
- 2025-08-12 - improvement: #306: add information about whether a user is deletable from this plugin viewpoint.
- 2025-08-12 - improvement: #306: add settings item to inform that prior custom user profile fields added by this plugin still exist and should be deleted.
There are no longer used nor updated. - 2025-08-12 - improvement: #306: add PHP API to list deletable users.
UPGRADING
Before upgrading to this version, please check your own automatization processes in case they use the plugin profile fields.
You should adapt them to use the logs from the plugin table tool_mergeusers. In this case,
we provide a PHP API on tool_mergeusers\local\last_merge::list_all_deletable_users()
to list all candidate users to be deletable. You can adapt your scripts starting from
this new API.
2025081100
- 2025-08-11 - fix: #315: replaced print_error() functions for moodle_exception. Thanks to @ManaElmountasir and @minhduchoang195.
- 2025-02-11 - bump version and update CHANGES.md
- 2025-08-11 - fix: #326: remove deprecation warnings on CLI script and tests. Thanks to @matthewhilton.
2025020505
- 2025-02-05 - bump version to make a new plugin version available for M4.5.
2025020503
- 2025-02-05 - fix: URL on old and new user profile fields definition.
- 2025-02-05 - improvement: CLI script now shows better log of merging operations.
2025020502
- 2025-02-05 #295 - fix: remove deprecation warning on CLIGathering, related to Iterator. Thanks to @CatSema.
2025020501
- 2025-02-05 - bump version, update CHANGES.md, and kept support only for M4.1.
2025020500
- 2025-02-05 - bump version and update CHANGES.md
- 2025-02-05 #283 - new feature: use custom profile fields to identify merged old and new users (to both users). Partly contributed thanks to @sampraxis and @ClausSchmidtPraxis on 2024-11-14. PHPUnit test ensures the behaviour is the expected.
- 2025-02-05 #294 - fix: pass tests on mod_assign again. Thanks to @leonstr.
- 2025-02-04 #304 - fix: set up again suspended image to merged source user.
- 2025-02-04 #253 - fix: CRLF codification passed to LF.
- 2025-01-23 #299 - fix: fix file content to get them properly uploaded into AMOS.
2025012300
- 2025-01-23 #299 - make lang file compatible with AMOS to be translatable.
- 2025-01-23 #299 - add $plugin->release property as releasing new plugin version warns it.
2025012200
- 2025-01-22 #295 - CliGathering: remove deprecation warnings from Iterator implementation.
- 2025-01-22 #292 - Bump plugin version and requires Moodle 4.5 onwards.
- CI passes on green, as before, for PHP 8.1, 8.2 and 8.3 only for core MOODLE_405_STABLE.
- version.php updated.
- Improve type detection on IDE.
- Uses new trait on the assign_test class.
- 2025-01-17 #291 - Make web administration work on merge users.
- Removed lines requiring "lib/outputcomponents.php" from two files.
2024060300
- 2024-06-03 #268 - CI: verify it is working from M4.1 to M4.4 and master. Solves #263 too.
- 2024-06-03 #268 - Fixed PHPDoc issues and revisited output from merger when running from CLI.
2023061900
- 2023-06-19 #245 - Add list of incremental changes on file CHANGES.md.
- 2023-06-19 #247 - Fix proper support for Moodle 4.2, thanks to Matthias Opitz.
2023040402
- 2023-04-13 #243 - remove unused class with API inconsistence.
2023040401
- 2023-04-04 #211 - add CSV export for merged user logs; added mergedbyuserid field, thanks to Mark Johnson.
2023040400
- 2023-04-04 Fix CI to run only for supported versions, supporting Moodle 3.11 and up.
- 2022-12-15 #228 - Add compound indexes for customcert_issues table, thanks to Leon Stringer.
- 2021-08-01 #197 - Use Github Actions, remove Travis CI usage.
2021072200
- 2021-07-23 #193 - Allow automatic Moodle Plugins release when defining git tab.
- 2021-07-14 #175 - Reaggregate completion for target user, thanks to Andrew Hancox.
- 2021-07-14 #194 - Update unit tests for Moodle 3.10+, thanks to Alistair Spark.
- 2021-07-02 #177 - Move observer functions into classes to bypass include file error, thanks to Andrew Madden.
- 2021-06-10 #181 - Guarantee processing any grade item.
- 2020-02-23 #169 - Fix wrong entries deleted in case of conflict, thanks to Tim Schroeder.
- 2019-08-18 #166 - Support for duplicated assign submissions and other fixes.
- 2019-08-16 #67 - Improve and clean up settings.php.
- 2019-08-16 #163 - Force user to keep not to be suspended.
- 2019-08-16 #161 - Split in chunks the list of record ids to delete/update to prevent buffer overflow on SQL sentences.
- 2019-08-15 #147 - Config: Add logstore_standard_log columns related to user.id.
- 2019-08-15 #151 - Config: Add composed keys for wikis.
- 2019-08-15 #146 - Fix searching by user.id on pgsql.
- 2019-08-15 #152 - Support any supported Moodle database.
Older changes
For a more extense list of changes, see git logs for changes before April 2019.
Contributors
Maintained by:
(Focus on stability and extensibility) (2025101700)
(Focus on stability and extensibility)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2025101700
Version release name: (Focus on stability and extensibility)
Maturity: Stable
Supported Moodle versions: 4.5, 5.0
Repository URL (Git): https://github.com/jpahullo/moodle-tool_mergeusers
Repository branch:
Repository tag: 2025101700
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
2025101700
- 2025-10-17: fix: #381: add all user-related compound indexes into default plugin settings.
- default_db_config.php updated manually with structured section about compound indexes.
- listuserfields.php CLI script improved to list all user-related compound indexes. This script must help administrators to identify other compound indexes that affect their Moodle instances.
2025101400
- 2025-10-14: fix: #382: ensure grade_grades table is merged properly. Thanks Daniel Tomé.
- Added tests for the new grade_grades table merger.
- Improved some existing tests.
- Improve Makefile to let run phpcs/phpcbf more easily.
2025092100
- 2025-09-21: improvement: #372: add output from last steps of regrading and reaggregation of course completions.
Also, reaggregation of course completion now happens inside the time of the merge process, and not after as before. - 2025-09-21: task: #362: remove YUI code. Simplified javascript code to the maximum.
2025091800
- 2025-09-18: fix: #371: listuserfields.php CLI scripts supports tables that does not exist on the XML database schema.
2025090401
- 2025-09-04: fix: #367: database settings tab did no show properly
the default nor calculated settings. - 2025-09-04: fix: #369: add PHP attributes to hook.
2025082301
- 2025-08-23: improvement: #360: new class added to manage session-based
users selection when merging users from web administration. - 2025-08-23: improvement: #358: add "suspended" tag besides the
user detail on all pages (including user search, user review and logs).
Single log page now shows the full user detail, as in the rest of pages. - 2025-08-23: fix: #358: users selection table showed always the user
detail of the user to remove. Now, it shows properly both users.
It was detected while working on the improvement of #358.
2025082200
- 2025-08-22: improvement: #356: code reorganization on the whole plugin.
- Placed all suitable file under
/classes/for autoloading. - Revisited all files (except
/tests/) with phpcs (usinglocal_codechecker) - Removed content from
lib.phpin favour ofsettingslib.phpand
a new classdatabase_transactions::are_supported(). - Added a
Makefilewith some targets for helping while developing. - All tests passes again.
- All clicks on the web work again.
- Moved the link to see merge logs into the
Reportsadministration menu.
- Placed all suitable file under
UPGRADING
When upgrading to this version, you have to choose one of these paths:
- In case you have local plugin customizations: you must check twice
the new plugin structure since there has been a major refactor
of the whole plugin. Thelib/directory was removed, and
most of the plugin classes were moved inside theclasses/directory
for a better code organization and with the benefit of autoloading.
Also, we removed the vast majority of functions from thelib.php,
leaving there only the necessary Moodle callbacks.
Update your local customizations appropriately according to new
classes and file structure. - In case you DO NOT have local plugin customizations: you can freely
upgrade the plugin without worrying.
2025082000
- 2025-08-20: fix: #354: ensure that setting
tool_mergeusers/uniquekeynewidtomaintain
applies.
2025081900
- 2025-08-19: improvement: #350: added hook to proceed with operations after
all tables have been merged, and before registering the end of the merge.
- If these hook's callbacks are invoked, it means that all went ok
and table mergers processed the merge with success till now. - The callbacks for this hook are meant to process any kind of operations
from Moodle internals or plugin specific tasks, that are transversal,
(operations not specific for a single table) or any kind of
aggregation operation, not updated by the table mergers. - To provide you an example, we have moved the regrading of the users and
the course recompletions into callbacks for this hook. - We think this hook will help Moodle and plugin developers to adjust the
merge users tool to better fit any Moodle instance (with a variable
number of custom Moodle changes and plugins).
- If these hook's callbacks are invoked, it means that all went ok
NOTE
Actually, with callbacks for both hooks, Moodle core and plugins
can make work this plugin as they need to merge users properly. Why?
This plugin provides a generic way to merge users, but internals from
Moodle core (subsystems, and so) and plugins really know how user's
information is managed. So, their maintainers have the full knowledge
and they can provide callbacks for both hooks:
- Callbacks for
add_settings_before_merginghook may help providing specific
database-related settings: mainly table mergers (settingtablemergers),
compound indexes (settingcompoundindexes) or user-related table columns
(settinguserfieldnames). - Callbacks for
after_merged_all_tableshook may help providing specific
post-processes.
UPGRADING
Just as a clarification: The inclusion of the hooks does not alter the
way of using this plugin at all. It will behave as it did.
However, these two hooks provide you as a developer and maintainer of your
plugin or Moodle instance powerful tools to customize the behaviour of the merge,
just placing the necessary callbacks and related stuff in your own
code, to ensure merge users is processed properly.
2025081800
- 2025-08-18: improvement: #348: added hook to load database-related settings.
- This is though to help Moodle and plugin developers to adjust their code to help
this plugin merge users properly. - The settings that are loaded by this hook are those populated on the old
config/config.phpandconfig/config.local.phpfiles. These files are not supported any more. - The content of the old
config/config.phpis now placed onclasses/local/default_db_config.php.
This must help this plugin maintainers to keep in a single place the default behaviour. - Added tests to ensure the database-related settings are kept properly.
- Priority of the settings (more priority settings are kept, in front of subsequent settings):
- Custom admin setting: the set of settings with the highest priority.
This must let administrators adjusting plugin behaviour at any time. - Hook settings: settings populated from this hook's callbacks are the second set of
settings in priority. - Default settings: the plugin's default settings are kept as with the lowest priority.
Any existing setting from hooks and custom settings will replace default ones.
- Custom admin setting: the set of settings with the highest priority.
- This is though to help Moodle and plugin developers to adjust their code to help
2025081700
- 2025-08-17: fix: #308: reportedly, extension
pcntlseems to be loaded sometimes but itspcntl_*functions
are not available. We have removed support for aborting forCtrl+C(SIGINT) usingpcntlextension.
No panic: in several instances we have, we can cancel the CLI script execution withCtrl+Cwithout
thepcntlextension loaded. It was necessary on initial version of this plugin. Nowadays it seems unnecessary. - 2025-08-17: improvement: #308: updated the CLI script help to show that when using
--alwaysrollbackoption
there is no loop for merging pairs of users.
2025081603
- 2025-0816: improvement: #244: allow resetting web user selection. Unified search and review tables.
Added extra column on search table to show whether a user is already suspended (probably already merged). - 2025-08-16: improvement: #345: move config.local.php into a new admin setting, in JSON format, for being human-readable.
- Also, consider that setting with name
alwaysRollbackwas renamed toalwaysrollbackto unify the case insensitiveness
of the rest of the configuration settings. It applies within the code and also on the CLI script parameters.
- Also, consider that setting with name
UPGRADING
Recommendation when upgrading: Keep your config/config.local.php in place. It will help
updating the value of the new admin setting tool_mergeusers/customdbsettings automatically,
without the need to convert your old config/config.local.php to JSON.
But, it is only a recommendation.
Otherwise, you will have to update that admin setting manually with the content of your previous
config/config.local.php on the new admin setting. To help you, you can use the
tool_mergeusers\local\jsonizer::to_json($customsettings) with an array with all your
$customsettings, and it will provide you the JSON content to place.
If you did not have any customization or file on config/config.local.php, you have to do nothing
with this upgrading step.
2025081500
- 2025-08-15: improvement: #328: added support for Moodle 5.0.
2025081402
- 2025-08-14: fix: #336: deleted users are excluded from everywhere when searching by and merging users.
- 2025-08-14: improvement: #281: add debug info into log when no course module is found when regrading. Thanks to @Richardvi.
- 2025-08-14: fix: #277: revisit all Moodle tables and user-related fields to
update config.php settings. Provide a CLI script to help.
2025081300
- 2025-08-13 - fix: #275: make web user search work on any database engine. Thanks to @leonstr.
- 2025-08-13 - fix: #273: exclude deleted users from the web search. Thanks to @leonstr.
2025081205
- 2025-08-12 - fix: #329: set renumber quiz attempts as the default setting.
- 2025-08-12 - fix: #331: prevents web browser alert from leaving form page on the summary page.
- 2025-08-12 - improvement: #311: use Catalyst CI. Thanks to @matthewhilton.
- 2025-08-12 - improvement: #306: remove user profile fields; use profile page hook to show merging detail. Thanks to @matthewhilton.
- 2025-08-12 - fix: #68: move logger to proper namespace. Thanks to @matthewhilton.
- 2025-08-12 - improvement: #306: define new capability to see logs, either as admin or from user profile. Thanks to @matthewhilton.
- 2025-08-12 - improvement: #306: add information about whether a user is deletable from this plugin viewpoint.
- 2025-08-12 - improvement: #306: add settings item to inform that prior custom user profile fields added by this plugin still exist and should be deleted.
There are no longer used nor updated. - 2025-08-12 - improvement: #306: add PHP API to list deletable users.
UPGRADING
Before upgrading to this version, please check your own automatization processes in case they use the plugin profile fields.
You should adapt them to use the logs from the plugin table tool_mergeusers. In this case,
we provide a PHP API on tool_mergeusers\local\last_merge::list_all_deletable_users()
to list all candidate users to be deletable. You can adapt your scripts starting from
this new API.
2025081100
- 2025-08-11 - fix: #315: replaced print_error() functions for moodle_exception. Thanks to @ManaElmountasir and @minhduchoang195.
- 2025-02-11 - bump version and update CHANGES.md
- 2025-08-11 - fix: #326: remove deprecation warnings on CLI script and tests. Thanks to @matthewhilton.
2025020505
- 2025-02-05 - bump version to make a new plugin version available for M4.5.
2025020503
- 2025-02-05 - fix: URL on old and new user profile fields definition.
- 2025-02-05 - improvement: CLI script now shows better log of merging operations.
2025020502
- 2025-02-05 #295 - fix: remove deprecation warning on CLIGathering, related to Iterator. Thanks to @CatSema.
2025020501
- 2025-02-05 - bump version, update CHANGES.md, and kept support only for M4.1.
2025020500
- 2025-02-05 - bump version and update CHANGES.md
- 2025-02-05 #283 - new feature: use custom profile fields to identify merged old and new users (to both users). Partly contributed thanks to @sampraxis and @ClausSchmidtPraxis on 2024-11-14. PHPUnit test ensures the behaviour is the expected.
- 2025-02-05 #294 - fix: pass tests on mod_assign again. Thanks to @leonstr.
- 2025-02-04 #304 - fix: set up again suspended image to merged source user.
- 2025-02-04 #253 - fix: CRLF codification passed to LF.
- 2025-01-23 #299 - fix: fix file content to get them properly uploaded into AMOS.
2025012300
- 2025-01-23 #299 - make lang file compatible with AMOS to be translatable.
- 2025-01-23 #299 - add $plugin->release property as releasing new plugin version warns it.
2025012200
- 2025-01-22 #295 - CliGathering: remove deprecation warnings from Iterator implementation.
- 2025-01-22 #292 - Bump plugin version and requires Moodle 4.5 onwards.
- CI passes on green, as before, for PHP 8.1, 8.2 and 8.3 only for core MOODLE_405_STABLE.
- version.php updated.
- Improve type detection on IDE.
- Uses new trait on the assign_test class.
- 2025-01-17 #291 - Make web administration work on merge users.
- Removed lines requiring "lib/outputcomponents.php" from two files.
2024060300
- 2024-06-03 #268 - CI: verify it is working from M4.1 to M4.4 and master. Solves #263 too.
- 2024-06-03 #268 - Fixed PHPDoc issues and revisited output from merger when running from CLI.
2023061900
- 2023-06-19 #245 - Add list of incremental changes on file CHANGES.md.
- 2023-06-19 #247 - Fix proper support for Moodle 4.2, thanks to Matthias Opitz.
2023040402
- 2023-04-13 #243 - remove unused class with API inconsistence.
2023040401
- 2023-04-04 #211 - add CSV export for merged user logs; added mergedbyuserid field, thanks to Mark Johnson.
2023040400
- 2023-04-04 Fix CI to run only for supported versions, supporting Moodle 3.11 and up.
- 2022-12-15 #228 - Add compound indexes for customcert_issues table, thanks to Leon Stringer.
- 2021-08-01 #197 - Use Github Actions, remove Travis CI usage.
2021072200
- 2021-07-23 #193 - Allow automatic Moodle Plugins release when defining git tab.
- 2021-07-14 #175 - Reaggregate completion for target user, thanks to Andrew Hancox.
- 2021-07-14 #194 - Update unit tests for Moodle 3.10+, thanks to Alistair Spark.
- 2021-07-02 #177 - Move observer functions into classes to bypass include file error, thanks to Andrew Madden.
- 2021-06-10 #181 - Guarantee processing any grade item.
- 2020-02-23 #169 - Fix wrong entries deleted in case of conflict, thanks to Tim Schroeder.
- 2019-08-18 #166 - Support for duplicated assign submissions and other fixes.
- 2019-08-16 #67 - Improve and clean up settings.php.
- 2019-08-16 #163 - Force user to keep not to be suspended.
- 2019-08-16 #161 - Split in chunks the list of record ids to delete/update to prevent buffer overflow on SQL sentences.
- 2019-08-15 #147 - Config: Add logstore_standard_log columns related to user.id.
- 2019-08-15 #151 - Config: Add composed keys for wikis.
- 2019-08-15 #146 - Fix searching by user.id on pgsql.
- 2019-08-15 #152 - Support any supported Moodle database.
Older changes
For a more extense list of changes, see git logs for changes before April 2019.
Contributors
Maintained by:
(Mode vacation: off) (2025090401)
(Mode vacation: off)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2025090401
Version release name: (Mode vacation: off)
Maturity: Stable
Supported Moodle versions: 4.5, 5.0
Repository URL (Git): https://github.com/jpahullo/moodle-tool_mergeusers
Repository branch:
Repository tag: 2025090401
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
2025090401
- 2025-09-04: fix: #367: database settings tab did no show properly
the default nor calculated settings. - 2025-09-04: fix: #369: add PHP attributes to hook.
2025082301
- 2025-08-23: improvement: #360: new class added to manage session-based
users selection when merging users from web administration. - 2025-08-23: improvement: #358: add "suspended" tag besides the
user detail on all pages (including user search, user review and logs).
Single log page now shows the full user detail, as in the rest of pages. - 2025-08-23: fix: #358: users selection table showed always the user
detail of the user to remove. Now, it shows properly both users.
It was detected while working on the improvement of #358.
2025082200
- 2025-08-22: improvement: #356: code reorganization on the whole plugin.
- Placed all suitable file under
/classes/for autoloading. - Revisited all files (except
/tests/) with phpcs (usinglocal_codechecker) - Removed content from
lib.phpin favour ofsettingslib.phpand
a new classdatabase_transactions::are_supported(). - Added a
Makefilewith some targets for helping while developing. - All tests passes again.
- All clicks on the web work again.
- Moved the link to see merge logs into the
Reportsadministration menu.
- Placed all suitable file under
UPGRADING
When upgrading to this version, you have to choose one of these paths:
- In case you have local plugin customizations: you must check twice
the new plugin structure since there has been a major refactor
of the whole plugin. Thelib/directory was removed, and
most of the plugin classes were moved inside theclasses/directory
for a better code organization and with the benefit of autoloading.
Also, we removed the vast majority of functions from thelib.php,
leaving there only the necessary Moodle callbacks.
Update your local customizations appropriately according to new
classes and file structure. - In case you DO NOT have local plugin customizations: you can freely
upgrade the plugin without worrying.
2025082000
- 2025-08-20: fix: #354: ensure that setting
tool_mergeusers/uniquekeynewidtomaintain
applies.
2025081900
- 2025-08-19: improvement: #350: added hook to proceed with operations after
all tables have been merged, and before registering the end of the merge.
- If these hook's callbacks are invoked, it means that all went ok
and table mergers processed the merge with success till now. - The callbacks for this hook are meant to process any kind of operations
from Moodle internals or plugin specific tasks, that are transversal,
(operations not specific for a single table) or any kind of
aggregation operation, not updated by the table mergers. - To provide you an example, we have moved the regrading of the users and
the course recompletions into callbacks for this hook. - We think this hook will help Moodle and plugin developers to adjust the
merge users tool to better fit any Moodle instance (with a variable
number of custom Moodle changes and plugins).
- If these hook's callbacks are invoked, it means that all went ok
NOTE
Actually, with callbacks for both hooks, Moodle core and plugins
can make work this plugin as they need to merge users properly. Why?
This plugin provides a generic way to merge users, but internals from
Moodle core (subsystems, and so) and plugins really know how user's
information is managed. So, their maintainers have the full knowledge
and they can provide callbacks for both hooks:
- Callbacks for
add_settings_before_merginghook may help providing specific
database-related settings: mainly table mergers (settingtablemergers),
compound indexes (settingcompoundindexes) or user-related table columns
(settinguserfieldnames). - Callbacks for
after_merged_all_tableshook may help providing specific
post-processes.
UPGRADING
Just as a clarification: The inclusion of the hooks does not alter the
way of using this plugin at all. It will behave as it did.
However, these two hooks provide you as a developer and maintainer of your
plugin or Moodle instance powerful tools to customize the behaviour of the merge,
just placing the necessary callbacks and related stuff in your own
code, to ensure merge users is processed properly.
2025081800
- 2025-08-18: improvement: #348: added hook to load database-related settings.
- This is though to help Moodle and plugin developers to adjust their code to help
this plugin merge users properly. - The settings that are loaded by this hook are those populated on the old
config/config.phpandconfig/config.local.phpfiles. These files are not supported any more. - The content of the old
config/config.phpis now placed onclasses/local/default_db_config.php.
This must help this plugin maintainers to keep in a single place the default behaviour. - Added tests to ensure the database-related settings are kept properly.
- Priority of the settings (more priority settings are kept, in front of subsequent settings):
- Custom admin setting: the set of settings with the highest priority.
This must let administrators adjusting plugin behaviour at any time. - Hook settings: settings populated from this hook's callbacks are the second set of
settings in priority. - Default settings: the plugin's default settings are kept as with the lowest priority.
Any existing setting from hooks and custom settings will replace default ones.
- Custom admin setting: the set of settings with the highest priority.
- This is though to help Moodle and plugin developers to adjust their code to help
2025081700
- 2025-08-17: fix: #308: reportedly, extension
pcntlseems to be loaded sometimes but itspcntl_*functions
are not available. We have removed support for aborting forCtrl+C(SIGINT) usingpcntlextension.
No panic: in several instances we have, we can cancel the CLI script execution withCtrl+Cwithout
thepcntlextension loaded. It was necessary on initial version of this plugin. Nowadays it seems unnecessary. - 2025-08-17: improvement: #308: updated the CLI script help to show that when using
--alwaysrollbackoption
there is no loop for merging pairs of users.
2025081603
- 2025-0816: improvement: #244: allow resetting web user selection. Unified search and review tables.
Added extra column on search table to show whether a user is already suspended (probably already merged). - 2025-08-16: improvement: #345: move config.local.php into a new admin setting, in JSON format, for being human-readable.
- Also, consider that setting with name
alwaysRollbackwas renamed toalwaysrollbackto unify the case insensitiveness
of the rest of the configuration settings. It applies within the code and also on the CLI script parameters.
- Also, consider that setting with name
UPGRADING
Recommendation when upgrading: Keep your config/config.local.php in place. It will help
updating the value of the new admin setting tool_mergeusers/customdbsettings automatically,
without the need to convert your old config/config.local.php to JSON.
But, it is only a recommendation.
Otherwise, you will have to update that admin setting manually with the content of your previous
config/config.local.php on the new admin setting. To help you, you can use the
tool_mergeusers\local\jsonizer::to_json($customsettings) with an array with all your
$customsettings, and it will provide you the JSON content to place.
If you did not have any customization or file on config/config.local.php, you have to do nothing
with this upgrading step.
2025081500
- 2025-08-15: improvement: #328: added support for Moodle 5.0.
2025081402
- 2025-08-14: fix: #336: deleted users are excluded from everywhere when searching by and merging users.
- 2025-08-14: improvement: #281: add debug info into log when no course module is found when regrading. Thanks to @Richardvi.
- 2025-08-14: fix: #277: revisit all Moodle tables and user-related fields to
update config.php settings. Provide a CLI script to help.
2025081300
- 2025-08-13 - fix: #275: make web user search work on any database engine. Thanks to @leonstr.
- 2025-08-13 - fix: #273: exclude deleted users from the web search. Thanks to @leonstr.
2025081205
- 2025-08-12 - fix: #329: set renumber quiz attempts as the default setting.
- 2025-08-12 - fix: #331: prevents web browser alert from leaving form page on the summary page.
- 2025-08-12 - improvement: #311: use Catalyst CI. Thanks to @matthewhilton.
- 2025-08-12 - improvement: #306: remove user profile fields; use profile page hook to show merging detail. Thanks to @matthewhilton.
- 2025-08-12 - fix: #68: move logger to proper namespace. Thanks to @matthewhilton.
- 2025-08-12 - improvement: #306: define new capability to see logs, either as admin or from user profile. Thanks to @matthewhilton.
- 2025-08-12 - improvement: #306: add information about whether a user is deletable from this plugin viewpoint.
- 2025-08-12 - improvement: #306: add settings item to inform that prior custom user profile fields added by this plugin still exist and should be deleted.
There are no longer used nor updated. - 2025-08-12 - improvement: #306: add PHP API to list deletable users.
UPGRADING
Before upgrading to this version, please check your own automatization processes in case they use the plugin profile fields.
You should adapt them to use the logs from the plugin table tool_mergeusers. In this case,
we provide a PHP API on tool_mergeusers\local\last_merge::list_all_deletable_users()
to list all candidate users to be deletable. You can adapt your scripts starting from
this new API.
2025081100
- 2025-08-11 - fix: #315: replaced print_error() functions for moodle_exception. Thanks to @ManaElmountasir and @minhduchoang195.
- 2025-02-11 - bump version and update CHANGES.md
- 2025-08-11 - fix: #326: remove deprecation warnings on CLI script and tests. Thanks to @matthewhilton.
2025020505
- 2025-02-05 - bump version to make a new plugin version available for M4.5.
2025020503
- 2025-02-05 - fix: URL on old and new user profile fields definition.
- 2025-02-05 - improvement: CLI script now shows better log of merging operations.
2025020502
- 2025-02-05 #295 - fix: remove deprecation warning on CLIGathering, related to Iterator. Thanks to @CatSema.
2025020501
- 2025-02-05 - bump version, update CHANGES.md, and kept support only for M4.1.
2025020500
- 2025-02-05 - bump version and update CHANGES.md
- 2025-02-05 #283 - new feature: use custom profile fields to identify merged old and new users (to both users). Partly contributed thanks to @sampraxis and @ClausSchmidtPraxis on 2024-11-14. PHPUnit test ensures the behaviour is the expected.
- 2025-02-05 #294 - fix: pass tests on mod_assign again. Thanks to @leonstr.
- 2025-02-04 #304 - fix: set up again suspended image to merged source user.
- 2025-02-04 #253 - fix: CRLF codification passed to LF.
- 2025-01-23 #299 - fix: fix file content to get them properly uploaded into AMOS.
2025012300
- 2025-01-23 #299 - make lang file compatible with AMOS to be translatable.
- 2025-01-23 #299 - add $plugin->release property as releasing new plugin version warns it.
2025012200
- 2025-01-22 #295 - CliGathering: remove deprecation warnings from Iterator implementation.
- 2025-01-22 #292 - Bump plugin version and requires Moodle 4.5 onwards.
- CI passes on green, as before, for PHP 8.1, 8.2 and 8.3 only for core MOODLE_405_STABLE.
- version.php updated.
- Improve type detection on IDE.
- Uses new trait on the assign_test class.
- 2025-01-17 #291 - Make web administration work on merge users.
- Removed lines requiring "lib/outputcomponents.php" from two files.
2024060300
- 2024-06-03 #268 - CI: verify it is working from M4.1 to M4.4 and master. Solves #263 too.
- 2024-06-03 #268 - Fixed PHPDoc issues and revisited output from merger when running from CLI.
2023061900
- 2023-06-19 #245 - Add list of incremental changes on file CHANGES.md.
- 2023-06-19 #247 - Fix proper support for Moodle 4.2, thanks to Matthias Opitz.
2023040402
- 2023-04-13 #243 - remove unused class with API inconsistence.
2023040401
- 2023-04-04 #211 - add CSV export for merged user logs; added mergedbyuserid field, thanks to Mark Johnson.
2023040400
- 2023-04-04 Fix CI to run only for supported versions, supporting Moodle 3.11 and up.
- 2022-12-15 #228 - Add compound indexes for customcert_issues table, thanks to Leon Stringer.
- 2021-08-01 #197 - Use Github Actions, remove Travis CI usage.
2021072200
- 2021-07-23 #193 - Allow automatic Moodle Plugins release when defining git tab.
- 2021-07-14 #175 - Reaggregate completion for target user, thanks to Andrew Hancox.
- 2021-07-14 #194 - Update unit tests for Moodle 3.10+, thanks to Alistair Spark.
- 2021-07-02 #177 - Move observer functions into classes to bypass include file error, thanks to Andrew Madden.
- 2021-06-10 #181 - Guarantee processing any grade item.
- 2020-02-23 #169 - Fix wrong entries deleted in case of conflict, thanks to Tim Schroeder.
- 2019-08-18 #166 - Support for duplicated assign submissions and other fixes.
- 2019-08-16 #67 - Improve and clean up settings.php.
- 2019-08-16 #163 - Force user to keep not to be suspended.
- 2019-08-16 #161 - Split in chunks the list of record ids to delete/update to prevent buffer overflow on SQL sentences.
- 2019-08-15 #147 - Config: Add logstore_standard_log columns related to user.id.
- 2019-08-15 #151 - Config: Add composed keys for wikis.
- 2019-08-15 #146 - Fix searching by user.id on pgsql.
- 2019-08-15 #152 - Support any supported Moodle database.
Older changes
For a more extense list of changes, see git logs for changes before April 2019.
Contributors
Maintained by:
2025020505 (Happy 2025) (2025020505)
2025020505 (Happy 2025)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2025020505
Version release name: 2025020505 (Happy 2025)
Maturity: Stable
Supported Moodle versions: 4.5
Repository URL (Git): https://github.com/jpahullo/moodle-tool_mergeusers
Repository branch:
Repository tag: 2025020505
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
2025020505
- 2025-02-05 - bump version to make a new plugin version available for M4.5.
2025020503
- 2025-02-05 - fix: URL on old and new user profile fields definition.
- 2025-02-05 - improvement: CLI script now shows better log of merging operations.
2025020502
- 2025-02-05 #295 - fix: remove deprecation warning on CLIGathering, related to Iterator. Thanks to @CatSema.
2025020501
- 2025-02-05 - bump version, update CHANGES.md, and kept support only for M4.1.
2025020500
- 2025-02-05 - bump version and update CHANGES.md
- 2025-02-05 #283 - new feature: use custom profile fields to identify merged old and new users (to both users). Partly contributed thanks to @sampraxis and @ClausSchmidtPraxis on 2024-11-14. PHPUnit test ensures the behaviour is the expected.
- 2025-02-05 #294 - fix: pass tests on mod_assign again. Thanks to @leonstr.
- 2025-02-04 #304 - fix: set up again suspended image to merged source user.
- 2025-02-04 #253 - fix: CRLF codification passed to LF.
- 2025-01-23 #299 - fix: fix file content to get them properly uploaded into AMOS.
2025012300
- 2025-01-23 #299 - make lang file compatible with AMOS to be translatable.
- 2025-01-23 #299 - add $plugin->release property as releasing new plugin version warns it.
2025012200
- 2025-01-22 #295 - CliGathering: remove deprecation warnings from Iterator implementation.
- 2025-01-22 #292 - Bump plugin version and requires Moodle 4.5 onwards.
- CI passes on green, as before, for PHP 8.1, 8.2 and 8.3 only for core MOODLE_405_STABLE.
- version.php updated.
- Improve type detection on IDE.
- Uses new trait on the assign_test class.
- 2025-01-17 #291 - Make web administration work on merge users.
- Removed lines requiring "lib/outputcomponents.php" from two files.
2024060300
- 2024-06-03 #268 - CI: verify it is working from M4.1 to M4.4 and master. Solves #263 too.
- 2024-06-03 #268 - Fixed PHPDoc issues and revisited output from merger when running from CLI.
2023061900
- 2023-06-19 #245 - Add list of incremental changes on file CHANGES.md.
- 2023-06-19 #247 - Fix proper support for Moodle 4.2, thanks to Matthias Opitz.
2023040402
- 2023-04-13 #243 - remove unused class with API inconsistence.
2023040401
- 2023-04-04 #211 - add CSV export for merged user logs; added mergedbyuserid field, thanks to Mark Johnson.
2023040400
- 2023-04-04 Fix CI to run only for supported versions, supporting Moodle 3.11 and up.
- 2022-12-15 #228 - Add compound indexes for customcert_issues table, thanks to Leon Stringer.
- 2021-08-01 #197 - Use Github Actions, remove Travis CI usage.
2021072200
- 2021-07-23 #193 - Allow automatic Moodle Plugins release when defining git tab.
- 2021-07-14 #175 - Reaggregate completion for target user, thanks to Andrew Hancox.
- 2021-07-14 #194 - Update unit tests for Moodle 3.10+, thanks to Alistair Spark.
- 2021-07-02 #177 - Move observer functions into classes to bypass include file error, thanks to Andrew Madden.
- 2021-06-10 #181 - Guarantee processing any grade item.
- 2020-02-23 #169 - Fix wrong entries deleted in case of conflict, thanks to Tim Schroeder.
- 2019-08-18 #166 - Support for duplicated assign submissions and other fixes.
- 2019-08-16 #67 - Improve and clean up settings.php.
- 2019-08-16 #163 - Force user to keep not to be suspended.
- 2019-08-16 #161 - Split in chunks the list of record ids to delete/update to prevent buffer overflow on SQL sentences.
- 2019-08-15 #147 - Config: Add logstore_standard_log columns related to user.id.
- 2019-08-15 #151 - Config: Add composed keys for wikis.
- 2019-08-15 #146 - Fix searching by user.id on pgsql.
- 2019-08-15 #152 - Support any supported Moodle database.
For a more extense list of changes, see git logs for changes before April 2019.
Contributors
Maintained by:
2025020504 (Happy 2025) (2025020504)
2025020504 (Happy 2025)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2025020504
Version release name: 2025020504 (Happy 2025)
Maturity: Stable
Supported Moodle versions: 4.2, 4.3, 4.4
Repository URL (Git): https://github.com/jpahullo/moodle-tool_mergeusers
Repository branch:
Repository tag: 2025020504
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
2025020504
- 2025-02-05 - bump version to make a new plugin version available for M4.2 to M4.4.
2025020503
- 2025-02-05 - fix: URL on old and new user profile fields definition.
- 2025-02-05 - improvement: CLI script now shows better log of merging operations.
2025020502
- 2025-02-05 #295 - fix: remove deprecation warning on CLIGathering, related to Iterator. Thanks to @CatSema.
2025020501
- 2025-02-05 - bump version, update CHANGES.md, and kept support only for M4.1.
2025020500
- 2025-02-05 - bump version and update CHANGES.md
- 2025-02-05 #283 - new feature: use custom profile fields to identify merged old and new users (to both users). Partly contributed thanks to @sampraxis and @ClausSchmidtPraxis on 2024-11-14. PHPUnit test ensures the behaviour is the expected.
- 2025-02-05 #294 - fix: pass tests on mod_assign again. Thanks to @leonstr.
- 2025-02-04 #304 - fix: set up again suspended image to merged source user.
- 2025-02-04 #253 - fix: CRLF codification passed to LF.
- 2025-01-23 #299 - fix: fix file content to get them properly uploaded into AMOS.
2024060300
- 2024-06-03 #268 - CI: verify it is working from M4.1 to M4.4 and master. Solves #263 too.
- 2024-06-03 #268 - Fixed PHPDoc issues and revisited output from merger when running from CLI.
2023061900
- 2023-06-19 #245 - Add list of incremental changes on file CHANGES.md.
- 2023-06-19 #247 - Fix proper support for Moodle 4.2, thanks to Matthias Opitz.
2023040402
- 2023-04-13 #243 - remove unused class with API inconsistence.
2023040401
- 2023-04-04 #211 - add CSV export for merged user logs; added mergedbyuserid field, thanks to Mark Johnson.
2023040400
- 2023-04-04 Fix CI to run only for supported versions, supporting Moodle 3.11 and up.
- 2022-12-15 #228 - Add compound indexes for customcert_issues table, thanks to Leon Stringer.
- 2021-08-01 #197 - Use Github Actions, remove Travis CI usage.
2021072200
- 2021-07-23 #193 - Allow automatic Moodle Plugins release when defining git tab.
- 2021-07-14 #175 - Reaggregate completion for target user, thanks to Andrew Hancox.
- 2021-07-14 #194 - Update unit tests for Moodle 3.10+, thanks to Alistair Spark.
- 2021-07-02 #177 - Move observer functions into classes to bypass include file error, thanks to Andrew Madden.
- 2021-06-10 #181 - Guarantee processing any grade item.
- 2020-02-23 #169 - Fix wrong entries deleted in case of conflict, thanks to Tim Schroeder.
- 2019-08-18 #166 - Support for duplicated assign submissions and other fixes.
- 2019-08-16 #67 - Improve and clean up settings.php.
- 2019-08-16 #163 - Force user to keep not to be suspended.
- 2019-08-16 #161 - Split in chunks the list of record ids to delete/update to prevent buffer overflow on SQL sentences.
- 2019-08-15 #147 - Config: Add logstore_standard_log columns related to user.id.
- 2019-08-15 #151 - Config: Add composed keys for wikis.
- 2019-08-15 #146 - Fix searching by user.id on pgsql.
- 2019-08-15 #152 - Support any supported Moodle database.
For a more extense list of changes, see git logs for changes before April 2019.
Contributors
Maintained by:
2025020503 (Happy 2025) (2025020503)
2025020503 (Happy 2025)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2025020503
Version release name: 2025020503 (Happy 2025)
Maturity: Stable
Supported Moodle versions: 4.1
Repository URL (Git): https://github.com/jpahullo/moodle-tool_mergeusers
Repository branch:
Repository tag: 2025020503
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
2025020503
- 2025-02-05 - fix: URL on old and new user profile fields definition.
- 2025-02-05 - improvement: CLI script now shows better log of merging operations.
2025020502
- 2025-02-05 #295 - fix: remove deprecation warning on CLIGathering, related to Iterator. Thanks to @CatSema.
2025020501
- 2025-02-05 - bump version, update CHANGES.md, and kept support only for M4.1.
2025020500
- 2025-02-05 - bump version and update CHANGES.md
- 2025-02-05 #283 - new feature: use custom profile fields to identify merged old and new users (to both users). Partly contributed thanks to @sampraxis and @ClausSchmidtPraxis on 2024-11-14. PHPUnit test ensures the behaviour is the expected.
- 2025-02-05 #294 - fix: pass tests on mod_assign again. Thanks to @leonstr.
- 2025-02-04 #304 - fix: set up again suspended image to merged source user.
- 2025-02-04 #253 - fix: CRLF codification passed to LF.
- 2025-01-23 #299 - fix: fix file content to get them properly uploaded into AMOS.
2023040402
- 2023-04-13 #243 - remove unused class with API inconsistence.
2023040401
- 2023-04-04 #211 - add CSV export for merged user logs; added mergedbyuserid field, thanks to Mark Johnson.
2023040400
- 2023-04-04 Fix CI to run only for supported versions, supporting Moodle 3.11 and up.
- 2022-12-15 #228 - Add compound indexes for customcert_issues table, thanks to Leon Stringer.
- 2021-08-01 #197 - Use Github Actions, remove Travis CI usage.
2021072200
- 2021-07-23 #193 - Allow automatic Moodle Plugins release when defining git tab.
- 2021-07-14 #175 - Reaggregate completion for target user, thanks to Andrew Hancox.
- 2021-07-14 #194 - Update unit tests for Moodle 3.10+, thanks to Alistair Spark.
- 2021-07-02 #177 - Move observer functions into classes to bypass include file error, thanks to Andrew Madden.
- 2021-06-10 #181 - Guarantee processing any grade item.
- 2020-02-23 #169 - Fix wrong entries deleted in case of conflict, thanks to Tim Schroeder.
- 2019-08-18 #166 - Support for duplicated assign submissions and other fixes.
- 2019-08-16 #67 - Improve and clean up settings.php.
- 2019-08-16 #163 - Force user to keep not to be suspended.
- 2019-08-16 #161 - Split in chunks the list of record ids to delete/update to prevent buffer overflow on SQL sentences.
- 2019-08-15 #147 - Config: Add logstore_standard_log columns related to user.id.
- 2019-08-15 #151 - Config: Add composed keys for wikis.
- 2019-08-15 #146 - Fix searching by user.id on pgsql.
- 2019-08-15 #152 - Support any supported Moodle database.
For a more extense list of changes, see git logs for changes before April 2019.
Contributors
Maintained by:
2025020502 (Happy 2025) (2025020502)
2025020502 (Happy 2025)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2025020502
Version release name: 2025020502 (Happy 2025)
Maturity: Stable
Supported Moodle versions: 4.1
Repository URL (Git): https://github.com/jpahullo/moodle-tool_mergeusers
Repository branch:
Repository tag: 2025020502
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
2025020502
- 2025-02-05 #295 - fix: remove deprecation warning on CLIGathering, related to Iterator. Thanks to @CatSema.
2025020501
- 2025-02-05 - bump version, update CHANGES.md, and kept support only for M4.1.
2025020500
- 2025-02-05 - bump version and update CHANGES.md
- 2025-02-05 #283 - new feature: use custom profile fields to identify merged old and new users (to both users). Partly contributed thanks to @sampraxis and @ClausSchmidtPraxis on 2024-11-14. PHPUnit test ensures the behaviour is the expected.
- 2025-02-05 #294 - fix: pass tests on mod_assign again. Thanks to @leonstr.
- 2025-02-04 #304 - fix: set up again suspended image to merged source user.
- 2025-02-04 #253 - fix: CRLF codification passed to LF.
- 2025-01-23 #299 - fix: fix file content to get them properly uploaded into AMOS.
2023040402
- 2023-04-13 #243 - remove unused class with API inconsistence.
2023040401
- 2023-04-04 #211 - add CSV export for merged user logs; added mergedbyuserid field, thanks to Mark Johnson.
2023040400
- 2023-04-04 Fix CI to run only for supported versions, supporting Moodle 3.11 and up.
- 2022-12-15 #228 - Add compound indexes for customcert_issues table, thanks to Leon Stringer.
- 2021-08-01 #197 - Use Github Actions, remove Travis CI usage.
2021072200
- 2021-07-23 #193 - Allow automatic Moodle Plugins release when defining git tab.
- 2021-07-14 #175 - Reaggregate completion for target user, thanks to Andrew Hancox.
- 2021-07-14 #194 - Update unit tests for Moodle 3.10+, thanks to Alistair Spark.
- 2021-07-02 #177 - Move observer functions into classes to bypass include file error, thanks to Andrew Madden.
- 2021-06-10 #181 - Guarantee processing any grade item.
- 2020-02-23 #169 - Fix wrong entries deleted in case of conflict, thanks to Tim Schroeder.
- 2019-08-18 #166 - Support for duplicated assign submissions and other fixes.
- 2019-08-16 #67 - Improve and clean up settings.php.
- 2019-08-16 #163 - Force user to keep not to be suspended.
- 2019-08-16 #161 - Split in chunks the list of record ids to delete/update to prevent buffer overflow on SQL sentences.
- 2019-08-15 #147 - Config: Add logstore_standard_log columns related to user.id.
- 2019-08-15 #151 - Config: Add composed keys for wikis.
- 2019-08-15 #146 - Fix searching by user.id on pgsql.
- 2019-08-15 #152 - Support any supported Moodle database.
For a more extense list of changes, see git logs for changes before April 2019.
Contributors
Maintained by:
2025020501 (Happy 2025) (2025020501)
2025020501 (Happy 2025)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2025020501
Version release name: 2025020501 (Happy 2025)
Maturity: Stable
Supported Moodle versions: 4.1
Repository URL (Git): https://github.com/jpahullo/moodle-tool_mergeusers
Repository branch:
Repository tag: 2025020501
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
2025020501
- 2025-02-05 - bump version, update CHANGES.md, and kept support only for M4.1.
2025020500
- 2025-02-05 - bump version and update CHANGES.md
- 2025-02-05 #283 - new feature: use custom profile fields to identify merged old and new users (to both users). Partly contributed thanks to @sampraxis and @ClausSchmidtPraxis on 2024-11-14. PHPUnit test ensures the behaviour is the expected.
- 2025-02-05 #294 - fix: pass tests on mod_assign again. Thanks to @leonstr.
- 2025-02-04 #304 - fix: set up again suspended image to merged source user.
- 2025-02-04 #253 - fix: CRLF codification passed to LF.
- 2025-01-23 #299 - fix: fix file content to get them properly uploaded into AMOS.
2023040402
- 2023-04-13 #243 - remove unused class with API inconsistence.
2023040401
- 2023-04-04 #211 - add CSV export for merged user logs; added mergedbyuserid field, thanks to Mark Johnson.
2023040400
- 2023-04-04 Fix CI to run only for supported versions, supporting Moodle 3.11 and up.
- 2022-12-15 #228 - Add compound indexes for customcert_issues table, thanks to Leon Stringer.
- 2021-08-01 #197 - Use Github Actions, remove Travis CI usage.
2021072200
- 2021-07-23 #193 - Allow automatic Moodle Plugins release when defining git tab.
- 2021-07-14 #175 - Reaggregate completion for target user, thanks to Andrew Hancox.
- 2021-07-14 #194 - Update unit tests for Moodle 3.10+, thanks to Alistair Spark.
- 2021-07-02 #177 - Move observer functions into classes to bypass include file error, thanks to Andrew Madden.
- 2021-06-10 #181 - Guarantee processing any grade item.
- 2020-02-23 #169 - Fix wrong entries deleted in case of conflict, thanks to Tim Schroeder.
- 2019-08-18 #166 - Support for duplicated assign submissions and other fixes.
- 2019-08-16 #67 - Improve and clean up settings.php.
- 2019-08-16 #163 - Force user to keep not to be suspended.
- 2019-08-16 #161 - Split in chunks the list of record ids to delete/update to prevent buffer overflow on SQL sentences.
- 2019-08-15 #147 - Config: Add logstore_standard_log columns related to user.id.
- 2019-08-15 #151 - Config: Add composed keys for wikis.
- 2019-08-15 #146 - Fix searching by user.id on pgsql.
- 2019-08-15 #152 - Support any supported Moodle database.
For a more extense list of changes, see git logs for changes before April 2019.
Contributors
Maintained by:
2025012300 (Happy 2025) (2025012300)
2025012300 (Happy 2025)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2025012300
Version release name: 2025012300 (Happy 2025)
Maturity: Stable
Supported Moodle versions: 4.5
Repository URL (Git): https://github.com/jpahullo/moodle-tool_mergeusers
Repository branch:
Repository tag: 2025012300
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
2025012300
- 2025-01-23 #299 - make lang file compatible with AMOS to be translatable.
- 2025-01-23 #299 - add $plugin->release property as releasing new plugin version warns it.
2025012200
- 2025-01-22 #295 - CliGathering: remove deprecation warnings from Iterator implementation.
- 2025-01-22 #292 - Bump plugin version and requires Moodle 4.5 onwards.
- CI passes on green, as before, for PHP 8.1, 8.2 and 8.3 only for core MOODLE_405_STABLE.
- version.php updated.
- Improve type detection on IDE.
- Uses new trait on the assign_test class.
- 2025-01-17 #291 - Make web administration work on merge users.
- Removed lines requiring "lib/outputcomponents.php" from two files.
2024060300
- 2024-06-03 #268 - CI: verify it is working from M4.1 to M4.4 and master. Solves #263 too.
- 2024-06-03 #268 - Fixed PHPDoc issues and revisited output from merger when running from CLI.
2023061900
- 2023-06-19 #245 - Add list of incremental changes on file CHANGES.md.
- 2023-06-19 #247 - Fix proper support for Moodle 4.2, thanks to Matthias Opitz.
2023040402
- 2023-04-13 #243 - remove unused class with API inconsistence.
2023040401
- 2023-04-04 #211 - add CSV export for merged user logs; added mergedbyuserid field, thanks to Mark Johnson.
2023040400
- 2023-04-04 Fix CI to run only for supported versions, supporting Moodle 3.11 and up.
- 2022-12-15 #228 - Add compound indexes for customcert_issues table, thanks to Leon Stringer.
- 2021-08-01 #197 - Use Github Actions, remove Travis CI usage.
2021072200
- 2021-07-23 #193 - Allow automatic Moodle Plugins release when defining git tab.
- 2021-07-14 #175 - Reaggregate completion for target user, thanks to Andrew Hancox.
- 2021-07-14 #194 - Update unit tests for Moodle 3.10+, thanks to Alistair Spark.
- 2021-07-02 #177 - Move observer functions into classes to bypass include file error, thanks to Andrew Madden.
- 2021-06-10 #181 - Guarantee processing any grade item.
- 2020-02-23 #169 - Fix wrong entries deleted in case of conflict, thanks to Tim Schroeder.
- 2019-08-18 #166 - Support for duplicated assign submissions and other fixes.
- 2019-08-16 #67 - Improve and clean up settings.php.
- 2019-08-16 #163 - Force user to keep not to be suspended.
- 2019-08-16 #161 - Split in chunks the list of record ids to delete/update to prevent buffer overflow on SQL sentences.
- 2019-08-15 #147 - Config: Add logstore_standard_log columns related to user.id.
- 2019-08-15 #151 - Config: Add composed keys for wikis.
- 2019-08-15 #146 - Fix searching by user.id on pgsql.
- 2019-08-15 #152 - Support any supported Moodle database.
For a more extense list of changes, see git logs for changes before April 2019.
Contributors
Maintained by:
(2025012200)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2025012200
Version release name:
Maturity: Stable
Supported Moodle versions: 4.5
Repository URL (Git): https://github.com/jpahullo/moodle-tool_mergeusers
Repository branch:
Repository tag: 2025012200
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
2025012200
- 2025-01-22 #295 - CliGathering: remove deprecation warnings from Iterator implementation.
- 2025-01-22 #292 - Bump plugin version and requires Moodle 4.5 onwards.
- CI passes on green, as before, for PHP 8.1, 8.2 and 8.3 only for core MOODLE_405_STABLE.
- version.php updated.
- Improve type detection on IDE.
- Uses new trait on the assign_test class.
- 2025-01-17 #291 - Make web administration work on merge users.
- Removed lines requiring "lib/outputcomponents.php" from two files.
2024060300
- 2024-06-03 #268 - CI: verify it is working from M4.1 to M4.4 and master. Solves #263 too.
- 2024-06-03 #268 - Fixed PHPDoc issues and revisited output from merger when running from CLI.
2023061900
- 2023-06-19 #245 - Add list of incremental changes on file CHANGES.md.
- 2023-06-19 #247 - Fix proper support for Moodle 4.2, thanks to Matthias Opitz.
2023040402
- 2023-04-13 #243 - remove unused class with API inconsistence.
2023040401
- 2023-04-04 #211 - add CSV export for merged user logs; added mergedbyuserid field, thanks to Mark Johnson.
2023040400
- 2023-04-04 Fix CI to run only for supported versions, supporting Moodle 3.11 and up.
- 2022-12-15 #228 - Add compound indexes for customcert_issues table, thanks to Leon Stringer.
- 2021-08-01 #197 - Use Github Actions, remove Travis CI usage.
2021072200
- 2021-07-23 #193 - Allow automatic Moodle Plugins release when defining git tab.
- 2021-07-14 #175 - Reaggregate completion for target user, thanks to Andrew Hancox.
- 2021-07-14 #194 - Update unit tests for Moodle 3.10+, thanks to Alistair Spark.
- 2021-07-02 #177 - Move observer functions into classes to bypass include file error, thanks to Andrew Madden.
- 2021-06-10 #181 - Guarantee processing any grade item.
- 2020-02-23 #169 - Fix wrong entries deleted in case of conflict, thanks to Tim Schroeder.
- 2019-08-18 #166 - Support for duplicated assign submissions and other fixes.
- 2019-08-16 #67 - Improve and clean up settings.php.
- 2019-08-16 #163 - Force user to keep not to be suspended.
- 2019-08-16 #161 - Split in chunks the list of record ids to delete/update to prevent buffer overflow on SQL sentences.
- 2019-08-15 #147 - Config: Add logstore_standard_log columns related to user.id.
- 2019-08-15 #151 - Config: Add composed keys for wikis.
- 2019-08-15 #146 - Fix searching by user.id on pgsql.
- 2019-08-15 #152 - Support any supported Moodle database.
For a more extense list of changes, see git logs for changes before April 2019.
Contributors
Maintained by:
(2024060300)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2024060300
Version release name:
Maturity: Stable
Supported Moodle versions: 4.2, 4.3, 4.4
Repository URL (Git): https://github.com/jpahullo/moodle-tool_mergeusers
Repository branch:
Repository tag: 2024060300
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
2024060300
- 2024-06-03 #268 - CI: verify it is working from M4.1 to M4.4 and master. Solves #263 too.
- 2024-06-03 #268 - Fixed PHPDoc issues and revisited output from merger when running from CLI.
2023061900
- 2023-06-19 #245 - Add list of incremental changes on file CHANGES.md.
- 2023-06-19 #247 - Fix proper support for Moodle 4.2, thanks to Matthias Opitz.
2023040402
- 2023-04-13 #243 - remove unused class with API inconsistence.
2023040401
- 2023-04-04 #211 - add CSV export for merged user logs; added mergedbyuserid field, thanks to Mark Johnson.
2023040400
- 2023-04-04 Fix CI to run only for supported versions, supporting Moodle 3.11 and up.
- 2022-12-15 #228 - Add compound indexes for customcert_issues table, thanks to Leon Stringer.
- 2021-08-01 #197 - Use Github Actions, remove Travis CI usage.
2021072200
- 2021-07-23 #193 - Allow automatic Moodle Plugins release when defining git tab.
- 2021-07-14 #175 - Reaggregate completion for target user, thanks to Andrew Hancox.
- 2021-07-14 #194 - Update unit tests for Moodle 3.10+, thanks to Alistair Spark.
- 2021-07-02 #177 - Move observer functions into classes to bypass include file error, thanks to Andrew Madden.
- 2021-06-10 #181 - Guarantee processing any grade item.
- 2020-02-23 #169 - Fix wrong entries deleted in case of conflict, thanks to Tim Schroeder.
- 2019-08-18 #166 - Support for duplicated assign submissions and other fixes.
- 2019-08-16 #67 - Improve and clean up settings.php.
- 2019-08-16 #163 - Force user to keep not to be suspended.
- 2019-08-16 #161 - Split in chunks the list of record ids to delete/update to prevent buffer overflow on SQL sentences.
- 2019-08-15 #147 - Config: Add logstore_standard_log columns related to user.id.
- 2019-08-15 #151 - Config: Add composed keys for wikis.
- 2019-08-15 #146 - Fix searching by user.id on pgsql.
- 2019-08-15 #152 - Support any supported Moodle database.
For a more extense list of changes, see git logs for changes before April 2019.
Contributors
Maintained by:
(2023061900)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2023061900
Version release name:
Maturity: Stable
Supported Moodle versions: 4.2
Repository URL (Git): https://github.com/jpahullo/moodle-tool_mergeusers
Repository branch:
Repository tag: 2023061900
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
2023061900
- 2023-06-19 #245 - Add list of incremental changes on file CHANGES.md.
- 2023-06-19 #247 - Fix proper support for Moodle 4.2, thanks to Matthias Opitz.
2023040402
- 2023-04-13 #243 - remove unused class with API inconsistence.
2023040401
- 2023-04-04 #211 - add CSV export for merged user logs; added mergedbyuserid field, thanks to Mark Johnson.
2023040400
- 2023-04-04 Fix CI to run only for supported versions, supporting Moodle 3.11 and up.
- 2022-12-15 #228 - Add compound indexes for customcert_issues table, thanks to Leon Stringer.
- 2021-08-01 #197 - Use Github Actions, remove Travis CI usage.
2021072200
- 2021-07-23 #193 - Allow automatic Moodle Plugins release when defining git tab.
- 2021-07-14 #175 - Reaggregate completion for target user, thanks to Andrew Hancox.
- 2021-07-14 #194 - Update unit tests for Moodle 3.10+, thanks to Alistair Spark.
- 2021-07-02 #177 - Move observer functions into classes to bypass include file error, thanks to Andrew Madden.
- 2021-06-10 #181 - Guarantee processing any grade item.
- 2020-02-23 #169 - Fix wrong entries deleted in case of conflict, thanks to Tim Schroeder.
- 2019-08-18 #166 - Support for duplicated assign submissions and other fixes.
- 2019-08-16 #67 - Improve and clean up settings.php.
- 2019-08-16 #163 - Force user to keep not to be suspended.
- 2019-08-16 #161 - Split in chunks the list of record ids to delete/update to prevent buffer overflow on SQL sentences.
- 2019-08-15 #147 - Config: Add logstore_standard_log columns related to user.id.
- 2019-08-15 #151 - Config: Add composed keys for wikis.
- 2019-08-15 #146 - Fix searching by user.id on pgsql.
- 2019-08-15 #152 - Support any supported Moodle database.
For a more extense list of changes, see git logs for changes before April 2019.
Contributors
Maintained by:
(2023040402)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2023040402
Version release name:
Maturity: Stable
Supported Moodle versions: 3.11, 4.0, 4.1
Repository URL (Git): https://github.com/ndunand/moodle-tool_mergeusers
Repository branch:
Repository tag: 2023040402
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
- (#243) Remove unused class with API insconsistence.
Contributors
Maintained by:
- Nicolas Dunand.
- Jordi Pujol-Ahulló.
(2021072202)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2021072202
Version release name:
Maturity: Stable
Supported Moodle versions: 3.10, 3.9
Repository URL (Git): https://github.com/ndunand/moodle-tool_mergeusers
Repository branch:
Repository tag: 2021072202
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
- (#243) Remove unused class with API insconsistence.
Contributors
Maintained by:
- Nicolas Dunand.
- Jordi Pujol-Ahulló.
(2021072201)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2021072201
Version release name:
Maturity: Stable
Supported Moodle versions: 3.10, 3.9
Repository URL (Git): https://github.com/ndunand/moodle-tool_mergeusers
Repository branch:
Repository tag: 2021072201
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
- Minimum Moodle version supported is 3.9.
- Maximum Moodle version supported is 3.10.
- Splitted git branches for supporting properly 311 version and up.
Contributors
Maintained by:
- Nicolas Dunand.
- Jordi Pujol-Ahulló.
(2023040401)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2023040401
Version release name:
Maturity: Stable
Supported Moodle versions: 3.11, 4.0, 4.1
Repository URL (Git): https://github.com/ndunand/moodle-tool_mergeusers
Repository branch:
Repository tag: 2023040401
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
- (#211) Export list of logs as CSV. By @marxjohnson.
Contributors
Maintained by:
- Nicolas Dunand.
- Jordi Pujol-Ahulló.
(2023040400)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2023040400
Version release name:
Maturity: Stable
Supported Moodle versions: 3.11, 4.0, 4.1
Repository URL (Git): https://github.com/ndunand/moodle-tool_mergeusers
Repository branch:
Repository tag: 2023040400
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
- Minimum Moodle version supported is 3.11.
Contributors
Maintained by:
- Nicolas Dunand.
- Jordi Pujol-Ahulló.
(2021072200)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2021072200
Version release name:
Maturity: Stable
Supported Moodle versions: 3.10, 3.9
Repository URL (Git): https://github.com/ndunand/moodle-tool_mergeusers
Repository branch:
Repository tag: 2021072200
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Release notes
- Minimum Moodle version supported is 3.9.
- (#175) Guarantee course completions are properly processed after merging users.
- (#177) Refactor observer functions into classes due to Moodle version requirements.
- (#181) Guarantee processing any grade item.
- (#168) Fix wrong entries being deleted in case of conflict.
Contributors
Maintained by:
- Nicolas Dunand.
- Jordi Pujol-Ahulló (at SREd, Universitat Rovira i Virgili).
1.21 for Moodle 3.4 and upwards (Build: 2019082000) (2019082000)
1.21 for Moodle 3.4 and upwards (Build: 2019082000)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2019082000
Version release name: 1.21 for Moodle 3.4 and upwards (Build: 2019082000)
Maturity: Stable
Supported Moodle versions: 3.4, 3.5, 3.6, 3.7, 3.8, 3.9
Repository URL (Git): https://github.com/ndunand/moodle-tool_mergeusers
Repository branch:
Repository tag: 2019082000
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Moodle compatibility
This plugin version is:
- Compatible from Moodle 3.4 and upwards.
- Supporting any Moodle compatible database.
Merge users script for Moodle
This script will merge two Moodle user accounts, "user A" and "user B".
The intent of the script is to assign all activity & records from user A to
user B. This will give the effect of user B seeming to have done everything
both users have ever done in Moodle. The basic function of the script is to
loop through the tables and update the userid of every record from user A to
user B. This works well for most tables. We do however, have a few special
cases:
- Special Case #1: The grade_grades table has a compound unique key on userid
and itemid. This prevents a simple update statement if the two users have
done the same activity. What this script does is determine which activities
have been completed by both users and delete the entry for the old user
from this table. Data is not lost because a duplicate entry can be found in
the grade_grades_history table, which is correctly updated by the regular
processing of the script. - Special Case #2: The user_enrolments table controls which user is enrolled
in which course. Rather than unenroll the old user from the course, this
script simply updates their access to the course to "2" which makes them
completely unable to access the course. To remove these records all
together I recomend disabling or deleting the entire old user account once
the migration has been successful. - Special Case #3: There are 4 logging/preference tables
(user_lastaccess, user_preferences, user_private_key, my_pages) which exist in
Moodle 2.x. This script is simply skipping these tables since there's no
legitimate purpose to updating the userid value here. This would lead to
duplicate rows for the new user which is silly. Again, if you want to
remove these records I would recommend deleting the old user after this
script runs sucessfully. my_pages' records will not be deleted, but
this is something you find in Moodle, that not all records related to a
specific entity are clened up. We need to skip my_pages table too, since
that MyMoodle page of the old user have a relation of blocks appearing on it.
If we proceed with a normal merging action, resulting with two records
with the same userid, the user will not see correctly his/her MyMoodle page.
Due to a community request, all these tables except my_pages can be omitted
from this exclusion and so, if set in settings, they can be merged as usual. - Special Case #4: mod/journal plugin has a record per user and journal on
journal_entries table. In case there is a record for both users, we delete
the record related to the old user. For the rest of cases, this operates as usual. - Special Case #5: groups_members table has a record per user and group.
Updating always the old user id for the new one is incorrect if both users
appear in that group. In that case, this plugin deletes the record related
to the old user. For the rest of cases, this plugin operates as usual. - Special Case #6: course_completions table has a record per user and course.
Updating always the old user id for the new one is incorrect if both users
appear in that group. In that case, this plugin deletes the record related
to the old user. For the rest of cases, this plugin operates as usual. - Special case #7: message_contacts table has a record per user and contact id,
which is again a user.id. If replacing the old id by the new one means
index conflict, this means actually that the resulting record already exists,
so we can securely remove the old record. In addition, this checking is performed
for both column names (userid and contactid) looking for matching on both
in the same way. - Special case #8: role_assignments table has a three-field unique index,
including context, role and userid. As before, it always updates records to
be the new one. If only old id exists, it is updated; if only new id exists,
it does nothing; if both ids exist, the record with the old id is removed. - Special case #9: user_lastaccess table has a two-field unique index, including
userid and courseid. In case both users has a record for the same
courseid, this plugin removes the record for the old user and keep that one
for the new user. For the rest of cases, this plugin operates as usual. - Special case #10: quiz_attempts table has a three-field unique index, including
userid, quiz and attempt. This table and related quiz_grades and quiz_grades_history
are processed as specified in the plugin settings. This plugin provies you
several options when merging quiz attempts from two users:
- Merge attempts from both users and renumber. Attempts from the old user are
merged with the ones of the new user and renumbered by the time they were
started. - Keep attempts from the new user. Attempts from the old user are removed.
Attempts from the new user are kept, since this option considers them as the
most important. - Keep attempts from the old user. Attempts from the new user are removed.
Attempts from the old user are kept, since this option considers them as the
most important. - Do nothing: do not merge nor delete (by default). Attempts are not merged nor
deleted, remaining related to the user who made them. This is the most secure
action, but merging users from user A to user B or B to A may produce different
quiz grades.
- Special case #11: there are cases where third party plugins build unique indexes
applied onto a single column related to user.id. In such cases, we have added
a new setting "uniquekeynewidtomaintain" that helps handles this conflict.
If you mark this option (by default), data related to the new user is kept.
Otherwise, if you unmark this setting, this plugin will keep the data from
the old user.
Command-line script
A cli/climerger.php script is added. You can now perform user mergings by command line having
their user ids.
You can go further and develop your own CLI script by extending the Gathering interface
(see lib/cligathering.php for an example). Ok, but let us explain how to do it step by step:
- Develop a class, namely MyGathering, in lib/mygathering.php, implementing the interface Gathering.
Be sure the class name and the filename are the same, but filename all in lowercase ending with ".php".
See lib/cligathering for an example. - Create or edit the file config/config.local.php with at least the following content:
<?php
return array(
// gathering tool
'gathering' => 'MyGathering',
);
- Run as a command line in a form like this: $ time php cli/climerger.php.
Events and event management
Once the merging action is completed, an event 'merging_success' is triggered if it was ok,
or an event 'merging_failed' otherwise. The available data on the event are as follows:
- oldid: the user.id of the "user A" to be removed from all his/her activity.
- newid: the user.id of the "user B" which will gather the activity of both users.
- log: string with the list of actions performed.
- timemodified: time in which the event is generated, after the merging action.
The goal of this event triggering is the ability to be detected by other parts of Moodle.
This plugin also manages the 'merging_success' event is trigered, what includes:
- Suspending the user (user.suspended = 1). This prevents the person to log in with the old account.
- Changing the old user's profile picture by the given on pix/suspended.jpg. It is a simple
white image with the text "suspended user", which could help to teachers and
managers to rapidly detect them.
Correct way of testing this plugin
First of all, check admin/settings.php?section=mergeusers_settings for the
description of the setting tool_mergeusers | transactions_only
if your database type and version supports transcations. If so,
no action will actually be committed if something goes wrong.
Mainly, these are the main steps to test this plugin:
- You should have a replica of your Moodle instance, with a full replica of your Moodle database where you run this plugin.
- Run a sufficient amount of user merging to check if anything goes wrong.
- What if...?
- ... all was ok? You are almost confident that all will be ok also in your production instance of Moodle.
- ... something went wrong? There are several reasons for that:
- Non-core plugins installed on your Moodle and not assumed in this plugin.
- Local database changes on Moodle that may affect to the normal execution of this plugin.
- Some compound index not detected yet.
If in your tests or already in production something went wrong, please, report the error log on the
official plugin website on moodle.org. And if you have some PHP skill, you can try to solve it
and share both the error and the patch to solve it ;-)
Common sense
Before running this plugin, it is highly recommended to back up your database.
That will help you to restore the state before any merging action was done.
This plugin stores a log for any user merging, with the list of actions done or
errors produced. If your database supports transactions (see above section),
automatic rollbacks are done at database level, so that your database state
remains consistent.
However, running this plugin in databases without
transaction support can put you in trouble. That is, there is no provision for
automatic rollbacks, so if something were to fail midway through,
you will end up with a half-updated database. Nevertheless, if you found a
problem when merging users A and B, do not panic. Merging will be successfully
completed when a solution for your problem is included into this plugin, and
you rerun merging users A and B.
Development
Developing and testing phase
We recommend to use the https://github.com/moodlehq/moodle-docker project to
run your own Moodle instances for developing and testing.
PHPUnit testing
To quickly setup your own development, we suggest to run the command:
php admin/tool/phpunit/cli/util.php --buildcomponentconfigs
as documented at https://docs.moodle.org/dev/PHPUnit to have the phpunit.xml
file under admin/tool/mergeusers/phpunit.xml.
Then, you can run all plugin's tests as follows:
vendor/bin/phpunit -c admin/tool/mergeusers
or also like this, without the need of running the buildcomponentconfigs:
vendor/bin/phpunit --group tool_mergeusers
There are also other PHPUnit groups created to help testing only the part
of the plugin of your choice. Take a look at the tests code for other group names.
Minimum requirements
- MySQL v5.x or MSSQL or Postgres
- Moodle v2.2
License
GNU GPL v3 or later. http://www.gnu.org/copyleft/gpl.html
Contributors
- Based on the mergeusers_v2.php script written by Nicolas Dunand.
- Updated for Moodle 2.0 by Mike Holzer [m.e.holzer AT gmail DOT com]
- Moodle 2.x report by Forrest Gaston
- Updated by Jordi Pujol-Ahulló (at SREd, Universitat Rovira i Virgili) with:
- several compound index on database tables,
- selector for the type of user identification (username, id, idnumber),
- more Moodle-like web and code, including web renderer,
- config.php with current configuration settings, used for merging,
- config.local.php to include local settings on your Moodle instance,
- log of any merging action in database for further reference,
- revisited web interface for the new wizard when merging users manually,
- TableMerger entities to process Moodle tables accordingly,
- quiz attempts are processed as suggested in
https://moodle.org/mod/forum/discuss.php?d=258979, adding 4 different options
for their processing.
- Web wizard for merging users by John Hoopes, University of Wisconsin - Madison
- Updated by Andrew Hancox with:
- improvements and fixing a bug on cli script.
- Plugin maintained by Nicolas Dunand [nicolas.dunand AT unil DOT ch]
1.20 for Moodle 3.4 and upwards (Build: 2019081600) (2019081600)
1.20 for Moodle 3.4 and upwards (Build: 2019081600)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2019081600
Version release name: 1.20 for Moodle 3.4 and upwards (Build: 2019081600)
Maturity: Stable
Supported Moodle versions: 3.4, 3.5, 3.6, 3.7
Repository URL (Git): https://github.com/ndunand/moodle-tool_mergeusers
Repository branch:
Repository tag: 2019081600
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Moodle compatibility
This plugin version is:
- Compatible from Moodle 3.4 and upwards.
- Supporting any Moodle compatible database.
Merge users script for Moodle
This script will merge two Moodle user accounts, "user A" and "user B".
The intent of the script is to assign all activity & records from user A to
user B. This will give the effect of user B seeming to have done everything
both users have ever done in Moodle. The basic function of the script is to
loop through the tables and update the userid of every record from user A to
user B. This works well for most tables. We do however, have a few special
cases:
- Special Case #1: The grade_grades table has a compound unique key on userid
and itemid. This prevents a simple update statement if the two users have
done the same activity. What this script does is determine which activities
have been completed by both users and delete the entry for the old user
from this table. Data is not lost because a duplicate entry can be found in
the grade_grades_history table, which is correctly updated by the regular
processing of the script. - Special Case #2: The user_enrolments table controls which user is enrolled
in which course. Rather than unenroll the old user from the course, this
script simply updates their access to the course to "2" which makes them
completely unable to access the course. To remove these records all
together I recomend disabling or deleting the entire old user account once
the migration has been successful. - Special Case #3: There are 4 logging/preference tables
(user_lastaccess, user_preferences, user_private_key, my_pages) which exist in
Moodle 2.x. This script is simply skipping these tables since there's no
legitimate purpose to updating the userid value here. This would lead to
duplicate rows for the new user which is silly. Again, if you want to
remove these records I would recommend deleting the old user after this
script runs sucessfully. my_pages' records will not be deleted, but
this is something you find in Moodle, that not all records related to a
specific entity are clened up. We need to skip my_pages table too, since
that MyMoodle page of the old user have a relation of blocks appearing on it.
If we proceed with a normal merging action, resulting with two records
with the same userid, the user will not see correctly his/her MyMoodle page.
Due to a community request, all these tables except my_pages can be omitted
from this exclusion and so, if set in settings, they can be merged as usual. - Special Case #4: mod/journal plugin has a record per user and journal on
journal_entries table. In case there is a record for both users, we delete
the record related to the old user. For the rest of cases, this operates as usual. - Special Case #5: groups_members table has a record per user and group.
Updating always the old user id for the new one is incorrect if both users
appear in that group. In that case, this plugin deletes the record related
to the old user. For the rest of cases, this plugin operates as usual. - Special Case #6: course_completions table has a record per user and course.
Updating always the old user id for the new one is incorrect if both users
appear in that group. In that case, this plugin deletes the record related
to the old user. For the rest of cases, this plugin operates as usual. - Special case #7: message_contacts table has a record per user and contact id,
which is again a user.id. If replacing the old id by the new one means
index conflict, this means actually that the resulting record already exists,
so we can securely remove the old record. In addition, this checking is performed
for both column names (userid and contactid) looking for matching on both
in the same way. - Special case #8: role_assignments table has a three-field unique index,
including context, role and userid. As before, it always updates records to
be the new one. If only old id exists, it is updated; if only new id exists,
it does nothing; if both ids exist, the record with the old id is removed. - Special case #9: user_lastaccess table has a two-field unique index, including
userid and courseid. In case both users has a record for the same
courseid, this plugin removes the record for the old user and keep that one
for the new user. For the rest of cases, this plugin operates as usual. - Special case #10: quiz_attempts table has a three-field unique index, including
userid, quiz and attempt. This table and related quiz_grades and quiz_grades_history
are processed as specified in the plugin settings. This plugin provies you
several options when merging quiz attempts from two users:
- Merge attempts from both users and renumber. Attempts from the old user are
merged with the ones of the new user and renumbered by the time they were
started. - Keep attempts from the new user. Attempts from the old user are removed.
Attempts from the new user are kept, since this option considers them as the
most important. - Keep attempts from the old user. Attempts from the new user are removed.
Attempts from the old user are kept, since this option considers them as the
most important. - Do nothing: do not merge nor delete (by default). Attempts are not merged nor
deleted, remaining related to the user who made them. This is the most secure
action, but merging users from user A to user B or B to A may produce different
quiz grades.
- Special case #11: there are cases where third party plugins build unique indexes
applied onto a single column related to user.id. In such cases, we have added
a new setting "uniquekeynewidtomaintain" that helps handles this conflict.
If you mark this option (by default), data related to the new user is kept.
Otherwise, if you unmark this setting, this plugin will keep the data from
the old user.
Command-line script
A cli/climerger.php script is added. You can now perform user mergings by command line having
their user ids.
You can go further and develop your own CLI script by extending the Gathering interface
(see lib/cligathering.php for an example). Ok, but let us explain how to do it step by step:
- Develop a class, namely MyGathering, in lib/mygathering.php, implementing the interface Gathering.
Be sure the class name and the filename are the same, but filename all in lowercase ending with ".php".
See lib/cligathering for an example. - Create or edit the file config/config.local.php with at least the following content:
<?php
return array(
// gathering tool
'gathering' => 'MyGathering',
);
- Run as a command line in a form like this: $ time php cli/climerger.php.
Events and event management
Once the merging action is completed, an event 'merging_success' is triggered if it was ok,
or an event 'merging_failed' otherwise. The available data on the event are as follows:
- oldid: the user.id of the "user A" to be removed from all his/her activity.
- newid: the user.id of the "user B" which will gather the activity of both users.
- log: string with the list of actions performed.
- timemodified: time in which the event is generated, after the merging action.
The goal of this event triggering is the ability to be detected by other parts of Moodle.
This plugin also manages the 'merging_success' event is trigered, what includes:
- Suspending the user (user.suspended = 1). This prevents the person to log in with the old account.
- Changing the old user's profile picture by the given on pix/suspended.jpg. It is a simple
white image with the text "suspended user", which could help to teachers and
managers to rapidly detect them.
Correct way of testing this plugin
First of all, check admin/settings.php?section=mergeusers_settings for the
description of the setting tool_mergeusers | transactions_only
if your database type and version supports transcations. If so,
no action will actually be committed if something goes wrong.
Mainly, these are the main steps to test this plugin:
- You should have a replica of your Moodle instance, with a full replica of your Moodle database where you run this plugin.
- Run a sufficient amount of user merging to check if anything goes wrong.
- What if...?
- ... all was ok? You are almost confident that all will be ok also in your production instance of Moodle.
- ... something went wrong? There are several reasons for that:
- Non-core plugins installed on your Moodle and not assumed in this plugin.
- Local database changes on Moodle that may affect to the normal execution of this plugin.
- Some compound index not detected yet.
If in your tests or already in production something went wrong, please, report the error log on the
official plugin website on moodle.org. And if you have some PHP skill, you can try to solve it
and share both the error and the patch to solve it ;-)
Common sense
Before running this plugin, it is highly recommended to back up your database.
That will help you to restore the state before any merging action was done.
This plugin stores a log for any user merging, with the list of actions done or
errors produced. If your database supports transactions (see above section),
automatic rollbacks are done at database level, so that your database state
remains consistent.
However, running this plugin in databases without
transaction support can put you in trouble. That is, there is no provision for
automatic rollbacks, so if something were to fail midway through,
you will end up with a half-updated database. Nevertheless, if you found a
problem when merging users A and B, do not panic. Merging will be successfully
completed when a solution for your problem is included into this plugin, and
you rerun merging users A and B.
Development
Developing and testing phase
We recommend to use the https://github.com/moodlehq/moodle-docker project to
run your own Moodle instances for developing and testing.
PHPUnit testing
To quickly setup your own development, we suggest to run the command:
php admin/tool/phpunit/cli/util.php --buildcomponentconfigs
as documented at https://docs.moodle.org/dev/PHPUnit to have the phpunit.xml
file under admin/tool/mergeusers/phpunit.xml.
Then, you can run all plugin's tests as follows:
vendor/bin/phpunit -c admin/tool/mergeusers
or also like this, without the need of running the buildcomponentconfigs:
vendor/bin/phpunit --group tool_mergeusers
There are also other PHPUnit groups created to help testing only the part
of the plugin of your choice. Take a look at the tests code for other group names.
Minimum requirements
- MySQL v5.x or MSSQL or Postgres
- Moodle v2.2
License
GNU GPL v3 or later. http://www.gnu.org/copyleft/gpl.html
Contributors
- Based on the mergeusers_v2.php script written by Nicolas Dunand.
- Updated for Moodle 2.0 by Mike Holzer [m.e.holzer AT gmail DOT com]
- Moodle 2.x report by Forrest Gaston
- Updated by Jordi Pujol-Ahulló (at SREd, Universitat Rovira i Virgili) with:
- several compound index on database tables,
- selector for the type of user identification (username, id, idnumber),
- more Moodle-like web and code, including web renderer,
- config.php with current configuration settings, used for merging,
- config.local.php to include local settings on your Moodle instance,
- log of any merging action in database for further reference,
- revisited web interface for the new wizard when merging users manually,
- TableMerger entities to process Moodle tables accordingly,
- quiz attempts are processed as suggested in
https://moodle.org/mod/forum/discuss.php?d=258979, adding 4 different options
for their processing.
- Web wizard for merging users by John Hoopes, University of Wisconsin - Madison
- Updated by Andrew Hancox with:
- improvements and fixing a bug on cli script.
- Plugin maintained by Nicolas Dunand [nicolas.dunand AT unil DOT ch]
1.19 for Moodle 3.4 and upwards (Build: 2019081500) (2019081500)
1.19 for Moodle 3.4 and upwards (Build: 2019081500)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2019081500
Version release name: 1.19 for Moodle 3.4 and upwards (Build: 2019081500)
Maturity: Stable
Supported Moodle versions: 3.4, 3.5, 3.6, 3.7
Repository URL (Git): https://github.com/ndunand/moodle-tool_mergeusers
Repository branch:
Repository tag: 2019081500
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Moodle compatibility
This plugin version is compatible from Moodle 3.4 and upwards.
Merge users script for Moodle
This script will merge two Moodle user accounts, "user A" and "user B".
The intent of the script is to assign all activity & records from user A to
user B. This will give the effect of user B seeming to have done everything
both users have ever done in Moodle. The basic function of the script is to
loop through the tables and update the userid of every record from user A to
user B. This works well for most tables. We do however, have a few special
cases:
- Special Case #1: The grade_grades table has a compound unique key on userid
and itemid. This prevents a simple update statement if the two users have
done the same activity. What this script does is determine which activities
have been completed by both users and delete the entry for the old user
from this table. Data is not lost because a duplicate entry can be found in
the grade_grades_history table, which is correctly updated by the regular
processing of the script. - Special Case #2: The user_enrolments table controls which user is enrolled
in which course. Rather than unenroll the old user from the course, this
script simply updates their access to the course to "2" which makes them
completely unable to access the course. To remove these records all
together I recomend disabling or deleting the entire old user account once
the migration has been successful. - Special Case #3: There are 4 logging/preference tables
(user_lastaccess, user_preferences, user_private_key, my_pages) which exist in
Moodle 2.x. This script is simply skipping these tables since there's no
legitimate purpose to updating the userid value here. This would lead to
duplicate rows for the new user which is silly. Again, if you want to
remove these records I would recommend deleting the old user after this
script runs sucessfully. my_pages' records will not be deleted, but
this is something you find in Moodle, that not all records related to a
specific entity are clened up. We need to skip my_pages table too, since
that MyMoodle page of the old user have a relation of blocks appearing on it.
If we proceed with a normal merging action, resulting with two records
with the same userid, the user will not see correctly his/her MyMoodle page.
Due to a community request, all these tables except my_pages can be omitted
from this exclusion and so, if set in settings, they can be merged as usual. - Special Case #4: mod/journal plugin has a record per user and journal on
journal_entries table. In case there is a record for both users, we delete
the record related to the old user. For the rest of cases, this operates as usual. - Special Case #5: groups_members table has a record per user and group.
Updating always the old user id for the new one is incorrect if both users
appear in that group. In that case, this plugin deletes the record related
to the old user. For the rest of cases, this plugin operates as usual. - Special Case #6: course_completions table has a record per user and course.
Updating always the old user id for the new one is incorrect if both users
appear in that group. In that case, this plugin deletes the record related
to the old user. For the rest of cases, this plugin operates as usual. - Special case #7: message_contacts table has a record per user and contact id,
which is again a user.id. If replacing the old id by the new one means
index conflict, this means actually that the resulting record already exists,
so we can securely remove the old record. In addition, this checking is performed
for both column names (userid and contactid) looking for matching on both
in the same way. - Special case #8: role_assignments table has a three-field unique index,
including context, role and userid. As before, it always updates records to
be the new one. If only old id exists, it is updated; if only new id exists,
it does nothing; if both ids exist, the record with the old id is removed. - Special case #9: user_lastaccess table has a two-field unique index, including
userid and courseid. In case both users has a record for the same
courseid, this plugin removes the record for the old user and keep that one
for the new user. For the rest of cases, this plugin operates as usual. - Special case #10: quiz_attempts table has a three-field unique index, including
userid, quiz and attempt. This table and related quiz_grades and quiz_grades_history
are processed as specified in the plugin settings. This plugin provies you
several options when merging quiz attempts from two users:
- Merge attempts from both users and renumber. Attempts from the old user are
merged with the ones of the new user and renumbered by the time they were
started. - Keep attempts from the new user. Attempts from the old user are removed.
Attempts from the new user are kept, since this option considers them as the
most important. - Keep attempts from the old user. Attempts from the new user are removed.
Attempts from the old user are kept, since this option considers them as the
most important. - Do nothing: do not merge nor delete (by default). Attempts are not merged nor
deleted, remaining related to the user who made them. This is the most secure
action, but merging users from user A to user B or B to A may produce different
quiz grades.
- Special case #11: there are cases where third party plugins build unique indexes
applied onto a single column related to user.id. In such cases, we have added
a new setting "uniquekeynewidtomaintain" that helps handles this conflict.
If you mark this option (by default), data related to the new user is kept.
Otherwise, if you unmark this setting, this plugin will keep the data from
the old user.
Command-line script
A cli/climerger.php script is added. You can now perform user mergings by command line having
their user ids.
You can go further and develop your own CLI script by extending the Gathering interface
(see lib/cligathering.php for an example). Ok, but let us explain how to do it step by step:
- Develop a class, namely MyGathering, in lib/mygathering.php, implementing the interface Gathering.
Be sure the class name and the filename are the same, but filename all in lowercase ending with ".php".
See lib/cligathering for an example. - Create or edit the file config/config.local.php with at least the following content:
<?php
return array(
// gathering tool
'gathering' => 'MyGathering',
);
- Run as a command line in a form like this: $ time php cli/climerger.php.
Events and event management
Once the merging action is completed, an event 'merging_success' is triggered if it was ok,
or an event 'merging_failed' otherwise. The available data on the event are as follows:
- oldid: the user.id of the "user A" to be removed from all his/her activity.
- newid: the user.id of the "user B" which will gather the activity of both users.
- log: string with the list of actions performed.
- timemodified: time in which the event is generated, after the merging action.
The goal of this event triggering is the ability to be detected by other parts of Moodle.
This plugin also manages the 'merging_success' event is trigered, what includes:
- Suspending the user (user.suspended = 1). This prevents the person to log in with the old account.
- Changing the old user's profile picture by the given on pix/suspended.jpg. It is a simple
white image with the text "suspended user", which could help to teachers and
managers to rapidly detect them.
Correct way of testing this plugin
First of all, check admin/settings.php?section=mergeusers_settings for the
description of the setting tool_mergeusers | transactions_only
if your database type and version supports transcations. If so,
no action will actually be committed if something goes wrong.
Mainly, these are the main steps to test this plugin:
- You should have a replica of your Moodle instance, with a full replica of your Moodle database where you run this plugin.
- Run a sufficient amount of user merging to check if anything goes wrong.
- What if...?
- ... all was ok? You are almost confident that all will be ok also in your production instance of Moodle.
- ... something went wrong? There are several reasons for that:
- Non-core plugins installed on your Moodle and not assumed in this plugin.
- Local database changes on Moodle that may affect to the normal execution of this plugin.
- Some compound index not detected yet.
If in your tests or already in production something went wrong, please, report the error log on the
official plugin website on moodle.org. And if you have some PHP skill, you can try to solve it
and share both the error and the patch to solve it ;-)
Common sense
Before running this plugin, it is highly recommended to back up your database.
That will help you to restore the state before any merging action was done.
This plugin stores a log for any user merging, with the list of actions done or
errors produced. If your database supports transactions (see above section),
automatic rollbacks are done at database level, so that your database state
remains consistent.
However, running this plugin in databases without
transaction support can put you in trouble. That is, there is no provision for
automatic rollbacks, so if something were to fail midway through,
you will end up with a half-updated database. Nevertheless, if you found a
problem when merging users A and B, do not panic. Merging will be successfully
completed when a solution for your problem is included into this plugin, and
you rerun merging users A and B.
Development
Developing and testing phase
We recommend to use the https://github.com/moodlehq/moodle-docker project to
run your own Moodle instances for developing and testing.
PHPUnit testing
To quickly setup your own development, we suggest to run the command:
php admin/tool/phpunit/cli/util.php --buildcomponentconfigs
as documented at https://docs.moodle.org/dev/PHPUnit to have the phpunit.xml
file under admin/tool/mergeusers/phpunit.xml.
Then, you can run all plugin's tests as follows:
vendor/bin/phpunit -c admin/tool/mergeusers
or also like this, without the need of running the buildcomponentconfigs:
vendor/bin/phpunit --group tool_mergeusers
There are also other PHPUnit groups created to help testing only the part
of the plugin of your choice. Take a look at the tests code for other group names.
Minimum requirements
- MySQL v5.x or MSSQL or Postgres
- Moodle v2.2
License
GNU GPL v3 or later. http://www.gnu.org/copyleft/gpl.html
Contributors
- Based on the mergeusers_v2.php script written by Nicolas Dunand.
- Updated for Moodle 2.0 by Mike Holzer [m.e.holzer AT gmail DOT com]
- Moodle 2.x report by Forrest Gaston
- Updated by Jordi Pujol-Ahulló (at SREd, Universitat Rovira i Virgili) with:
- several compound index on database tables,
- selector for the type of user identification (username, id, idnumber),
- more Moodle-like web and code, including web renderer,
- config.php with current configuration settings, used for merging,
- config.local.php to include local settings on your Moodle instance,
- log of any merging action in database for further reference,
- revisited web interface for the new wizard when merging users manually,
- TableMerger entities to process Moodle tables accordingly,
- quiz attempts are processed as suggested in
https://moodle.org/mod/forum/discuss.php?d=258979, adding 4 different options
for their processing.
- Web wizard for merging users by John Hoopes, University of Wisconsin - Madison
- Updated by Andrew Hancox with:
- improvements and fixing a bug on cli script.
- Plugin maintained by Nicolas Dunand [nicolas.dunand AT unil DOT ch]
1.18 for Moodle 3.4 and upwards (Build: 2018050401) (2018050401)
1.18 for Moodle 3.4 and upwards (Build: 2018050401)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2018050401
Version release name: 1.18 for Moodle 3.4 and upwards (Build: 2018050401)
Maturity: Stable
Supported Moodle versions: 3.4, 3.5, 3.6, 3.7
Repository URL (Git): https://github.com/ndunand/moodle-tool_mergeusers
Repository branch:
Repository tag: 2018050401
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Moodle compatibility
This plugin version is compatible from Moodle 3.4 and upwards.
Merge users script for Moodle
This script will merge two Moodle user accounts, "user A" and "user B".
The intent of the script is to assign all activity & records from user A to
user B. This will give the effect of user B seeming to have done everything
both users have ever done in Moodle. The basic function of the script is to
loop through the tables and update the userid of every record from user A to
user B. This works well for most tables. We do however, have a few special
cases:
- Special Case #1: The grade_grades table has a compound unique key on userid
and itemid. This prevents a simple update statement if the two users have
done the same activity. What this script does is determine which activities
have been completed by both users and delete the entry for the old user
from this table. Data is not lost because a duplicate entry can be found in
the grade_grades_history table, which is correctly updated by the regular
processing of the script. - Special Case #2: The user_enrolments table controls which user is enrolled
in which course. Rather than unenroll the old user from the course, this
script simply updates their access to the course to "2" which makes them
completely unable to access the course. To remove these records all
together I recomend disabling or deleting the entire old user account once
the migration has been successful. - Special Case #3: There are 4 logging/preference tables
(user_lastaccess, user_preferences, user_private_key, my_pages) which exist in
Moodle 2.x. This script is simply skipping these tables since there's no
legitimate purpose to updating the userid value here. This would lead to
duplicate rows for the new user which is silly. Again, if you want to
remove these records I would recommend deleting the old user after this
script runs sucessfully. my_pages' records will not be deleted, but
this is something you find in Moodle, that not all records related to a
specific entity are clened up. We need to skip my_pages table too, since
that MyMoodle page of the old user have a relation of blocks appearing on it.
If we proceed with a normal merging action, resulting with two records
with the same userid, the user will not see correctly his/her MyMoodle page.
Due to a community request, all these tables except my_pages can be omitted
from this exclusion and so, if set in settings, they can be merged as usual. - Special Case #4: mod/journal plugin has a record per user and journal on
journal_entries table. In case there is a record for both users, we delete
the record related to the old user. For the rest of cases, this operates as usual. - Special Case #5: groups_members table has a record per user and group.
Updating always the old user id for the new one is incorrect if both users
appear in that group. In that case, this plugin deletes the record related
to the old user. For the rest of cases, this plugin operates as usual. - Special Case #6: course_completions table has a record per user and course.
Updating always the old user id for the new one is incorrect if both users
appear in that group. In that case, this plugin deletes the record related
to the old user. For the rest of cases, this plugin operates as usual. - Special case #7: message_contacts table has a record per user and contact id,
which is again a user.id. If replacing the old id by the new one means
index conflict, this means actually that the resulting record already exists,
so we can securely remove the old record. In addition, this checking is performed
for both column names (userid and contactid) looking for matching on both
in the same way. - Special case #8: role_assignments table has a three-field unique index,
including context, role and userid. As before, it always updates records to
be the new one. If only old id exists, it is updated; if only new id exists,
it does nothing; if both ids exist, the record with the old id is removed. - Special case #9: user_lastaccess table has a two-field unique index, including
userid and courseid. In case both users has a record for the same
courseid, this plugin removes the record for the old user and keep that one
for the new user. For the rest of cases, this plugin operates as usual. - Special case #10: quiz_attempts table has a three-field unique index, including
userid, quiz and attempt. This table and related quiz_grades and quiz_grades_history
are processed as specified in the plugin settings. This plugin provies you
several options when merging quiz attempts from two users:
- Merge attempts from both users and renumber. Attempts from the old user are
merged with the ones of the new user and renumbered by the time they were
started. - Keep attempts from the new user. Attempts from the old user are removed.
Attempts from the new user are kept, since this option considers them as the
most important. - Keep attempts from the old user. Attempts from the new user are removed.
Attempts from the old user are kept, since this option considers them as the
most important. - Do nothing: do not merge nor delete (by default). Attempts are not merged nor
deleted, remaining related to the user who made them. This is the most secure
action, but merging users from user A to user B or B to A may produce different
quiz grades.
- Special case #11: there are cases where third party plugins build unique indexes
applied onto a single column related to user.id. In such cases, we have added
a new setting "uniquekeynewidtomaintain" that helps handles this conflict.
If you mark this option (by default), data related to the new user is kept.
Otherwise, if you unmark this setting, this plugin will keep the data from
the old user.
Command-line script
A cli/climerger.php script is added. You can now perform user mergings by command line having
their user ids.
You can go further and develop your own CLI script by extending the Gathering interface
(see lib/cligathering.php for an example). Ok, but let us explain how to do it step by step:
- Develop a class, namely MyGathering, in lib/mygathering.php, implementing the interface Gathering.
Be sure the class name and the filename are the same, but filename all in lowercase ending with ".php".
See lib/cligathering for an example. - Create or edit the file config/config.local.php with at least the following content:
<?php
return array(
// gathering tool
'gathering' => 'MyGathering',
);
- Run as a command line in a form like this: $ time php cli/climerger.php.
Events and event management
Once the merging action is completed, an event 'merging_success' is triggered if it was ok,
or an event 'merging_failed' otherwise. The available data on the event are as follows:
- oldid: the user.id of the "user A" to be removed from all his/her activity.
- newid: the user.id of the "user B" which will gather the activity of both users.
- log: string with the list of actions performed.
- timemodified: time in which the event is generated, after the merging action.
The goal of this event triggering is the ability to be detected by other parts of Moodle.
This plugin also manages the 'merging_success' event is trigered, what includes:
- Suspending the user (user.suspended = 1). This prevents the person to log in with the old account.
- Changing the old user's profile picture by the given on pix/suspended.jpg. It is a simple
white image with the text "suspended user", which could help to teachers and
managers to rapidly detect them.
Correct way of testing this plugin
First of all, check admin/settings.php?section=mergeusers_settings for the
description of the setting tool_mergeusers | transactions_only
if your database type and version supports transcations. If so,
no action will actually be committed if something goes wrong.
Mainly, these are the main steps to test this plugin:
- You should have a replica of your Moodle instance, with a full replica of your Moodle database where you run this plugin.
- Run a sufficient amount of user merging to check if anything goes wrong.
- What if...?
- ... all was ok? You are almost confident that all will be ok also in your production instance of Moodle.
- ... something went wrong? There are several reasons for that:
- Non-core plugins installed on your Moodle and not assumed in this plugin.
- Local database changes on Moodle that may affect to the normal execution of this plugin.
- Some compound index not detected yet.
If in your tests or already in production something went wrong, please, report the error log on the
official plugin website on moodle.org. And if you have some PHP skill, you can try to solve it
and share both the error and the patch to solve it ;-)
Common sense
Before running this plugin, it is highly recommended to back up your database.
That will help you to restore the state before any merging action was done.
This plugin stores a log for any user merging, with the list of actions done or
errors produced. If your database supports transactions (see above section),
automatic rollbacks are done at database level, so that your database state
remains consistent.
However, running this plugin in databases without
transaction support can put you in trouble. That is, there is no provision for
automatic rollbacks, so if something were to fail midway through,
you will end up with a half-updated database. Nevertheless, if you found a
problem when merging users A and B, do not panic. Merging will be successfully
completed when a solution for your problem is included into this plugin, and
you rerun merging users A and B.
Development
Developing and testing phase
We recommend to use the https://github.com/moodlehq/moodle-docker project to
run your own Moodle instances for developing and testing.
PHPUnit testing
To quickly setup your own development, we suggest to run the command:
php admin/tool/phpunit/cli/util.php --buildcomponentconfigs
as documented at https://docs.moodle.org/dev/PHPUnit to have the phpunit.xml
file under admin/tool/mergeusers/phpunit.xml.
Then, you can run all plugin's tests as follows:
vendor/bin/phpunit -c admin/tool/mergeusers
or also like this, without the need of running the buildcomponentconfigs:
vendor/bin/phpunit --group tool_mergeusers
There are also other PHPUnit groups created to help testing only the part
of the plugin of your choice. Take a look at the tests code for other group names.
Minimum requirements
- MySQL v5.x or MSSQL or Postgres
- Moodle v2.2
License
GNU GPL v3 or later. http://www.gnu.org/copyleft/gpl.html
Contributors
- Based on the mergeusers_v2.php script written by Nicolas Dunand.
- Updated for Moodle 2.0 by Mike Holzer [m.e.holzer AT gmail DOT com]
- Moodle 2.x report by Forrest Gaston
- Updated by Jordi Pujol-Ahulló (at SREd, Universitat Rovira i Virgili) with:
- several compound index on database tables,
- selector for the type of user identification (username, id, idnumber),
- more Moodle-like web and code, including web renderer,
- config.php with current configuration settings, used for merging,
- config.local.php to include local settings on your Moodle instance,
- log of any merging action in database for further reference,
- revisited web interface for the new wizard when merging users manually,
- TableMerger entities to process Moodle tables accordingly,
- quiz attempts are processed as suggested in
https://moodle.org/mod/forum/discuss.php?d=258979, adding 4 different options
for their processing.
- Web wizard for merging users by John Hoopes, University of Wisconsin - Madison
- Updated by Andrew Hancox with:
- improvements and fixing a bug on cli script.
- Plugin maintained by Nicolas Dunand [nicolas.dunand AT unil DOT ch]
1.17 for Moodle 3.4-3.5 (Build: 2018050400) (2018050400)
1.17 for Moodle 3.4-3.5 (Build: 2018050400)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2018050400
Version release name: 1.17 for Moodle 3.4-3.5 (Build: 2018050400)
Maturity: Stable
Supported Moodle versions: 3.4, 3.5
Repository URL (Git): https://github.com/ndunand/moodle-tool_mergeusers
Repository branch:
Repository tag: 2018050400
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Moodle compatibility
This plugin version is compatible from Moodle 3.4 and upwards.
Merge users script for Moodle
This script will merge two Moodle user accounts, "user A" and "user B".
The intent of the script is to assign all activity & records from user A to
user B. This will give the effect of user B seeming to have done everything
both users have ever done in Moodle. The basic function of the script is to
loop through the tables and update the userid of every record from user A to
user B. This works well for most tables. We do however, have a few special
cases:
- Special Case #1: The grade_grades table has a compound unique key on userid
and itemid. This prevents a simple update statement if the two users have
done the same activity. What this script does is determine which activities
have been completed by both users and delete the entry for the old user
from this table. Data is not lost because a duplicate entry can be found in
the grade_grades_history table, which is correctly updated by the regular
processing of the script. - Special Case #2: The user_enrolments table controls which user is enrolled
in which course. Rather than unenroll the old user from the course, this
script simply updates their access to the course to "2" which makes them
completely unable to access the course. To remove these records all
together I recomend disabling or deleting the entire old user account once
the migration has been successful. - Special Case #3: There are 4 logging/preference tables
(user_lastaccess, user_preferences, user_private_key, my_pages) which exist in
Moodle 2.x. This script is simply skipping these tables since there's no
legitimate purpose to updating the userid value here. This would lead to
duplicate rows for the new user which is silly. Again, if you want to
remove these records I would recommend deleting the old user after this
script runs sucessfully. my_pages' records will not be deleted, but
this is something you find in Moodle, that not all records related to a
specific entity are clened up. We need to skip my_pages table too, since
that MyMoodle page of the old user have a relation of blocks appearing on it.
If we proceed with a normal merging action, resulting with two records
with the same userid, the user will not see correctly his/her MyMoodle page.
Due to a community request, all these tables except my_pages can be omitted
from this exclusion and so, if set in settings, they can be merged as usual. - Special Case #4: mod/journal plugin has a record per user and journal on
journal_entries table. In case there is a record for both users, we delete
the record related to the old user. For the rest of cases, this operates as usual. - Special Case #5: groups_members table has a record per user and group.
Updating always the old user id for the new one is incorrect if both users
appear in that group. In that case, this plugin deletes the record related
to the old user. For the rest of cases, this plugin operates as usual. - Special Case #6: course_completions table has a record per user and course.
Updating always the old user id for the new one is incorrect if both users
appear in that group. In that case, this plugin deletes the record related
to the old user. For the rest of cases, this plugin operates as usual. - Special case #7: message_contacts table has a record per user and contact id,
which is again a user.id. If replacing the old id by the new one means
index conflict, this means actually that the resulting record already exists,
so we can securely remove the old record. In addition, this checking is performed
for both column names (userid and contactid) looking for matching on both
in the same way. - Special case #8: role_assignments table has a three-field unique index,
including context, role and userid. As before, it always updates records to
be the new one. If only old id exists, it is updated; if only new id exists,
it does nothing; if both ids exist, the record with the old id is removed. - Special case #9: user_lastaccess table has a two-field unique index, including
userid and courseid. In case both users has a record for the same
courseid, this plugin removes the record for the old user and keep that one
for the new user. For the rest of cases, this plugin operates as usual. - Special case #10: quiz_attempts table has a three-field unique index, including
userid, quiz and attempt. This table and related quiz_grades and quiz_grades_history
are processed as specified in the plugin settings. This plugin provies you
several options when merging quiz attempts from two users:
- Merge attempts from both users and renumber. Attempts from the old user are
merged with the ones of the new user and renumbered by the time they were
started. - Keep attempts from the new user. Attempts from the old user are removed.
Attempts from the new user are kept, since this option considers them as the
most important. - Keep attempts from the old user. Attempts from the new user are removed.
Attempts from the old user are kept, since this option considers them as the
most important. - Do nothing: do not merge nor delete (by default). Attempts are not merged nor
deleted, remaining related to the user who made them. This is the most secure
action, but merging users from user A to user B or B to A may produce different
quiz grades.
- Special case #11: there are cases where third party plugins build unique indexes
applied onto a single column related to user.id. In such cases, we have added
a new setting "uniquekeynewidtomaintain" that helps handles this conflict.
If you mark this option (by default), data related to the new user is kept.
Otherwise, if you unmark this setting, this plugin will keep the data from
the old user.
Command-line script
A cli/climerger.php script is added. You can now perform user mergings by command line having
their user ids.
You can go further and develop your own CLI script by extending the Gathering interface
(see lib/cligathering.php for an example). Ok, but let us explain how to do it step by step:
- Develop a class, namely MyGathering, in lib/mygathering.php, implementing the interface Gathering.
Be sure the class name and the filename are the same, but filename all in lowercase ending with ".php".
See lib/cligathering for an example. - Create or edit the file config/config.local.php with at least the following content:
<?php
return array(
// gathering tool
'gathering' => 'MyGathering',
);
- Run as a command line in a form like this: $ time php cli/climerger.php.
Events and event management
Once the merging action is completed, an event 'merging_success' is triggered if it was ok,
or an event 'merging_failed' otherwise. The available data on the event are as follows:
- oldid: the user.id of the "user A" to be removed from all his/her activity.
- newid: the user.id of the "user B" which will gather the activity of both users.
- log: string with the list of actions performed.
- timemodified: time in which the event is generated, after the merging action.
The goal of this event triggering is the ability to be detected by other parts of Moodle.
This plugin also manages the 'merging_success' event is trigered, what includes:
- Suspending the user (user.suspended = 1). This prevents the person to log in with the old account.
- Changing the old user's profile picture by the given on pix/suspended.jpg. It is a simple
white image with the text "suspended user", which could help to teachers and
managers to rapidly detect them.
Correct way of testing this plugin
First of all, check admin/settings.php?section=mergeusers_settings for the
description of the setting tool_mergeusers | transactions_only
if your database type and version supports transcations. If so,
no action will actually be committed if something goes wrong.
Mainly, these are the main steps to test this plugin:
- You should have a replica of your Moodle instance, with a full replica of your Moodle database where you run this plugin.
- Run a sufficient amount of user merging to check if anything goes wrong.
- What if...?
- ... all was ok? You are almost confident that all will be ok also in your production instance of Moodle.
- ... something went wrong? There are several reasons for that:
- Non-core plugins installed on your Moodle and not assumed in this plugin.
- Local database changes on Moodle that may affect to the normal execution of this plugin.
- Some compound index not detected yet.
If in your tests or already in production something went wrong, please, report the error log on the
official plugin website on moodle.org. And if you have some PHP skill, you can try to solve it
and share both the error and the patch to solve it ;-)
Common sense
Before running this plugin, it is highly recommended to back up your database.
That will help you to restore the state before any merging action was done.
This plugin stores a log for any user merging, with the list of actions done or
errors produced. If your database supports transactions (see above section),
automatic rollbacks are done at database level, so that your database state
remains consistent.
However, running this plugin in databases without
transaction support can put you in trouble. That is, there is no provision for
automatic rollbacks, so if something were to fail midway through,
you will end up with a half-updated database. Nevertheless, if you found a
problem when merging users A and B, do not panic. Merging will be successfully
completed when a solution for your problem is included into this plugin, and
you rerun merging users A and B.
Development
Developing and testing phase
We recommend to use the https://github.com/moodlehq/moodle-docker project to
run your own Moodle instances for developing and testing.
PHPUnit testing
To quickly setup your own development, we suggest to run the command:
php admin/tool/phpunit/cli/util.php --buildcomponentconfigs
as documented at https://docs.moodle.org/dev/PHPUnit to have the phpunit.xml
file under admin/tool/mergeusers/phpunit.xml.
Then, you can run all plugin's tests as follows:
vendor/bin/phpunit -c admin/tool/mergeusers
or also like this, without the need of running the buildcomponentconfigs:
vendor/bin/phpunit --group tool_mergeusers
There are also other PHPUnit groups created to help testing only the part
of the plugin of your choice. Take a look at the tests code for other group names.
Minimum requirements
- MySQL v5.x or MSSQL or Postgres
- Moodle v2.2
License
GNU GPL v3 or later. http://www.gnu.org/copyleft/gpl.html
Contributors
- Based on the mergeusers_v2.php script written by Nicolas Dunand.
- Updated for Moodle 2.0 by Mike Holzer [m.e.holzer AT gmail DOT com]
- Moodle 2.x report by Forrest Gaston
- Updated by Jordi Pujol-Ahulló (at SREd, Universitat Rovira i Virgili) with:
- several compound index on database tables,
- selector for the type of user identification (username, id, idnumber),
- more Moodle-like web and code, including web renderer,
- config.php with current configuration settings, used for merging,
- config.local.php to include local settings on your Moodle instance,
- log of any merging action in database for further reference,
- revisited web interface for the new wizard when merging users manually,
- TableMerger entities to process Moodle tables accordingly,
- quiz attempts are processed as suggested in
https://moodle.org/mod/forum/discuss.php?d=258979, adding 4 different options
for their processing.
- Web wizard for merging users by John Hoopes, University of Wisconsin - Madison
- Updated by Andrew Hancox with:
- improvements and fixing a bug on cli script.
- Plugin maintained by Nicolas Dunand [nicolas.dunand AT unil DOT ch]
1.16 for Moodle 3.4 (Build: 2018031601) (2018031601)
1.16 for Moodle 3.4 (Build: 2018031601)
Plugin type: Administration tools
Frankenstyle component name: tool_mergeusers
Version build number: 2018031601
Version release name: 1.16 for Moodle 3.4 (Build: 2018031601)
Maturity: Stable
Supported Moodle versions: 3.4
Repository URL (Git): https://github.com/ndunand/moodle-tool_mergeusers
Repository branch: master
Repository tag: 2018031601
Issue/bug tracker URL: https://github.com/jpahullo/moodle-tool_mergeusers/issues
Moodle compatibility
This plugin version is compatible from Moodle 3.4 and upwards.
Merge users script for Moodle
This script will merge two Moodle user accounts, "user A" and "user B".
The intent of the script is to assign all activity & records from user A to
user B. This will give the effect of user B seeming to have done everything
both users have ever done in Moodle. The basic function of the script is to
loop through the tables and update the userid of every record from user A to
user B. This works well for most tables. We do however, have a few special
cases:
- Special Case #1: The grade_grades table has a compound unique key on userid
and itemid. This prevents a simple update statement if the two users have
done the same activity. What this script does is determine which activities
have been completed by both users and delete the entry for the old user
from this table. Data is not lost because a duplicate entry can be found in
the grade_grades_history table, which is correctly updated by the regular
processing of the script. - Special Case #2: The user_enrolments table controls which user is enrolled
in which course. Rather than unenroll the old user from the course, this
script simply updates their access to the course to "2" which makes them
completely unable to access the course. To remove these records all
together I recomend disabling or deleting the entire old user account once
the migration has been successful. - Special Case #3: There are 4 logging/preference tables
(user_lastaccess, user_preferences, user_private_key, my_pages) which exist in
Moodle 2.x. This script is simply skipping these tables since there's no
legitimate purpose to updating the userid value here. This would lead to
duplicate rows for the new user which is silly. Again, if you want to
remove these records I would recommend deleting the old user after this
script runs sucessfully. my_pages' records will not be deleted, but
this is something you find in Moodle, that not all records related to a
specific entity are clened up. We need to skip my_pages table too, since
that MyMoodle page of the old user have a relation of blocks appearing on it.
If we proceed with a normal merging action, resulting with two records
with the same userid, the user will not see correctly his/her MyMoodle page.
Due to a community request, all these tables except my_pages can be omitted
from this exclusion and so, if set in settings, they can be merged as usual. - Special Case #4: mod/journal plugin has a record per user and journal on
journal_entries table. In case there is a record for both users, we delete
the record related to the old user. For the rest of cases, this operates as usual. - Special Case #5: groups_members table has a record per user and group.
Updating always the old user id for the new one is incorrect if both users
appear in that group. In that case, this plugin deletes the record related
to the old user. For the rest of cases, this plugin operates as usual. - Special Case #6: course_completions table has a record per user and course.
Updating always the old user id for the new one is incorrect if both users
appear in that group. In that case, this plugin deletes the record related
to the old user. For the rest of cases, this plugin operates as usual. - Special case #7: message_contacts table has a record per user and contact id,
which is again a user.id. If replacing the old id by the new one means
index conflict, this means actually that the resulting record already exists,
so we can securely remove the old record. In addition, this checking is performed
for both column names (userid and contactid) looking for matching on both
in the same way. - Special case #8: role_assignments table has a three-field unique index,
including context, role and userid. As before, it always updates records to
be the new one. If only old id exists, it is updated; if only new id exists,
it does nothing; if both ids exist, the record with the old id is removed. - Special case #9: user_lastaccess table has a two-field unique index, including
userid and courseid. In case both users has a record for the same
courseid, this plugin removes the record for the old user and keep that one
for the new user. For the rest of cases, this plugin operates as usual. - Special case #10: quiz_attempts table has a three-field unique index, including
userid, quiz and attempt. This table and related quiz_grades and quiz_grades_history
are processed as specified in the plugin settings. This plugin provies you
several options when merging quiz attempts from two users:
- Merge attempts from both users and renumber. Attempts from the old user are
merged with the ones of the new user and renumbered by the time they were
started. - Keep attempts from the new user. Attempts from the old user are removed.
Attempts from the new user are kept, since this option considers them as the
most important. - Keep attempts from the old user. Attempts from the new user are removed.
Attempts from the old user are kept, since this option considers them as the
most important. - Do nothing: do not merge nor delete (by default). Attempts are not merged nor
deleted, remaining related to the user who made them. This is the most secure
action, but merging users from user A to user B or B to A may produce different
quiz grades.
- Special case #11: there are cases where third party plugins build unique indexes
applied onto a single column related to user.id. In such cases, we have added
a new setting "uniquekeynewidtomaintain" that helps handles this conflict.
If you mark this option (by default), data related to the new user is kept.
Otherwise, if you unmark this setting, this plugin will keep the data from
the old user.
Command-line script
A cli/climerger.php script is added. You can now perform user mergings by command line having
their user ids.
You can go further and develop your own CLI script by extending the Gathering interface
(see lib/cligathering.php for an example). Ok, but let us explain how to do it step by step:
- Develop a class, namely MyGathering, in lib/mygathering.php, implementing the interface Gathering.
Be sure the class name and the filename are the same, but filename all in lowercase ending with ".php".
See lib/cligathering for an example. - Create or edit the file config/config.local.php with at least the following content:
<?php
return array(
// gathering tool
'gathering' => 'MyGathering',
);
- Run as a command line in a form like this: $ time php cli/climerger.php.
Events and event management
Once the merging action is completed, an event 'merging_success' is triggered if it was ok,
or an event 'merging_failed' otherwise. The available data on the event are as follows:
- oldid: the user.id of the "user A" to be removed from all his/her activity.
- newid: the user.id of the "user B" which will gather the activity of both users.
- log: string with the list of actions performed.
- timemodified: time in which the event is generated, after the merging action.
The goal of this event triggering is the ability to be detected by other parts of Moodle.
This plugin also manages the 'merging_success' event is trigered, what includes:
- Suspending the user (user.suspended = 1). This prevents the person to log in with the old account.
- Changing the old user's profile picture by the given on pix/suspended.jpg. It is a simple
white image with the text "suspended user", which could help to teachers and
managers to rapidly detect them.
Correct way of testing this plugin
First of all, check admin/settings.php?section=mergeusers_settings for the
description of the setting tool_mergeusers | transactions_only
if your database type and version supports transcations. If so,
no action will actually be committed if something goes wrong.
Mainly, these are the main steps to test this plugin:
- You should have a replica of your Moodle instance, with a full replica of your Moodle database where you run this plugin.
- Run a sufficient amount of user merging to check if anything goes wrong.
- What if...?
- ... all was ok? You are almost confident that all will be ok also in your production instance of Moodle.
- ... something went wrong? There are several reasons for that:
- Non-core plugins installed on your Moodle and not assumed in this plugin.
- Local database changes on Moodle that may affect to the normal execution of this plugin.
- Some compound index not detected yet.
If in your tests or already in production something went wrong, please, report the error log on the
official plugin website on moodle.org. And if you have some PHP skill, you can try to solve it
and share both the error and the patch to solve it ;-)
Common sense
Before running this plugin, it is highly recommended to back up your database.
That will help you to restore the state before any merging action was done.
This plugin stores a log for any user merging, with the list of actions done or
errors produced. If your database supports transactions (see above section),
automatic rollbacks are done at database level, so that your database state
remains consistent.
However, running this plugin in databases without
transaction support can put you in trouble. That is, there is no provision for
automatic rollbacks, so if something were to fail midway through,
you will end up with a half-updated database. Nevertheless, if you found a
problem when merging users A and B, do not panic. Merging will be successfully
completed when a solution for your problem is included into this plugin, and
you rerun merging users A and B.
Development
Developing and testing phase
We recommend to use the https://github.com/moodlehq/moodle-docker project to
run your own Moodle instances for developing and testing.
PHPUnit testing
To quickly setup your own development, we suggest to run the command:
php admin/tool/phpunit/cli/util.php --buildcomponentconfigs
as documented at https://docs.moodle.org/dev/PHPUnit to have the phpunit.xml
file under admin/tool/mergeusers/phpunit.xml.
Then, you can run all plugin's tests as follows:
vendor/bin/phpunit -c admin/tool/mergeusers
or also like this, without the need of running the buildcomponentconfigs:
vendor/bin/phpunit --group tool_mergeusers
There are also other PHPUnit groups created to help testing only the part
of the plugin of your choice. Take a look at the tests code for other group names.
Minimum requirements
- MySQL v5.x or MSSQL or Postgres
- Moodle v2.2
License
GNU GPL v3 or later. http://www.gnu.org/copyleft/gpl.html
Contributors
- Based on the mergeusers_v2.php script written by Nicolas Dunand.
- Updated for Moodle 2.0 by Mike Holzer [m.e.holzer AT gmail DOT com]
- Moodle 2.x report by Forrest Gaston
- Updated by Jordi Pujol-Ahulló (at SREd, Universitat Rovira i Virgili) with:
- several compound index on database tables,
- selector for the type of user identification (username, id, idnumber),
- more Moodle-like web and code, including web renderer,
- config.php with current configuration settings, used for merging,
- config.local.php to include local settings on your Moodle instance,
- log of any merging action in database for further reference,
- revisited web interface for the new wizard when merging users manually,
- TableMerger entities to process Moodle tables accordingly,
- quiz attempts are processed as suggested in
https://moodle.org/mod/forum/discuss.php?d=258979, adding 4 different options
for their processing.
- Web wizard for merging users by John Hoopes, University of Wisconsin - Madison
- Updated by Andrew Hancox with:
- improvements and fixing a bug on cli script.
- Plugin maintained by Nicolas Dunand [nicolas.dunand AT unil DOT ch]