Both sides previous revision Previous revision Next revision | Previous revision |
en:entwickler:changelog_implementation [2025/02/16 11:39] – [Part D: Additional Steps for Third-Party Extensions] kainhofer | en:entwickler:changelog_implementation [2025/03/21 08:55] (current) – kainhofer |
---|
Starting with Admidio 5.0, all changes to objects (Users, Events, Groups/Roles, Weblinks, Albums, Folders/Files, ...) and settings that are saved in Admidio's database can be logged and the changes displayed in the Change History screen. Logging can be enabled per object type (=database table) in the preferences. Each object or list with changelogs enabled will display a changelog button to view it: | Starting with Admidio 5.0, all changes to objects (Users, Events, Groups/Roles, Weblinks, Albums, Folders/Files, ...) and settings that are saved in Admidio's database can be logged and the changes displayed in the Change History screen. Logging can be enabled per object type (=database table) in the preferences. Each object or list with changelogs enabled will display a changelog button to view it: |
| |
}{{:en:entwickler:changelog:changelog_view_overview.png?400|The new changelog view}}{{:en:entwickler:changelog:changelog_settings.png?400|Settings for the changelog}}{{:en:entwickler:changelog:changelog_button_preferences.png?200|View changelog button}} | {{:en:entwickler:changelog:changelog_view_overview.png?400|The new changelog view}}{{:en:entwickler:changelog:changelog_settings.png?400|Settings for the changelog}}{{:en:entwickler:changelog:changelog_button_preferences.png?200|View changelog button}} |
| |
| |
====== Part C: Steps to Extend the Admidio Core with a New Module / Plugin ====== | ====== Part C: Steps to Extend the Admidio Core with a New Module / Plugin ====== |
| |
At the example of the Forum module's tables (adm_forum_posts and adm_forum_topics), these are the steps to implement full support. Basic changelog support already works out of the box with no required code changes (enabled with the ''changelog_table_others'' preference flag for all unknown or third-party database table). | At the example of the Forum module's tables (adm_forum_posts and adm_forum_topics), these are the steps to implement full support. Basic changelog support already works out of the box with no required code changes (enabled with the ''changelog_table_others'' preference flag for all unknown or third-party database table). All changes described here are only required to get a nicer changelog view with links and easy-to-understand labels. |
| |
| The example of the forum module is taken directly from the admidio code tree ([[https://github.com/Admidio/admidio/commit/ff61d0a0029be89e88a4bccdfbb227b9af612efc|commit ff61d0a on github]]) |
| |
- **A: Preparation / General setup for forum logging** | - **A: Preparation / General setup for forum logging** |
====== Part D: Additional Steps for Third-Party Extensions ====== | ====== Part D: Additional Steps for Third-Party Extensions ====== |
| |
Adding support for changelogs in third-party extensions, where modifying the core Admidio code is not possible, works similar to the above steps. Modifying the changelog entry creation is implemented inside the extension's Entity-derived database access classes, so this part is similar to core modules. Unfortunately, the adjustments to the changelog itself is done directly in the Admidio core code in the class ''ChangelogService'' and is currently not possible for third-party extensions. | Adding support for changelogs in third-party extensions, where modifying the core Admidio code is not possible, works similar to the above steps. Modifying the changelog entry creation is implemented inside the extension's Entity-derived database access classes, so this part is similar to core modules. However, the formatting in the Change history page view is implemented in the class ''ChangelogService'' for the core modules, which is not directly available for change to third-party extension developers. |
| |
However, the ChanglogService class is structured in a way that for each method, one could either | |
* add a method to append mappings directly to the arrays used in the static method of the Changelog class, or | |
* add a list of callback functions that are called in turn, when the default code does not handle a certain table/column/object. One would need to add a method to register such a callback function for each of the static methods. | |
| |
This generalization of the ChangelogService class is not yet done, and also not currently planned. However, anyone interested can start working on it and submit patches to the admidio project. | However, the ChanglogService class additionally provides a way to register mapping tables for table/column names or general callback functions for all the methods that need modifications as described above. The callback functions are registered with the method <code php>/** |
| * Register a callback function or value for the changelog functionality. If the callback is a value (string, array, etc.), it will |
| * be returned. If the callback is a function, it will be executed and if the return value is not empty, it will be returned. If the |
| * function returns a null or empty value, the next callback or the default processing of the ChangelogService method will proceed. |
| * @param string $function The method of the ChangelogService class that should be customized. One of |
| * 'getTableLabel', 'getTableLabelArray', 'getObjectForTable', 'getFieldTranslations', 'createLink', |
| * 'formatValue', 'getRelatedTable', 'getPermittedTables' |
| * @param string $moduleOrKey The module or type that should be customized. If empty, the callback will be |
| * executed for all values and it will be used if it evaluates to a non-empty value. |
| * @param mixed $callback The callback function or value. A value will be returned unchanged, a function will |
| be executed (arguments are identical to the ChangelogService's methods) |
| */ |
| static ChangelogService::registerCallback(string $function, string $moduleOrKey, mixed $callback)</code> |
| |
======= TODO ======= | Using these callback mechanisms, the forum changelog described above could also be implemented with the following code. It should be executed somewhere during php startup when the third-party module is loaded, and before either a changelog page can be displayed or before any of the third-party extension's database records are modified (i.e. before the extension writes data to the database). |
| |
* How to add new tables/objects to the logging (core development or third-party) | <code php> |
* General setup for basic logging | |
* Translating DB name and columns (display in changelog) | ## Translation of database tables |
* Adding links to the objects | ChangelogService::registerCallback('getTableLabelArray', 'forum_topics', 'SYS_FORUM_TOPIC'); |
* adding data types to DB columns | ChangelogService::registerCallback('getTableLabelArray', 'forum_posts', 'SYS_FORUM_POST'); |
* Ignoring certain tables, columns or changes | |
* Logging a change as something different (e.g. creation of a membership records as a modification of a user) | ## Translations and type definitions of database columns |
* Displaying the changelog button | ChangelogService::registerCallback('getFieldTranslations', '', [ |
* | 'fot_cat_id' => array('name' => 'SYS_CATEGORY', 'type' => 'CATEGORY'), |
| 'fot_fop_id_first_post' => array('name' => 'SYS_FORUM_POST', 'type' => 'POST'), |
| 'fot_title' => 'SYS_TITLE', |
| 'fop_text' => 'SYS_TEXT', |
| 'fop_fot_id' => array('name' => 'SYS_FORUM_TOPIC', 'type' => 'TOPIC') |
| ]); |
| |
| ## Formatting of new database column types (in many cases not needed) |
| ChangelogService::registerCallback('formatValue', 'TOPIC', function($value, $type, $entries = []) { |
| global $gDb; |
| if (empty($value)) return ''; |
| $obj = new Topic($gDb, $value??0); |
| return ChangelogService::createLink($obj->readableName(), 'forum_topics', |
| $obj->getValue('fot_id'), $obj->getValue('fot_uuid')); |
| }); |
| ChangelogService::registerCallback('formatValue', 'POST', function($value, $type, $entries = []) { |
| global $gDb; |
| if (empty($value)) return ''; |
| $obj = new POST($gDb, $value??0); |
| return ChangelogService::createLink($obj->readableName(), 'forum_posts', |
| $obj->getValue('fop_id'), $obj->getValue('fop_uuid')); |
| }); |
| |
| ## Create HTML links to the object's list view and edit pages |
| ChangelogService::registerCallback('createLink', 'forum_topics', function(string $text, string $module, int|string $id, string $uuid = '') { |
| return SecurityUtils::encodeUrl( ADMIDIO_URL.FOLDER_MODULES.'/forum.php', |
| array('mode' => 'topic', 'topic_uuid' => $uuid)); |
| }); |
| ChangelogService::registerCallback('createLink', 'forum_posts', function(string $text, string $module, int|string $id, string $uuid = '') { |
| return SecurityUtils::encodeUrl( ADMIDIO_URL.FOLDER_MODULES.'/forum.php', |
| array('mode' => 'post_edit', 'post_uuid' => $uuid)); |
| }); |
| |
| ## Object types of related objects (if object relations are used at all!) |
| ChangelogService::registerCallback('getRelatedTable', 'forum_topics', 'forum_posts'); |
| ChangelogService::registerCallback('getRelatedTable', 'forum_posts', 'forum_topics'); |
| |
| |
| ## Create Entity-derived objects to create headlines with proper object names |
| ChangelogService::registerCallback('getObjectForTable', 'forum_topics', function() {global $gDb; return new Topic($gDb);}); |
| ChangelogService::registerCallback('getObjectForTable', 'forum_posts', function() {global $gDb; return new Post($gDb);}); |
| |
| ## Enable per-user detection of access permissions to the tables (based on user's role permission); Admin is always allowed |
| ChangelogService::registerCallback('getPermittedTables', '', function(User $user) { |
| if ($user->administrateForum()) |
| return ['forum_topics', 'forum_posts']; |
| }); |
| </code> |