*/ private static array $altLogin = []; private static array $alreadyRegistered = []; public const supportedApp = 300; public const officialApp = 200; /** * clean the appId * * @psalm-taint-escape file * @psalm-taint-escape include * @psalm-taint-escape html * @psalm-taint-escape has_quotes * * @deprecated 31.0.0 use IAppManager::cleanAppId */ public static function cleanAppId(string $app): string { return str_replace(['<', '>', '"', "'", '\0', '/', '\\', '..'], '', $app); } /** * Check if an app is loaded * * @deprecated 27.0.0 use IAppManager::isAppLoaded */ public static function isAppLoaded(string $app): bool { return Server::get(IAppManager::class)->isAppLoaded($app); } /** * loads all apps * * @param string[] $types * * This function walks through the Nextcloud directory and loads all apps * it can find. A directory contains an app if the file /appinfo/info.xml * exists. * * if $types is set to non-empty array, only apps of those types will be loaded * * @deprecated 29.0.0 use IAppManager::loadApps instead */ public static function loadApps(array $types = []): bool { if (!Server::get(SystemConfig::class)->getValue('installed', false)) { // This should be done before calling this method so that appmanager can be used return false; } return Server::get(IAppManager::class)->loadApps($types); } /** * load a single app * * @throws Exception * @deprecated 27.0.0 use IAppManager::loadApp */ public static function loadApp(string $app): void { Server::get(IAppManager::class)->loadApp($app); } /** * @internal */ public static function registerAutoloading(string $app, string $path, bool $force = false): void { $key = $app . '-' . $path; if (!$force && isset(self::$alreadyRegistered[$key])) { return; } self::$alreadyRegistered[$key] = true; // Register on PSR-4 composer autoloader $appNamespace = Server::get(IAppManager::class)->getAppNamespace($app); \OC::$server->registerNamespace($app, $appNamespace); if (file_exists($path . '/composer/autoload.php')) { require_once $path . '/composer/autoload.php'; } else { \OC::$composerAutoloader->addPsr4($appNamespace . '\\', $path . '/lib/', true); } // Register Test namespace only when testing if (defined('PHPUNIT_RUN') || defined('CLI_TEST_RUN')) { \OC::$composerAutoloader->addPsr4($appNamespace . '\\Tests\\', $path . '/tests/', true); } } /** * Check if an app is of a specific type * * @deprecated 27.0.0 use IAppManager::isType */ public static function isType(string $app, array $types): bool { return Server::get(IAppManager::class)->isType($app, $types); } /** * Returns apps enabled for the current user. * * @param bool $forceRefresh whether to refresh the cache * @param bool $all whether to return apps for all users, not only the * currently logged in one * @return list * @deprecated 32.0.0 - use {@see \OCP\App\IAppManager::getEnabledAppsForUser} or {@see \OC\OCP\AppIAppManager::getEnabledApps} instead */ public static function getEnabledApps(bool $forceRefresh = false, bool $all = false): array { if (!Server::get(SystemConfig::class)->getValue('installed', false)) { return []; } // in incognito mode or when logged out, $user will be false, // which is also the case during an upgrade $appManager = Server::get(IAppManager::class); if ($all) { $user = null; } else { $user = Server::get(IUserSession::class)->getUser(); } if (is_null($user)) { $apps = $appManager->getEnabledApps(); } else { $apps = $appManager->getEnabledAppsForUser($user); } $apps = array_filter($apps, function ($app) { return $app !== 'files';//we add this manually }); sort($apps); array_unshift($apps, 'files'); return $apps; } /** * enables an app * * @param array $groups (optional) when set, only these groups will have access to the app * @throws \Exception * @deprecated 32.0.0 Use the installer and the app manager instead * * This function set an app as enabled in appconfig. */ public function enable(string $appId, array $groups = []): void { // Check if app is already downloaded /** @var Installer $installer */ $installer = Server::get(Installer::class); $isDownloaded = $installer->isDownloaded($appId); if (!$isDownloaded) { $installer->downloadApp($appId); } $installer->installApp($appId); $appManager = Server::get(IAppManager::class); if ($groups !== []) { $groupManager = Server::get(IGroupManager::class); $groupsList = []; foreach ($groups as $group) { $groupItem = $groupManager->get($group); if ($groupItem instanceof IGroup) { $groupsList[] = $groupManager->get($group); } } $appManager->enableAppForGroups($appId, $groupsList); } else { $appManager->enableApp($appId); } } /** * Find the apps root for an app id. * * If multiple copies are found, the apps root the latest version is returned. * * @param bool $ignoreCache ignore cache and rebuild it * @return false|array{path: string, url: string} the apps root shape * @deprecated 32.0.0 internal, use getAppPath or getAppWebPath */ public static function findAppInDirectories(string $appId, bool $ignoreCache = false) { return Server::get(AppManager::class)->findAppInDirectories($appId, $ignoreCache); } /** * get app's version based on it's path * * @deprecated 32.0.0 use Server::get(IAppManager)->getAppInfoByPath() with the path to info.xml directly */ public static function getAppVersionByPath(string $path): string { $infoFile = $path . '/appinfo/info.xml'; $appData = Server::get(IAppManager::class)->getAppInfoByPath($infoFile); return $appData['version'] ?? ''; } /** * get the id of loaded app * @deprecated 34.0.0 Don’t do that */ public static function getCurrentApp(): string { if (\OC::$CLI) { return ''; } $request = Server::get(IRequest::class); $script = substr($request->getScriptName(), strlen(OC::$WEBROOT) + 1); $topFolder = substr($script, 0, strpos($script, '/') ?: 0); if (empty($topFolder)) { try { $path_info = $request->getPathInfo(); } catch (Exception $e) { // Can happen from unit tests because the script name is `./vendor/bin/phpunit` or something a like then. Server::get(LoggerInterface::class)->error('Failed to detect current app from script path', ['exception' => $e]); return ''; } if ($path_info) { $topFolder = substr($path_info, 1, strpos($path_info, '/', 1) - 1); } } if ($topFolder == 'apps') { $length = strlen($topFolder); return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1) ?: ''; } else { return $topFolder; } } /** * @deprecated 20.0.0 Please register your alternative login option using the registerAlternativeLogin() on the RegistrationContext in your Application class implementing the OCP\Authentication\IAlternativeLogin interface */ public static function registerLogIn(array $entry): void { Server::get(LoggerInterface::class)->debug('OC_App::registerLogIn() is deprecated, please register your alternative login option using the registerAlternativeLogin() on the RegistrationContext in your Application class implementing the OCP\Authentication\IAlternativeLogin interface'); self::$altLogin[] = $entry; } /** * @return list */ public static function getAlternativeLogIns(): array { /** @var Coordinator $bootstrapCoordinator */ $bootstrapCoordinator = Server::get(Coordinator::class); foreach ($bootstrapCoordinator->getRegistrationContext()->getAlternativeLoginProviders() as $registration) { if (!in_array(IAlternativeLoginProvider::class, class_implements($registration->getService()), true)) { Server::get(LoggerInterface::class)->error('Alternative login option {option} does not implement {interface} and is therefore ignored.', [ 'option' => $registration->getService(), 'interface' => IAlternativeLoginProvider::class, 'app' => $registration->getAppId(), ]); continue; } try { /** @var IAlternativeLoginProvider $provider */ $provider = Server::get($registration->getService()); } catch (ContainerExceptionInterface $e) { Server::get(LoggerInterface::class)->error('Alternative login option {option} can not be initialized.', [ 'exception' => $e, 'option' => $registration->getService(), 'app' => $registration->getAppId(), ]); continue; } foreach ($provider->getAlternativeLogins() as $alternativeLogin) { try { $alternativeLogin->load(); self::$altLogin[] = [ 'name' => $alternativeLogin->getLabel(), 'href' => $alternativeLogin->getLink(), 'class' => $alternativeLogin->getClass(), ]; } catch (Throwable $e) { Server::get(LoggerInterface::class)->error('Alternative login option {option} had an error while loading.', [ 'exception' => $e, 'option' => $registration->getService(), 'app' => $registration->getAppId(), ]); } } } foreach ($bootstrapCoordinator->getRegistrationContext()->getAlternativeLogins() as $registration) { if (!in_array(IAlternativeLogin::class, class_implements($registration->getService()), true)) { Server::get(LoggerInterface::class)->error('Alternative login option {option} does not implement {interface} and is therefore ignored.', [ 'option' => $registration->getService(), 'interface' => IAlternativeLogin::class, 'app' => $registration->getAppId(), ]); continue; } try { /** @var IAlternativeLogin $provider */ $provider = Server::get($registration->getService()); } catch (ContainerExceptionInterface $e) { Server::get(LoggerInterface::class)->error('Alternative login option {option} can not be initialized.', [ 'exception' => $e, 'option' => $registration->getService(), 'app' => $registration->getAppId(), ]); } try { $provider->load(); self::$altLogin[] = [ 'name' => $provider->getLabel(), 'href' => $provider->getLink(), 'class' => $provider->getClass(), ]; } catch (Throwable $e) { Server::get(LoggerInterface::class)->error('Alternative login option {option} had an error while loading.', [ 'exception' => $e, 'option' => $registration->getService(), 'app' => $registration->getAppId(), ]); } } return self::$altLogin; } /** * get a list of all apps in the apps folder * * @return string[] an array of app names (string IDs) * @deprecated 31.0.0 Use IAppManager::getAllAppsInAppsFolders instead */ public static function getAllApps(): array { return Server::get(IAppManager::class)->getAllAppsInAppsFolders(); } /** * List all supported apps * * @deprecated 32.0.0 Use \OCP\Support\Subscription\IRegistry::delegateGetSupportedApps instead */ public function getSupportedApps(): array { $subscriptionRegistry = Server::get(IRegistry::class); $supportedApps = $subscriptionRegistry->delegateGetSupportedApps(); return $supportedApps; } /** * List all apps, this is used in apps.php */ public function listAllApps(): array { $appManager = Server::get(IAppManager::class); $installedApps = $appManager->getAllAppsInAppsFolders(); //we don't want to show configuration for these $blacklist = $appManager->getAlwaysEnabledApps(); $appList = []; $langCode = \OC::$server->getL10N('core')->getLanguageCode(); $urlGenerator = Server::get(IURLGenerator::class); $supportedApps = $this->getSupportedApps(); foreach ($installedApps as $app) { if (!in_array($app, $blacklist)) { $info = $appManager->getAppInfo($app, false, $langCode); if (!is_array($info)) { Server::get(LoggerInterface::class)->error('Could not read app info file for app "' . $app . '"', ['app' => 'core']); continue; } if (!isset($info['name'])) { Server::get(LoggerInterface::class)->error('App id "' . $app . '" has no name in appinfo', ['app' => 'core']); continue; } $enabled = Server::get(IConfig::class)->getAppValue($app, 'enabled', 'no'); $info['groups'] = null; if ($enabled === 'yes') { $active = true; } elseif ($enabled === 'no') { $active = false; } else { $active = true; $info['groups'] = $enabled; } $info['active'] = $active; if ($appManager->isShipped($app)) { $info['internal'] = true; $info['level'] = self::officialApp; $info['removable'] = false; } else { $info['internal'] = false; $info['removable'] = true; } if (in_array($app, $supportedApps)) { $info['level'] = self::supportedApp; } try { $appPath = $appManager->getAppPath($app); } catch (AppPathNotFoundException) { $appPath = false; } if ($appPath !== false) { $appIcon = $appPath . '/img/' . $app . '.svg'; if (file_exists($appIcon)) { $info['icon'] = $urlGenerator->imagePath($app, $app . '.svg'); } else { $appIcon = $appPath . '/img/app.svg'; if (file_exists($appIcon)) { $info['icon'] = $urlGenerator->imagePath($app, 'app.svg'); } } } // fix documentation if (isset($info['documentation']) && is_array($info['documentation'])) { foreach ($info['documentation'] as $key => $url) { // If it is not an absolute URL we assume it is a key // i.e. admin-ldap will get converted to go.php?to=admin-ldap if (stripos($url, 'https://') !== 0 && stripos($url, 'http://') !== 0) { $url = $urlGenerator->linkToDocs($url); } $info['documentation'][$key] = $url; } } $info['license'] = $info['licence']; $info['version'] = $appManager->getAppVersion($app); $appList[] = $info; } } return $appList; } /** * @deprecated 32.0.0 Use IAppManager::isUpgradeRequired instead */ public static function shouldUpgrade(string $app): bool { return Server::get(IAppManager::class)->isUpgradeRequired($app); } /** * Check whether the current Nextcloud version matches the given * application's version requirements. * * The comparison is made based on the number of parts that the * app info version has. For example for ownCloud 6.0.3 if the * app info version is expecting version 6.0, the comparison is * made on the first two parts of the ownCloud version. * This means that it's possible to specify "requiremin" => 6 * and "requiremax" => 6 and it will still match ownCloud 6.0.3. * * @param string $ocVersion Nextcloud version to check against * @param array $appInfo app info (from xml) * * @return bool true if compatible, otherwise false * @deprecated 32.0.0 Use IAppManager::isAppCompatible instead */ public static function isAppCompatible(string $ocVersion, array $appInfo, bool $ignoreMax = false): bool { return Server::get(IAppManager::class)->isAppCompatible($ocVersion, $appInfo, $ignoreMax); } /** * get the installed version of all apps * @deprecated 32.0.0 Use IAppManager::getAppInstalledVersions or IAppConfig::getAppInstalledVersions instead */ public static function getAppVersions(): array { return Server::get(IAppConfig::class)->getAppInstalledVersions(); } /** * update the database for the app and call the update script * * @deprecated 32.0.0 Use IAppManager::upgradeApp instead */ public static function updateApp(string $appId): bool { try { return Server::get(AppManager::class)->upgradeApp($appId); } catch (AppPathNotFoundException $e) { return false; } } /** * @param string $appId * @param string[] $steps * @throws NeedsUpdateException * @deprecated 34.0.0 Use {@see \OC\App\AppManager::executeRepairSteps} */ public static function executeRepairSteps(string $appId, array $steps) { Server::get(AppManager::class)->executeRepairSteps($appId, $steps); } /** * @deprecated 32.0.0 Use the IJobList directly instead */ public static function setupBackgroundJobs(array $jobs): void { $queue = Server::get(IJobList::class); foreach ($jobs as $job) { $queue->add($job); } } /** * @throws \Exception * @deprecated 34.0.0 Use {@see \OC\App\AppManager::checkAppDependencies} instead */ public static function checkAppDependencies(IConfig $config, IL10N $l, array $info, bool $ignoreMax): void { Server::get(AppManager::class)->checkAppDependencies($info['id'], $ignoreMax); } }