Skip to content

Deprecate and remove info.xml-based activity, settings, and collaboration registrations from loadApp() #59678

@joshtrichards

Description

@joshtrichards

Summary

AppManager::loadApp() calls getAppInfo() for every loaded app on every request to check for <activity>, <settings>, and <collaboration> entries in info.xml, then routes those registrations to the respective managers. These registrations are just lazy class-name-string registrations -- identical to what apps can already do directly via IActivityManager, ISettingsManager, ICollaboratorSearch, and IAutoCompleteManager in their Application::register() or Application::boot() methods.

There is nothing unique -- from what I can see -- about these registration types compared to others (event listeners, capabilities, search providers, notifiers, etc.) that are already exclusively registered through IBootstrap::register(). The info.xml path is legacy from before the IBootstrap/IRegistrationContext system (NC 20).

$eventLogger->start("bootstrap:load_app:$app:info", "Load info.xml for $app and register any services defined in it");
$info = $this->getAppInfo($app);
if (!empty($info['activity'])) {
$activityManager = Server::get(IActivityManager::class);
if (!empty($info['activity']['filters'])) {
foreach ($info['activity']['filters'] as $filter) {
$activityManager->registerFilter($filter);
}
}
if (!empty($info['activity']['settings'])) {
foreach ($info['activity']['settings'] as $setting) {
$activityManager->registerSetting($setting);
}
}
if (!empty($info['activity']['providers'])) {
foreach ($info['activity']['providers'] as $provider) {
$activityManager->registerProvider($provider);
}
}
}
if (!empty($info['settings'])) {
$settingsManager = Server::get(ISettingsManager::class);
if (!empty($info['settings']['admin'])) {
foreach ($info['settings']['admin'] as $setting) {
$settingsManager->registerSetting('admin', $setting);
}
}
if (!empty($info['settings']['admin-section'])) {
foreach ($info['settings']['admin-section'] as $section) {
$settingsManager->registerSection('admin', $section);
}
}
if (!empty($info['settings']['personal'])) {
foreach ($info['settings']['personal'] as $setting) {
$settingsManager->registerSetting('personal', $setting);
}
}
if (!empty($info['settings']['personal-section'])) {
foreach ($info['settings']['personal-section'] as $section) {
$settingsManager->registerSection('personal', $section);
}
}
if (!empty($info['settings']['admin-delegation'])) {
foreach ($info['settings']['admin-delegation'] as $setting) {
$settingsManager->registerSetting(ISettingsManager::SETTINGS_DELEGATION, $setting);
}
}
if (!empty($info['settings']['admin-delegation-section'])) {
foreach ($info['settings']['admin-delegation-section'] as $section) {
$settingsManager->registerSection(ISettingsManager::SETTINGS_DELEGATION, $section);
}
}
}
if (!empty($info['collaboration']['plugins'])) {
// deal with one or many plugin entries
$plugins = isset($info['collaboration']['plugins']['plugin']['@value'])
? [$info['collaboration']['plugins']['plugin']] : $info['collaboration']['plugins']['plugin'];
$collaboratorSearch = null;
$autoCompleteManager = null;
foreach ($plugins as $plugin) {
if ($plugin['@attributes']['type'] === 'collaborator-search') {
$pluginInfo = [
'shareType' => $plugin['@attributes']['share-type'],
'class' => $plugin['@value'],
];
$collaboratorSearch ??= Server::get(ICollaboratorSearch::class);
$collaboratorSearch->registerPlugin($pluginInfo);
} elseif ($plugin['@attributes']['type'] === 'autocomplete-sort') {
$autoCompleteManager ??= Server::get(IAutoCompleteManager::class);
$autoCompleteManager->registerSorter($plugin['@value']);
}
}
}
$eventLogger->end("bootstrap:load_app:$app:info");

Benefits

  • Code quality / consistency: One registration mechanism instead of two parallel paths. All registrations become PHP-based, IDE-navigable, and type-checked.
  • Marginal overhead reduction (with APCu, ~30 apps): Eliminates ~30× filemtime() stat calls + json_decode() of full app info arrays per request, just to check a few keys that are mostly empty. Negligible in practice, but streamlining is always nice.
  • Modest performance improvement (without APCu, ~30 apps): Without a local cache backend, every request does full XML parsing (file_get_contents + simplexml_load_string + array normalization) for every loaded app. Not an ideal deployment configuration, but not uncommon (e.g., shared hosting).

Proposed plan

  1. Deprecate the <activity>, <settings>, and <collaboration> registration blocks in info.xml
  2. Migrate shipped apps to register via the existing manager APIs in Application::register() or Application::boot()
  3. Communicate the deprecation to third-party app developers
  4. Remove the getAppInfo() call and associated registration logic from loadApp()
  5. Verify no other code in the loadApp() path depends on getAppInfo() being called as a side effect

Metadata

Metadata

Assignees

No one assigned
    No fields configured for Enhancement.

    Projects

    Status

    Triaged

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions