@@ -83,6 +83,8 @@ class AppManager implements IAppManager {
8383
8484 /** @var array<string, true> */
8585 private array $ loadedApps = [];
86+ /** @var array<string, true> */
87+ private array $ registeredApps = [];
8688
8789 /** @var string[] */
8890 private $ namespaceCache = [];
@@ -267,22 +269,12 @@ public function loadApps(array $types = []): bool {
267269
268270 // Load the enabled apps here
269271 $ apps = $ this ->getEnabledApps ();
270-
271- // Add each apps' folder as allowed class path
272- foreach ($ apps as $ app ) {
272+ $ appsToRegister = array_filter (
273+ $ apps ,
273274 // If the app is already loaded then autoloading it makes no sense
274- if (!$ this ->isAppLoaded ($ app ) && ($ types === [] || $ this ->isType ($ app , $ types ))) {
275- try {
276- $ path = $ this ->getAppPath ($ app );
277- \OC_App::registerAutoloading ($ app , $ path );
278- } catch (AppPathNotFoundException $ e ) {
279- $ this ->logger ->info ('Error during app loading: ' . $ e ->getMessage (), [
280- 'exception ' => $ e ,
281- 'app ' => $ app ,
282- ]);
283- }
284- }
285- }
275+ fn (string $ app ) => (!$ this ->isAppLoaded ($ app ) && ($ types === [] || $ this ->isType ($ app , $ types ))),
276+ );
277+ $ this ->registerAppsAutoloading ($ appsToRegister );
286278
287279 // prevent app loading from printing output
288280 ob_start ();
@@ -487,7 +479,7 @@ public function loadApp(string $app): void {
487479 $ eventLogger ->start ("bootstrap:load_app: $ app " , "Load app: $ app " );
488480
489481 // in case someone calls loadApp() directly
490- \OC_App:: registerAutoloading ( $ app, $ appPath );
482+ $ this -> registerAppsAutoloading ([ $ app] );
491483
492484 if (is_file ($ appPath . '/appinfo/app.php ' )) {
493485 $ this ->logger ->error ('/appinfo/app.php is not supported anymore, use \OCP\AppFramework\Bootstrap\IBootstrap on the application class instead. ' , [
@@ -578,6 +570,52 @@ public function loadApp(string $app): void {
578570 $ eventLogger ->end ("bootstrap:load_app: $ app " );
579571 }
580572
573+ /**
574+ * @internal
575+ */
576+ public function registerAppsAutoloading (array $ apps ): void {
577+ foreach ($ apps as $ app ) {
578+ if (!isset ($ this ->registeredApps [$ app ])) {
579+ try {
580+ $ path = $ this ->getAppPath ($ app );
581+ $ this ->registerAutoloading ($ app , $ path );
582+ } catch (AppPathNotFoundException $ e ) {
583+ $ this ->logger ->info ('Error during app loading: ' . $ e ->getMessage (), [
584+ 'exception ' => $ e ,
585+ 'app ' => $ app ,
586+ ]);
587+ }
588+ }
589+ }
590+ }
591+
592+ /**
593+ * @internal
594+ */
595+ public function registerAutoloading (string $ app , string $ path , bool $ force = false ): void {
596+ if (!$ force && isset ($ this ->registeredApps [$ app ])) {
597+ return ;
598+ }
599+
600+ $ this ->registeredApps [$ app ] = true ;
601+
602+ // Register on PSR-4 composer autoloader
603+ $ appNamespace = $ this ->getAppNamespace ($ app );
604+ \OC ::$ server ->registerNamespace ($ app , $ appNamespace );
605+
606+ if (file_exists ($ path . '/composer/autoload.php ' )) {
607+ require_once $ path . '/composer/autoload.php ' ;
608+ } elseif (is_dir ($ path . '/lib ' )) {
609+ // autoloader crashes on non-existing dir
610+ \OC ::$ composerAutoloader ->addPsr4 ($ appNamespace . '\\' , $ path . '/lib/ ' , true );
611+ }
612+
613+ // Register Test namespace only when testing
614+ if (defined ('PHPUNIT_RUN ' ) || defined ('CLI_TEST_RUN ' )) {
615+ \OC ::$ composerAutoloader ->addPsr4 ($ appNamespace . '\\Tests \\' , $ path . '/tests/ ' , true );
616+ }
617+ }
618+
581619 /**
582620 * Check if an app is loaded
583621 * @param string $app app id
@@ -1107,7 +1145,7 @@ public function upgradeApp(string $appId): bool {
11071145 $ ignoreMax = in_array ($ appId , $ ignoreMaxApps , true );
11081146 $ this ->checkAppDependencies ($ appId , $ ignoreMax );
11091147
1110- \OC_App:: registerAutoloading ($ appId , $ appPath , true );
1148+ $ this -> registerAutoloading ($ appId , $ appPath , true );
11111149 $ this ->executeRepairSteps ($ appId , $ appInfo ['repair-steps ' ]['pre-migration ' ]);
11121150
11131151 $ ms = new MigrationService ($ appId , Server::get (\OC \DB \Connection::class));
0 commit comments