aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/private/App/AppManager.php139
-rw-r--r--lib/private/legacy/OC_App.php134
-rw-r--r--lib/public/App/IAppManager.php14
3 files changed, 158 insertions, 129 deletions
diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php
index 0a89711f178..0b0bcecb5dc 100644
--- a/lib/private/App/AppManager.php
+++ b/lib/private/App/AppManager.php
@@ -39,6 +39,8 @@
namespace OC\App;
use OC\AppConfig;
+use OC\AppFramework\Bootstrap\Coordinator;
+use OC\ServerNotAvailableException;
use OCP\App\AppPathNotFoundException;
use OCP\App\Events\AppDisableEvent;
use OCP\App\Events\AppEnableEvent;
@@ -51,6 +53,7 @@ use OCP\IGroup;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserSession;
+use OCP\Settings\IManager as ISettingsManager;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -108,6 +111,9 @@ class AppManager implements IAppManager {
/** @var array */
private $autoDisabledApps = [];
+ /** @var array<string, true> */
+ private array $loadedApps = [];
+
public function __construct(IUserSession $userSession,
IConfig $config,
AppConfig $appConfig,
@@ -310,6 +316,139 @@ class AppManager implements IAppManager {
}
}
+ public function loadApp(string $app): void {
+ if (isset($this->loadedApps[$app])) {
+ return;
+ }
+ $this->loadedApps[$app] = true;
+ $appPath = \OC_App::getAppPath($app);
+ if ($appPath === false) {
+ return;
+ }
+ $eventLogger = \OC::$server->get(\OCP\Diagnostics\IEventLogger::class);
+ $eventLogger->start("bootstrap:load_app:$app", "Load $app");
+
+ // in case someone calls loadApp() directly
+ \OC_App::registerAutoloading($app, $appPath);
+
+ /** @var Coordinator $coordinator */
+ $coordinator = \OC::$server->get(Coordinator::class);
+ $isBootable = $coordinator->isBootable($app);
+
+ $hasAppPhpFile = is_file($appPath . '/appinfo/app.php');
+
+ if ($isBootable && $hasAppPhpFile) {
+ \OC::$server->getLogger()->error('/appinfo/app.php is not loaded when \OCP\AppFramework\Bootstrap\IBootstrap on the application class is used. Migrate everything from app.php to the Application class.', [
+ 'app' => $app,
+ ]);
+ } elseif ($hasAppPhpFile) {
+ $eventLogger->start("bootstrap:load_app:$app:app.php", "Load legacy app.php app $app");
+ \OC::$server->getLogger()->debug('/appinfo/app.php is deprecated, use \OCP\AppFramework\Bootstrap\IBootstrap on the application class instead.', [
+ 'app' => $app,
+ ]);
+ try {
+ self::requireAppFile($appPath);
+ } catch (\Throwable $ex) {
+ if ($ex instanceof ServerNotAvailableException) {
+ throw $ex;
+ }
+ if (!\OC::$server->getAppManager()->isShipped($app) && !self::isType($app, ['authentication'])) {
+ \OC::$server->getLogger()->logException($ex, [
+ 'message' => "App $app threw an error during app.php load and will be disabled: " . $ex->getMessage(),
+ ]);
+
+ // Only disable apps which are not shipped and that are not authentication apps
+ \OC::$server->getAppManager()->disableApp($app, true);
+ } else {
+ \OC::$server->getLogger()->logException($ex, [
+ 'message' => "App $app threw an error during app.php load: " . $ex->getMessage(),
+ ]);
+ }
+ }
+ $eventLogger->end("bootstrap:load_app:$app:app.php");
+ }
+
+ $coordinator->bootApp($app);
+
+ $eventLogger->start("bootstrap:load_app:$app:info", "Load info.xml for $app and register any services defined in it");
+ $info = self::getAppInfo($app);
+ if (!empty($info['activity']['filters'])) {
+ foreach ($info['activity']['filters'] as $filter) {
+ \OC::$server->getActivityManager()->registerFilter($filter);
+ }
+ }
+ if (!empty($info['activity']['settings'])) {
+ foreach ($info['activity']['settings'] as $setting) {
+ \OC::$server->getActivityManager()->registerSetting($setting);
+ }
+ }
+ if (!empty($info['activity']['providers'])) {
+ foreach ($info['activity']['providers'] as $provider) {
+ \OC::$server->getActivityManager()->registerProvider($provider);
+ }
+ }
+
+ if (!empty($info['settings']['admin'])) {
+ foreach ($info['settings']['admin'] as $setting) {
+ \OC::$server->get(ISettingsManager::class)->registerSetting('admin', $setting);
+ }
+ }
+ if (!empty($info['settings']['admin-section'])) {
+ foreach ($info['settings']['admin-section'] as $section) {
+ \OC::$server->get(ISettingsManager::class)->registerSection('admin', $section);
+ }
+ }
+ if (!empty($info['settings']['personal'])) {
+ foreach ($info['settings']['personal'] as $setting) {
+ \OC::$server->get(ISettingsManager::class)->registerSetting('personal', $setting);
+ }
+ }
+ if (!empty($info['settings']['personal-section'])) {
+ foreach ($info['settings']['personal-section'] as $section) {
+ \OC::$server->get(ISettingsManager::class)->registerSection('personal', $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'];
+ foreach ($plugins as $plugin) {
+ if ($plugin['@attributes']['type'] === 'collaborator-search') {
+ $pluginInfo = [
+ 'shareType' => $plugin['@attributes']['share-type'],
+ 'class' => $plugin['@value'],
+ ];
+ \OC::$server->getCollaboratorSearch()->registerPlugin($pluginInfo);
+ } elseif ($plugin['@attributes']['type'] === 'autocomplete-sort') {
+ \OC::$server->getAutoCompleteManager()->registerSorter($plugin['@value']);
+ }
+ }
+ }
+ $eventLogger->end("bootstrap:load_app:$app:info");
+
+ $eventLogger->end("bootstrap:load_app:$app");
+ }
+ /**
+ * Check if an app is loaded
+ * @param string $app app id
+ * @since 26.0.0
+ */
+ public function isAppLoaded(string $app): bool {
+ return isset($this->loadedApps[$app]);
+ }
+
+ /**
+ * Load app.php from the given app
+ *
+ * @param string $app app name
+ * @throws \Error
+ */
+ private static function requireAppFile(string $app): void {
+ // encapsulated here to avoid variable scope conflicts
+ require_once $app . '/appinfo/app.php';
+ }
+
/**
* Enable an app for every user
*
diff --git a/lib/private/legacy/OC_App.php b/lib/private/legacy/OC_App.php
index 3c255e91661..01bce057881 100644
--- a/lib/private/legacy/OC_App.php
+++ b/lib/private/legacy/OC_App.php
@@ -53,11 +53,11 @@ declare(strict_types=1);
use OCP\App\Events\AppUpdateEvent;
use OCP\AppFramework\QueryException;
+use OCP\App\IAppManager;
use OCP\App\ManagerEvent;
use OCP\Authentication\IAlternativeLogin;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\ILogger;
-use OCP\Settings\IManager as ISettingsManager;
use OC\AppFramework\Bootstrap\Coordinator;
use OC\App\DependencyAnalyzer;
use OC\App\Platform;
@@ -65,7 +65,6 @@ use OC\DB\MigrationService;
use OC\Installer;
use OC\Repair;
use OC\Repair\Events\RepairErrorEvent;
-use OC\ServerNotAvailableException;
use Psr\Log\LoggerInterface;
/**
@@ -77,7 +76,6 @@ class OC_App {
private static $adminForms = [];
private static $personalForms = [];
private static $appTypes = [];
- private static $loadedApps = [];
private static $altLogin = [];
private static $alreadyRegistered = [];
public const supportedApp = 300;
@@ -103,7 +101,7 @@ class OC_App {
* @return bool
*/
public static function isAppLoaded(string $app): bool {
- return isset(self::$loadedApps[$app]);
+ return \OC::$server->get(IAppManager::class)->isAppLoaded($app);
}
/**
@@ -128,7 +126,7 @@ class OC_App {
// Add each apps' folder as allowed class path
foreach ($apps as $app) {
// If the app is already loaded then autoloading it makes no sense
- if (!isset(self::$loadedApps[$app])) {
+ if (!self::isAppLoaded($app)) {
$path = self::getAppPath($app);
if ($path !== false) {
self::registerAutoloading($app, $path);
@@ -139,7 +137,7 @@ class OC_App {
// prevent app.php from printing output
ob_start();
foreach ($apps as $app) {
- if (!isset(self::$loadedApps[$app]) && ($types === [] || self::isType($app, $types))) {
+ if (!self::isAppLoaded($app) && ($types === [] || self::isType($app, $types))) {
try {
self::loadApp($app);
} catch (\Throwable $e) {
@@ -162,118 +160,7 @@ class OC_App {
* @throws Exception
*/
public static function loadApp(string $app): void {
- if (isset(self::$loadedApps[$app])) {
- return;
- }
- self::$loadedApps[$app] = true;
- $appPath = self::getAppPath($app);
- if ($appPath === false) {
- return;
- }
- $eventLogger = \OC::$server->get(\OCP\Diagnostics\IEventLogger::class);
- $eventLogger->start("bootstrap:load_app:$app", "Load $app");
-
- // in case someone calls loadApp() directly
- self::registerAutoloading($app, $appPath);
-
- /** @var Coordinator $coordinator */
- $coordinator = \OC::$server->query(Coordinator::class);
- $isBootable = $coordinator->isBootable($app);
-
- $hasAppPhpFile = is_file($appPath . '/appinfo/app.php');
-
- if ($isBootable && $hasAppPhpFile) {
- \OC::$server->getLogger()->error('/appinfo/app.php is not loaded when \OCP\AppFramework\Bootstrap\IBootstrap on the application class is used. Migrate everything from app.php to the Application class.', [
- 'app' => $app,
- ]);
- } elseif ($hasAppPhpFile) {
- $eventLogger->start("bootstrap:load_app:$app:app.php", "Load legacy app.php app $app");
- \OC::$server->getLogger()->debug('/appinfo/app.php is deprecated, use \OCP\AppFramework\Bootstrap\IBootstrap on the application class instead.', [
- 'app' => $app,
- ]);
- try {
- self::requireAppFile($appPath);
- } catch (Throwable $ex) {
- if ($ex instanceof ServerNotAvailableException) {
- throw $ex;
- }
- if (!\OC::$server->getAppManager()->isShipped($app) && !self::isType($app, ['authentication'])) {
- \OC::$server->getLogger()->logException($ex, [
- 'message' => "App $app threw an error during app.php load and will be disabled: " . $ex->getMessage(),
- ]);
-
- // Only disable apps which are not shipped and that are not authentication apps
- \OC::$server->getAppManager()->disableApp($app, true);
- } else {
- \OC::$server->getLogger()->logException($ex, [
- 'message' => "App $app threw an error during app.php load: " . $ex->getMessage(),
- ]);
- }
- }
- $eventLogger->end("bootstrap:load_app:$app:app.php");
- }
-
- $coordinator->bootApp($app);
-
- $eventLogger->start("bootstrap:load_app:$app:info", "Load info.xml for $app and register any services defined in it");
- $info = self::getAppInfo($app);
- if (!empty($info['activity']['filters'])) {
- foreach ($info['activity']['filters'] as $filter) {
- \OC::$server->getActivityManager()->registerFilter($filter);
- }
- }
- if (!empty($info['activity']['settings'])) {
- foreach ($info['activity']['settings'] as $setting) {
- \OC::$server->getActivityManager()->registerSetting($setting);
- }
- }
- if (!empty($info['activity']['providers'])) {
- foreach ($info['activity']['providers'] as $provider) {
- \OC::$server->getActivityManager()->registerProvider($provider);
- }
- }
-
- if (!empty($info['settings']['admin'])) {
- foreach ($info['settings']['admin'] as $setting) {
- \OC::$server->get(ISettingsManager::class)->registerSetting('admin', $setting);
- }
- }
- if (!empty($info['settings']['admin-section'])) {
- foreach ($info['settings']['admin-section'] as $section) {
- \OC::$server->get(ISettingsManager::class)->registerSection('admin', $section);
- }
- }
- if (!empty($info['settings']['personal'])) {
- foreach ($info['settings']['personal'] as $setting) {
- \OC::$server->get(ISettingsManager::class)->registerSetting('personal', $setting);
- }
- }
- if (!empty($info['settings']['personal-section'])) {
- foreach ($info['settings']['personal-section'] as $section) {
- \OC::$server->get(ISettingsManager::class)->registerSection('personal', $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'];
- foreach ($plugins as $plugin) {
- if ($plugin['@attributes']['type'] === 'collaborator-search') {
- $pluginInfo = [
- 'shareType' => $plugin['@attributes']['share-type'],
- 'class' => $plugin['@value'],
- ];
- \OC::$server->getCollaboratorSearch()->registerPlugin($pluginInfo);
- } elseif ($plugin['@attributes']['type'] === 'autocomplete-sort') {
- \OC::$server->getAutoCompleteManager()->registerSorter($plugin['@value']);
- }
- }
- }
-
- $eventLogger->end("bootstrap:load_app:$app:info");
-
- $eventLogger->end("bootstrap:load_app:$app");
+ \OC::$server->get(IAppManager::class)->loadApp($app);
}
/**
@@ -307,17 +194,6 @@ class OC_App {
}
/**
- * Load app.php from the given app
- *
- * @param string $app app name
- * @throws Error
- */
- private static function requireAppFile(string $app) {
- // encapsulated here to avoid variable scope conflicts
- require_once $app . '/appinfo/app.php';
- }
-
- /**
* check if an app is of a specific type
*
* @param string $app
diff --git a/lib/public/App/IAppManager.php b/lib/public/App/IAppManager.php
index de36fafcdfe..51bd5845b7c 100644
--- a/lib/public/App/IAppManager.php
+++ b/lib/public/App/IAppManager.php
@@ -94,6 +94,20 @@ interface IAppManager {
public function isDefaultEnabled(string $appId):bool;
/**
+ * Load an app, if not already loaded
+ * @param string $app app id
+ * @since 26.0.0
+ */
+ public function loadApp(string $app): void;
+
+ /**
+ * Check if an app is loaded
+ * @param string $app app id
+ * @since 26.0.0
+ */
+ public function isAppLoaded(string $app): bool;
+
+ /**
* Enable an app for every user
*
* @param string $appId