As of Q1 2020 Tuleap still runs Mediawiki 1.23, it's old, it's no longer maintained, it was already a pita to make it compatible with recent PHP version.
We had to keep this because of RHEL/CentOS6 compat' but now it's gone we can upgrade to a recent version. At time of writing, 1.35 is the last LTS, published in September 2020 and is a good candidate, esp. because it comes with the brand new VisualEditor that everybody and their dog wants.
That said, VisualEditor will come with a major change in the way Mediawiki is integrated in Tuleap
The Major Change
As of today, most of the users knows Mediawiki in Tuleap as "Mediawiki wrapped into Tuleap":
This view will no longer be possible after upgrade to 1.35. Mediawiki will be displayed as a standalone app.
This screenshot was made with 1.23 version of Mediawiki with the "Fullscreen" mode that is already available for project admin that want to activate the WikiEditor extension (poor's man wysiwyg that was available back then).
To be more specific, we can be closer to the "embedded" look by usage a Tuleap Sidebar WebComponent:
With this approach, teams will clearly understand that their mediawiki is actually "in a Tuleap project" with all direct access to other part of the project (services).
Note that, in order to render the sidebar, the integration will require to fetch information from Tuleap (current project, visibility, list of services, etc) while this is manageable for the sidebar, it seems more complex to do with the navigation bar (at the top) as a start. However this might be a possible future work.
The changes needed to integrated this sidebar in a bare mediawiki is relatively small, so maintenance should be easy.
A dedicated request details the Sidebar component extraction, see art #23465
Why this change ?
The reason to remove "Mediawiki wrapped into Tuleap" is actually the same then the one that lead to "Fullscreen" mode: the "wrapped" mode is a (pill of dirty) hack. Most of those hacks block usage of extensions, especially the one related to "front end". Here we are talking to VisualEditor.
So, basically, it's not possible to have VisualEditor in "wrapped" mode and upgrading to 1.35 without VisualEditor makes little sense, especially in 2021. Most users doesn't feel to write (Mediawiki) markup by hand.
Architecture
graph LR
User --> reverse-proxy[Reverse proxy]
subgraph tlp-srv [Tuleap Server]
reverse-proxy --> Mediawiki
reverse-proxy --> Tuleap
Mediawiki -. interface .- Tuleap
end
subgraph db [Database Server]
Mediawiki --> mw-db[(MW Database)]
Tuleap --> tlp-db[(Tuleap Database)]
end
With separated Mediawiki, it means that we could run the 2 apps in 2 completely different set of servers with different database & co. However we need to be careful with this approach as there are "connections" between Tuleap and Mediawiki that are not only visual:
- Session & user management (users are authenticated on both side)
- Groups management (admin can define mediawiki permissions based on groups defined in Tuleap)
- Cross references (Tuleap cross references are recognized by Mediawiki)
For the record, a spike for a previous update was conducted can be seen at gerrit #9844
Interfaces
Tuleap and Mediawiki should be as decoupled as possible. Ideally they should be able to run different version of PHP, NodeJS, etc.
Integration should be designed after REST API, keeping in mind that REST calls are not cheap and we cannot afford to make 10 REST calls at each page rendered by mediawiki (the cost would be at least 500ms which unacceptable). However it's perfectly doable to have one REST end point dedicated to MW integration at Tuleap side.
Typical integration sequence:
sequenceDiagram
participant U as User
participant M as Mediawiki
participant T as Tuleap
U->>+M: Access Mediawiki
M->>+T: Send Cookie
T->>-M: Send user<br>groups<br>project<br>services<br>...
M->>M: Session & User management
M->>-U: Render page
Migration
TBC...
Deprecations
- Tuleap embed UniversalLanguageSelector and a few other extensions. However this was done for a very specific purpose and never documented. It should probably be deprecated and not ported. This is referred to as
MLEB
in this document.
Integration points with Tuleap
Tuleap Hooks
This is the list of hooks Mediawiki plugin is listening to.
$this->addHook('cssfile');
custom css, should no longer be needed.
$this->addHook(Event::SERVICES_ALLOWED_FOR_PROJECT);
Control whether Mediawiki should appear in the list of services. Covered by story #24227. Done.
$this->addHook(Event::SERVICE_CLASSNAMES);
Custom Service
class for MW. Manage custom icon, who is admin of the service, etc. Covered by story #24227. Done.
$this->addHook(ServiceUrlCollector::NAME);
Integrate with FrontRouter
to route MW URLs. Not action needed for migration.
$this->addHook(Event::GET_PROJECTID_FROM_URL);
Integrate with legacy project based permission guard (private project, restricted user, etc). Cannot be used in standalone mediawiki (no pre.php), should be covered by story #25738.
$this->addHook('permission_get_name');
Define the Tuleap mediawiki permissions "Overall Read" and "Overall Write".
Must be kept and taken into account. Covered by story #25733.
$this->addHook(PermissionPerGroupPaneCollector::NAME);
Show mediawiki permission in project administration "Permission per group" panel. Covered by story #25733.
$this->addHook(Event::SERVICE_IS_USED);
Actions to perform when project admin activate Mediawiki service in a project. Covered by story #24228.
$this->addHook(RegisterProjectCreationEvent::NAME);
Actions to perform when a project is created. Covered by story #24228.
$this->addHook(Event::RENAME_PROJECT, 'rename_project');
Change of project shortname (hence mediawiki url). Covered by story #24228.
$this->addHook('project_is_deleted');
Actions to perform when project is deleted. Covered by story #24228.
$this->addHook(Event::GET_SYSTEM_EVENT_CLASS, 'getSystemEventClass');
$this->addHook(Event::SYSTEM_EVENT_GET_TYPES_FOR_DEFAULT_QUEUE);
Backend events for mediawiki. There are 2 events ATM:
-
SystemEvent_MEDIAWIKI_SWITCH_TO_123::NAME
=> No need to do anything with Mediawiki Standalone.
-
SystemEvent_MEDIAWIKI_TO_CENTRAL_DB::NAME
=> allows to switch from a mediawiki database per project
to one central DB for all mediawiki
(tables split by projects). Covered by story #25740.
$this->addHook('project_admin_remove_user');
$this->addHook('project_admin_change_user_permissions');
$this->addHook('project_admin_ugroup_remove_user');
$this->addHook('project_admin_remove_user_from_project_ugroups');
$this->addHook('project_admin_ugroup_deletion');
$this->addHook(UserBecomesProjectAdmin::NAME, 'updateUserGroupMappingFromUserAndProjectUGroupRelationshipEvent');
$this->addHook(UserIsNoLongerProjectAdmin::NAME, 'updateUserGroupMappingFromUserAndProjectUGroupRelationshipEvent');
$this->addHook(UserBecomesWikiAdmin::NAME, 'updateUserGroupMappingFromUserAndProjectUGroupRelationshipEvent');
$this->addHook(UserIsNoLongerWikiAdmin::NAME, 'updateUserGroupMappingFromUserAndProjectUGroupRelationshipEvent');
$this->addHook(UserBecomesForumAdmin::NAME, 'updateUserGroupMappingFromUserAndProjectUGroupRelationshipEvent');
$this->addHook(UserIsNoLongerForumAdmin::NAME, 'updateUserGroupMappingFromUserAndProjectUGroupRelationshipEvent');
$this->addHook(UserBecomesNewsWriter::NAME, 'updateUserGroupMappingFromUserAndProjectUGroupRelationshipEvent');
$this->addHook(UserIsNoLongerNewsWriter::NAME, 'updateUserGroupMappingFromUserAndProjectUGroupRelationshipEvent');
$this->addHook(UserBecomesNewsAdministrator::NAME, 'updateUserGroupMappingFromUserAndProjectUGroupRelationshipEvent');
$this->addHook(UserIsNoLongerNewsAdministrator::NAME, 'updateUserGroupMappingFromUserAndProjectUGroupRelationshipEvent');
Management of user groups membership (add/remove) in a project and in project's groups. Covered by story #25733.
$this->addHook(User_ForgeUserGroupPermissionsFactory::GET_PERMISSION_DELEGATION);
$this->addHook(DelegatedUserAccessForProject::NAME);
Tuleap allows to define an administrator of all Mediawiki of the platform (this person can even access mediawiki in private project they are not member of).
This is the event that control this behaviour.
Covered by story #25733.
$this->addHook(RestrictedUsersAreHandledByPluginEvent::NAME);
$this->addHook(Event::GET_SERVICES_ALLOWED_FOR_RESTRICTED);
Management of Tuleap Restricted users by mediawiki. Covered by story #25738.
$this->addHook('SystemEvent_USER_RENAME', 'systemevent_user_rename');
Rename a user. Covered by story #25738.
$this->addHook(Event::LAYOUT_SEARCH_ENTRY);
$this->addHook(Event::SEARCH_TYPES_PRESENTERS);
$this->addHook(Event::SEARCH_TYPE);
Integrate in Tuleap "Search" button. No longer relevant, covered by Tuleap Skin.
$this->addHook('plugin_statistics_service_usage');
$this->addHook('plugin_statistics_disk_usage_collect_project');
$this->addHook('plugin_statistics_disk_usage_service_label');
$this->addHook('plugin_statistics_color');
Collect statistics for Tuleap Statistics
plugin. Covered by story #25739.
$this->addHook(SiteAdministrationAddOption::NAME);
Add entry at site administration level. Only used for migration to MW 1.23 ATM.
Will be re-used for Mediawiki 1.35 migrations. Covered by story #26041.
$this->addHook(BurningParrotCompatiblePageEvent::NAME);
$this->addHook(Event::BURNING_PARROT_GET_JAVASCRIPT_FILES);
Use Tuleap BurningParrot
theme for site administration page. Nothing to do for this in Mediawiki Standalone.
$this->addHook(Event::PROJECT_ACCESS_CHANGE);
$this->addHook(Event::SITE_ACCESS_CHANGE);
Propagate permissions changes at site or project level. Covered by story #25738.
$this->addHook(Event::IMPORT_XML_PROJECT, 'importXmlProject', false);
$this->addHook(ExportXmlProject::NAME);
Import Mediawiki archive when doing an XML import or export. Covered by story #26040.
$this->addHook(NavigationDropdownQuickLinksCollector::NAME);
Direct access to mediawiki service permissions from project administration "Permissions" dropdown menu. Covered by story #25733.
Tuleap / Plugin / Mediawiki interactions
sequenceDiagram
participant T as Tuleap Core
participant P as Tuleap MW Plugin
participant M as Mediawiki
Note right of M: As of today most operations performed by Tuleap<br>on Mediawiki are done at DB level directly (no API).<br>See plugins/mediawiki/include/MediawikiDao.class.php
T->>+P: Event::SERVICES_ALLOWED_FOR_PROJECT
Note right of P: Mediawiki will have to check for service<br>activation for project
P->>-T: Yes/No
T->>+P: ServiceUrlCollector::NAME
Note right of P: will be covered by Reverse Proxy
P->>-T: routingMethod
T->>+P: Event::GET_PROJECTID_FROM_URL<br>RestrictedUsersAreHandledByPluginEvent::NAME<br>Event::GET_SERVICES_ALLOWED_FOR_RESTRICTED<br>PROJECT_ACCESS_CHANGE<br>Event::SITE_ACCESS_CHANGE
Note right of P: Events to deal with Restricted Users & Private Projects<br>those checks were managed by Tuleap (`pre.php`)<br>How to integrate that in MW ?
P->>-T: integer (project id)
T->>+P: 'permission_get_name'
Note right of P: Mediawiki will have to take those new<br>permissions into account
P->>-T: MEDIAWIKI_READ,MEDIAWIKI_WRITE
T->>P: Event::SERVICE_IS_USED
Note right of P: actions when service is activated in project
P->>+M: Create database & all for project
M->>-P: OK/ERROR
T->>P: RegisterProjectCreationEvent::NAME
Note right of P: actions when project is created with Mediawiki<br>in template
P->>+M: Create database & all for project
M->>-P: OK/ERROR
T->>P: Event::RENAME_PROJECT
Note right of P: actions when Tuleap project is renamed
P->>+M: rename mediawiki site
M->>-P: OK/ERROR
T->>P: 'project_is_deleted'
Note right of P: actions when Tuleap project is deleted
P->>+M: delete site (DB and data)
M->>-P: OK/ERROR
T->>P: 'project_admin_remove_user'<br>'project_admin_change_user_permissions'<br>'project_admin_ugroup_remove_user'<br>'project_admin_remove_user_from_project_ugroups'<br>'project_admin_ugroup_deletion'<br>UserBecomesProjectAdmin::NAME<br>UserIsNoLongerProjectAdmin::NAME<br>UserBecomesWikiAdmin::NAME<br>UserIsNoLongerWikiAdmin::NAME<br>UserBecomesForumAdmin::NAME<br>UserIsNoLongerForumAdmin::NAME<br>UserBecomesNewsWriter::NAME<br>UserIsNoLongerNewsWriter::NAME<br>UserBecomesNewsAdministrator::NAME<br>UserIsNoLongerNewsAdministrator::NAME
Note right of P: a dozen of events raised when a user is added<br>into a group. Should update MW internal groups.
P->>+M: update Tuleap/MW user & groups mapping
M->>-P: OK/ERROR
T->>P: 'SystemEvent_USER_RENAME'
Note right of P: actions when a user is renamed
P->>+M: update MW user table
M->>-P: OK/ERROR
T->>P: 'plugin_statistics_*'
Note right of P: collect statistics about MW usage (data size, etc)
P->>+M: gather data
M->>-P: return data
Resources
Upgrading Math extension will be a PITA. But there might be some hope, see https://phabricator.wikimedia.org/T188745