2011-03-03 15:55:32 -05:00
< ? php
2019-12-03 13:57:53 -05:00
2018-02-17 09:37:57 -05:00
declare ( strict_types = 1 );
2011-03-11 09:25:48 -05:00
/**
2024-05-23 03:26:56 -04:00
* SPDX - FileCopyrightText : 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX - FileCopyrightText : 2016 ownCloud , Inc .
* SPDX - License - Identifier : AGPL - 3.0 - only
2011-03-11 09:25:48 -05:00
*/
2025-07-29 11:47:40 -04:00
use OC\App\AppManager ;
2014-12-11 11:02:07 -05:00
use OC\App\DependencyAnalyzer ;
2022-08-22 11:59:26 -04:00
use OC\AppFramework\Bootstrap\Coordinator ;
2016-04-28 09:15:34 -04:00
use OC\Installer ;
2016-04-19 09:36:11 -04:00
use OC\Repair ;
2022-08-22 11:59:26 -04:00
use OC\Repair\Events\RepairErrorEvent ;
2023-02-07 10:56:04 -05:00
use OCP\App\IAppManager ;
2022-08-22 11:59:26 -04:00
use OCP\Authentication\IAlternativeLogin ;
2022-12-08 04:55:19 -05:00
use OCP\EventDispatcher\IEventDispatcher ;
2024-01-11 11:32:58 -05:00
use OCP\IAppConfig ;
2024-06-18 05:55:08 -04:00
use OCP\Server ;
2023-06-06 05:09:24 -04:00
use Psr\Container\ContainerExceptionInterface ;
2021-02-01 08:56:56 -05:00
use Psr\Log\LoggerInterface ;
2024-06-18 05:55:08 -04:00
use function OCP\Log\logger ;
2011-03-11 09:25:48 -05:00
2011-03-12 04:28:10 -05:00
/**
* This class manages the apps . It allows them to register and integrate in the
2024-09-17 08:41:25 -04:00
* Nextcloud ecosystem . Furthermore , this class is responsible for installing ,
2011-03-12 04:28:10 -05:00
* upgrading and removing apps .
*/
2014-04-17 09:30:27 -04:00
class OC_App {
2020-04-10 10:48:31 -04:00
private static $altLogin = [];
private static $alreadyRegistered = [];
2020-04-10 10:54:27 -04:00
public const supportedApp = 300 ;
public const officialApp = 200 ;
2011-03-03 15:55:32 -05:00
2013-02-09 09:03:47 -05:00
/**
2014-07-09 04:20:17 -04:00
* clean the appId
2015-02-02 08:47:38 -05:00
*
2020-11-20 06:19:59 -05:00
* @ psalm - taint - escape file
2020-11-20 19:57:25 -05:00
* @ psalm - taint - escape include
2022-08-31 15:15:02 -04:00
* @ psalm - taint - escape html
* @ psalm - taint - escape has_quotes
2020-11-20 06:19:59 -05:00
*
2024-09-12 10:17:19 -04:00
* @ deprecated 31.0 . 0 use IAppManager :: cleanAppId
2013-02-09 09:03:47 -05:00
*/
2018-02-17 09:37:57 -05:00
public static function cleanAppId ( string $app ) : string {
2022-08-31 15:15:02 -04:00
return str_replace ([ '<' , '>' , '"' , " ' " , '\0' , '/' , '\\' , '..' ], '' , $app );
2013-02-09 09:03:47 -05:00
}
2015-08-18 04:18:36 -04:00
/**
* Check if an app is loaded
*
* @ param string $app
* @ return bool
2023-03-27 08:27:23 -04:00
* @ deprecated 27.0 . 0 use IAppManager :: isAppLoaded
2015-08-18 04:18:36 -04:00
*/
2018-02-17 09:37:57 -05:00
public static function isAppLoaded ( string $app ) : bool {
2023-02-07 10:56:04 -05:00
return \OC :: $server -> get ( IAppManager :: class ) -> isAppLoaded ( $app );
2015-08-18 04:18:36 -04:00
}
2011-03-03 15:55:32 -05:00
/**
2014-05-19 11:50:53 -04:00
* loads all apps
2015-02-02 08:47:38 -05:00
*
2018-02-17 09:22:00 -05:00
* @ param string [] $types
2012-09-22 20:39:11 -04:00
* @ return bool
2011-03-03 15:55:32 -05:00
*
2024-09-17 08:41:25 -04:00
* This function walks through the Nextcloud directory and loads all apps
2015-03-17 10:33:55 -04:00
* it can find . A directory contains an app if the file / appinfo / info . xml
2011-03-11 08:59:24 -05:00
* exists .
2012-03-30 08:39:07 -04:00
*
2018-02-17 09:22:00 -05:00
* if $types is set to non - empty array , only apps of those types will be loaded
2024-02-08 08:34:01 -05:00
*
* @ deprecated 29.0 . 0 use IAppManager :: loadApps instead
2011-03-03 15:55:32 -05:00
*/
2018-02-17 09:22:00 -05:00
public static function loadApps ( array $types = []) : bool {
2023-02-08 06:35:57 -05:00
if ( ! \OC :: $server -> getSystemConfig () -> getValue ( 'installed' , false )) {
// This should be done before calling this method so that appmanager can be used
2014-07-24 11:51:28 -04:00
return false ;
}
2023-02-08 06:35:57 -05:00
return \OC :: $server -> get ( IAppManager :: class ) -> loadApps ( $types );
2013-02-09 11:27:57 -05:00
}
2011-03-03 15:55:32 -05:00
2012-05-13 18:28:22 -04:00
/**
* load a single app
2014-04-17 09:30:27 -04:00
*
2012-09-22 20:39:11 -04:00
* @ param string $app
2018-02-15 05:20:22 -05:00
* @ throws Exception
2023-03-27 08:27:23 -04:00
* @ deprecated 27.0 . 0 use IAppManager :: loadApp
2012-05-13 18:28:22 -04:00
*/
2023-02-07 10:06:32 -05:00
public static function loadApp ( string $app ) : void {
2023-02-07 10:56:04 -05:00
\OC :: $server -> get ( IAppManager :: class ) -> loadApp ( $app );
2012-05-13 18:28:22 -04:00
}
2016-05-02 08:11:34 -04:00
/**
2016-05-10 05:49:55 -04:00
* @ internal
2016-05-02 08:11:34 -04:00
* @ param string $app
* @ param string $path
2020-01-13 09:14:56 -05:00
* @ param bool $force
2016-05-02 08:11:34 -04:00
*/
2020-01-13 09:14:56 -05:00
public static function registerAutoloading ( string $app , string $path , bool $force = false ) {
2016-08-22 17:49:46 -04:00
$key = $app . '-' . $path ;
2020-01-13 09:14:56 -05:00
if ( ! $force && isset ( self :: $alreadyRegistered [ $key ])) {
2016-08-22 17:49:46 -04:00
return ;
}
2017-10-17 05:49:32 -04:00
2016-08-22 17:49:46 -04:00
self :: $alreadyRegistered [ $key ] = true ;
2017-10-17 05:49:32 -04:00
2016-05-02 08:11:34 -04:00
// Register on PSR-4 composer autoloader
$appNamespace = \OC\AppFramework\App :: buildAppNamespace ( $app );
2017-03-22 06:50:58 -04:00
\OC :: $server -> registerNamespace ( $app , $appNamespace );
2017-10-17 05:49:32 -04:00
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
2016-07-25 04:58:03 -04:00
if ( defined ( 'PHPUNIT_RUN' ) || defined ( 'CLI_TEST_RUN' )) {
2016-05-02 08:11:34 -04:00
\OC :: $composerAutoloader -> addPsr4 ( $appNamespace . '\\Tests\\' , $path . '/tests/' , true );
}
}
2012-03-30 08:39:07 -04:00
/**
2012-05-14 11:58:50 -04:00
* check if an app is of a specific type
2014-04-17 09:30:27 -04:00
*
2012-03-30 08:39:07 -04:00
* @ param string $app
2018-02-17 09:22:00 -05:00
* @ param array $types
2012-09-22 20:39:11 -04:00
* @ return bool
2023-03-27 08:27:23 -04:00
* @ deprecated 27.0 . 0 use IAppManager :: isType
2012-03-30 08:39:07 -04:00
*/
2018-02-17 09:22:00 -05:00
public static function isType ( string $app , array $types ) : bool {
2023-02-08 05:46:07 -05:00
return \OC :: $server -> get ( IAppManager :: class ) -> isType ( $app , $types );
2012-05-14 16:49:20 -04:00
}
2012-05-02 05:14:11 -04:00
2012-05-14 16:49:20 -04:00
/**
* read app types from info . xml and cache them in the database
*/
2018-02-17 09:29:15 -05:00
public static function setAppTypes ( string $app ) {
$appManager = \OC :: $server -> getAppManager ();
$appData = $appManager -> getAppInfo ( $app );
2016-03-30 17:29:26 -04:00
if ( ! is_array ( $appData )) {
return ;
}
2012-06-04 15:30:58 -04:00
2014-04-17 09:30:27 -04:00
if ( isset ( $appData [ 'types' ])) {
$appTypes = implode ( ',' , $appData [ 'types' ]);
} else {
$appTypes = '' ;
2017-01-04 04:40:14 -05:00
$appData [ 'types' ] = [];
2012-04-14 11:53:02 -04:00
}
2012-05-02 05:14:11 -04:00
2018-02-17 09:29:15 -05:00
$config = \OC :: $server -> getConfig ();
$config -> setAppValue ( $app , 'types' , $appTypes );
2017-01-04 04:40:14 -05:00
2018-02-17 09:29:15 -05:00
if ( $appManager -> hasProtectedAppType ( $appData [ 'types' ])) {
$enabled = $config -> getAppValue ( $app , 'enabled' , 'yes' );
2017-01-04 04:40:14 -05:00
if ( $enabled !== 'yes' && $enabled !== 'no' ) {
2018-02-17 09:29:15 -05:00
$config -> setAppValue ( $app , 'enabled' , 'yes' );
2017-01-04 04:40:14 -05:00
}
}
2012-04-14 11:53:02 -04:00
}
2013-01-14 14:30:39 -05:00
2014-09-02 08:30:46 -04:00
/**
* 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
2024-09-24 09:53:13 -04:00
* @ return list < string >
2014-09-02 08:30:46 -04:00
*/
2018-02-17 09:37:57 -05:00
public static function getEnabledApps ( bool $forceRefresh = false , bool $all = false ) : array {
2015-12-18 05:42:09 -05:00
if ( ! \OC :: $server -> getSystemConfig () -> getValue ( 'installed' , false )) {
2018-02-17 09:18:34 -05:00
return [];
2013-02-09 16:43:35 -05:00
}
2014-09-02 08:30:46 -04:00
// in incognito mode or when logged out, $user will be false,
// which is also the case during an upgrade
2015-02-02 08:47:38 -05:00
$appManager = \OC :: $server -> getAppManager ();
if ( $all ) {
$user = null ;
} else {
$user = \OC :: $server -> getUserSession () -> getUser ();
2013-10-05 13:18:18 -04:00
}
2015-02-02 08:47:38 -05:00
if ( is_null ( $user )) {
2025-02-10 05:35:38 -05:00
$apps = $appManager -> getEnabledApps ();
2015-02-02 08:47:38 -05:00
} else {
2015-02-05 09:11:07 -05:00
$apps = $appManager -> getEnabledAppsForUser ( $user );
2012-03-30 08:00:24 -04:00
}
2015-02-02 08:47:38 -05:00
$apps = array_filter ( $apps , function ( $app ) {
return $app !== 'files' ; //we add this manually
});
2014-04-21 07:38:08 -04:00
sort ( $apps );
array_unshift ( $apps , 'files' );
2012-03-30 08:00:24 -04:00
return $apps ;
}
2011-06-19 09:18:52 -04:00
/**
2014-05-19 11:50:53 -04:00
* enables an app
2015-02-02 08:47:38 -05:00
*
2016-10-27 11:41:15 -04:00
* @ param string $appId
2014-04-18 08:29:45 -04:00
* @ param array $groups ( optional ) when set , only these groups will have access to the app
2013-08-06 11:19:18 -04:00
* @ throws \Exception
* @ return void
2025-07-29 11:29:30 -04:00
* @ deprecated 32.0 . 0 Use the installer and the app manager instead
2011-06-19 09:18:52 -04:00
*
* This function set an app as enabled in appconfig .
*/
2018-02-17 09:36:16 -05:00
public function enable ( string $appId ,
array $groups = []) {
2016-10-27 11:41:15 -04:00
// Check if app is already downloaded
2018-02-22 10:00:26 -05:00
/** @var Installer $installer */
2025-06-04 15:38:43 -04:00
$installer = Server :: get ( Installer :: class );
2016-10-27 11:41:15 -04:00
$isDownloaded = $installer -> isDownloaded ( $appId );
if ( ! $isDownloaded ) {
2016-10-31 06:07:54 -04:00
$installer -> downloadApp ( $appId );
2016-10-27 11:41:15 -04:00
}
2017-05-15 01:03:35 -04:00
$installer -> installApp ( $appId );
2014-05-21 06:14:10 -04:00
2015-02-16 10:44:51 -05:00
$appManager = \OC :: $server -> getAppManager ();
2018-02-17 09:36:16 -05:00
if ( $groups !== []) {
2015-03-24 07:56:42 -04:00
$groupManager = \OC :: $server -> getGroupManager ();
$groupsList = [];
foreach ( $groups as $group ) {
$groupItem = $groupManager -> get ( $group );
if ( $groupItem instanceof \OCP\IGroup ) {
$groupsList [] = $groupManager -> get ( $group );
}
}
2016-10-27 11:41:15 -04:00
$appManager -> enableAppForGroups ( $appId , $groupsList );
2015-02-02 08:47:38 -05:00
} else {
2016-10-27 11:41:15 -04:00
$appManager -> enableApp ( $appId );
2014-06-05 16:54:27 -04:00
}
2014-05-21 06:14:10 -04:00
}
/**
2024-07-11 06:05:14 -04:00
* Find the apps root for an app id .
*
* If multiple copies are found , the apps root the latest version is returned .
2015-02-02 08:47:38 -05:00
*
2023-01-26 06:38:20 -05:00
* @ param bool $ignoreCache ignore cache and rebuild it
2024-07-11 06:05:14 -04:00
* @ return false | array { path : string , url : string } the apps root shape
2025-07-29 11:47:40 -04:00
* @ deprecated 32.0 . 0 internal , use getAppPath or getAppWebPath
2014-05-21 06:14:10 -04:00
*/
2023-01-26 06:38:20 -05:00
public static function findAppInDirectories ( string $appId , bool $ignoreCache = false ) {
2025-07-29 11:47:40 -04:00
return Server :: get ( AppManager :: class ) -> findAppInDirectories ( $appId , $ignoreCache );
2012-06-14 17:00:02 -04:00
}
2014-05-21 06:14:10 -04:00
/**
* get app 's version based on it' s path
2015-02-02 08:47:38 -05:00
*
2025-07-29 11:47:40 -04:00
* @ deprecated 32.0 . 0 use Server :: get ( IAppManager ) -> getAppInfoByPath () with the path to info . xml directly
2014-05-21 06:14:10 -04:00
*/
2018-02-17 09:37:57 -05:00
public static function getAppVersionByPath ( string $path ) : string {
2014-05-21 06:14:10 -04:00
$infoFile = $path . '/appinfo/info.xml' ;
2025-06-04 15:38:43 -04:00
$appData = Server :: get ( IAppManager :: class ) -> getAppInfoByPath ( $infoFile );
2023-07-07 06:13:21 -04:00
return $appData [ 'version' ] ? ? '' ;
2012-04-14 10:27:58 -04:00
}
2011-10-05 06:31:33 -04:00
2011-07-25 14:12:35 -04:00
/**
* get the id of loaded app
2014-04-17 09:30:27 -04:00
*
2011-07-25 14:12:35 -04:00
* @ return string
*/
2018-02-17 09:37:32 -05:00
public static function getCurrentApp () : string {
2022-04-07 08:08:37 -04:00
if ( \OC :: $CLI ) {
return '' ;
}
2015-02-10 07:02:48 -05:00
$request = \OC :: $server -> getRequest ();
$script = substr ( $request -> getScriptName (), strlen ( OC :: $WEBROOT ) + 1 );
2018-01-12 09:01:45 -05:00
$topFolder = substr ( $script , 0 , strpos ( $script , '/' ) ? : 0 );
2012-09-28 17:15:19 -04:00
if ( empty ( $topFolder )) {
2022-04-07 08:08:37 -04:00
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.
2022-04-07 08:45:58 -04:00
\OC :: $server -> get ( LoggerInterface :: class ) -> error ( 'Failed to detect current app from script path' , [ 'exception' => $e ]);
2022-04-07 08:08:37 -04:00
return '' ;
}
2012-09-28 17:15:19 -04:00
if ( $path_info ) {
2014-04-17 09:30:27 -04:00
$topFolder = substr ( $path_info , 1 , strpos ( $path_info , '/' , 1 ) - 1 );
2012-09-28 17:15:19 -04:00
}
}
2014-04-17 09:30:27 -04:00
if ( $topFolder == 'apps' ) {
$length = strlen ( $topFolder );
2018-02-17 09:37:32 -05:00
return substr ( $script , $length + 1 , strpos ( $script , '/' , $length + 1 ) - $length - 1 ) ? : '' ;
2014-04-17 09:30:27 -04:00
} else {
2011-07-25 14:12:35 -04:00
return $topFolder ;
}
}
2011-10-05 06:31:33 -04:00
2015-02-11 18:11:38 -05:00
/**
* @ param array $entry
2020-07-15 11:06:27 -04:00
* @ 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
2015-02-11 18:11:38 -05:00
*/
public static function registerLogIn ( array $entry ) {
2025-06-04 15:38:43 -04:00
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' );
2013-01-29 11:28:08 -05:00
self :: $altLogin [] = $entry ;
}
2015-02-11 18:11:38 -05:00
/**
* @ return array
*/
2018-02-17 09:37:57 -05:00
public static function getAlternativeLogIns () : array {
2020-07-15 11:06:27 -04:00
/** @var Coordinator $bootstrapCoordinator */
2025-06-04 15:38:43 -04:00
$bootstrapCoordinator = Server :: get ( Coordinator :: class );
2020-07-15 11:06:27 -04:00
foreach ( $bootstrapCoordinator -> getRegistrationContext () -> getAlternativeLogins () as $registration ) {
2021-01-28 08:08:38 -05:00
if ( ! in_array ( IAlternativeLogin :: class , class_implements ( $registration -> getService ()), true )) {
2025-06-04 15:38:43 -04:00
Server :: get ( LoggerInterface :: class ) -> error ( 'Alternative login option {option} does not implement {interface} and is therefore ignored.' , [
2021-01-28 08:08:38 -05:00
'option' => $registration -> getService (),
2020-07-15 11:06:27 -04:00
'interface' => IAlternativeLogin :: class ,
2021-01-28 08:08:38 -05:00
'app' => $registration -> getAppId (),
2020-07-15 11:06:27 -04:00
]);
continue ;
}
try {
/** @var IAlternativeLogin $provider */
2025-06-04 15:38:43 -04:00
$provider = Server :: get ( $registration -> getService ());
2023-06-06 05:09:24 -04:00
} catch ( ContainerExceptionInterface $e ) {
2025-06-04 15:38:43 -04:00
Server :: get ( LoggerInterface :: class ) -> error ( 'Alternative login option {option} can not be initialized.' ,
2024-09-14 19:34:47 -04:00
[
'exception' => $e ,
'option' => $registration -> getService (),
'app' => $registration -> getAppId (),
]);
2020-07-15 11:06:27 -04:00
}
try {
$provider -> load ();
self :: $altLogin [] = [
'name' => $provider -> getLabel (),
'href' => $provider -> getLink (),
2022-10-20 00:32:13 -04:00
'class' => $provider -> getClass (),
2020-07-15 11:06:27 -04:00
];
} catch ( Throwable $e ) {
2025-06-04 15:38:43 -04:00
Server :: get ( LoggerInterface :: class ) -> error ( 'Alternative login option {option} had an error while loading.' ,
2024-09-14 19:34:47 -04:00
[
'exception' => $e ,
'option' => $registration -> getService (),
'app' => $registration -> getAppId (),
]);
2020-07-15 11:06:27 -04:00
}
}
2013-01-29 11:28:08 -05:00
return self :: $altLogin ;
}
2011-08-10 06:20:43 -04:00
/**
2014-05-19 11:50:53 -04:00
* get a list of all apps in the apps folder
2015-02-02 08:47:38 -05:00
*
2020-05-28 14:37:24 -04:00
* @ return string [] an array of app names ( string IDs )
2024-09-12 10:38:35 -04:00
* @ deprecated 31.0 . 0 Use IAppManager :: getAllAppsInAppsFolders instead
2011-08-10 06:20:43 -04:00
*/
2018-02-17 09:37:57 -05:00
public static function getAllApps () : array {
2025-06-04 15:38:43 -04:00
return Server :: get ( IAppManager :: class ) -> getAllAppsInAppsFolders ();
2011-08-10 06:20:43 -04:00
}
2012-10-14 15:04:08 -04:00
2021-09-08 17:43:17 -04:00
/**
* List all supported apps
*
2025-03-24 12:02:50 -04:00
* @ deprecated 32.0 . 0 Use \OCP\Support\Subscription\IRegistry :: delegateGetSupportedApps instead
2021-09-08 17:43:17 -04:00
*/
public function getSupportedApps () : array {
2025-06-04 15:38:43 -04:00
$subscriptionRegistry = Server :: get ( \OCP\Support\Subscription\IRegistry :: class );
2021-09-08 17:43:17 -04:00
$supportedApps = $subscriptionRegistry -> delegateGetSupportedApps ();
return $supportedApps ;
}
2013-01-21 16:18:11 -05:00
/**
2015-03-30 09:58:20 -04:00
* List all apps , this is used in apps . php
2015-02-02 08:47:38 -05:00
*
2013-01-21 16:18:11 -05:00
* @ return array
*/
2018-02-17 09:37:57 -05:00
public function listAllApps () : array {
2017-08-01 12:57:00 -04:00
$appManager = \OC :: $server -> getAppManager ();
2024-09-12 10:38:35 -04:00
$installedApps = $appManager -> getAllAppsInAppsFolders ();
2015-10-16 10:38:43 -04:00
//we don't want to show configuration for these
2017-08-01 12:57:00 -04:00
$blacklist = $appManager -> getAlwaysEnabledApps ();
2018-02-17 09:18:34 -05:00
$appList = [];
2016-09-30 05:00:58 -04:00
$langCode = \OC :: $server -> getL10N ( 'core' ) -> getLanguageCode ();
2016-09-23 15:47:47 -04:00
$urlGenerator = \OC :: $server -> getURLGenerator ();
2021-09-08 17:43:17 -04:00
$supportedApps = $this -> getSupportedApps ();
2013-01-21 16:18:11 -05:00
2014-04-17 09:30:27 -04:00
foreach ( $installedApps as $app ) {
2023-09-17 04:43:23 -04:00
if ( ! in_array ( $app , $blacklist )) {
2023-05-31 15:15:51 -04:00
$info = $appManager -> getAppInfo ( $app , false , $langCode );
2016-03-30 17:29:26 -04:00
if ( ! is_array ( $info )) {
2025-06-04 15:38:43 -04:00
Server :: get ( LoggerInterface :: class ) -> error ( 'Could not read app info file for app "' . $app . '"' , [ 'app' => 'core' ]);
2016-03-30 17:29:26 -04:00
continue ;
}
2013-01-21 16:18:11 -05:00
if ( ! isset ( $info [ 'name' ])) {
2025-06-04 15:38:43 -04:00
Server :: get ( LoggerInterface :: class ) -> error ( 'App id "' . $app . '" has no name in appinfo' , [ 'app' => 'core' ]);
2013-01-21 16:18:11 -05:00
continue ;
}
2018-01-17 15:10:40 -05:00
$enabled = \OC :: $server -> getConfig () -> getAppValue ( $app , 'enabled' , 'no' );
2014-04-18 08:29:45 -04:00
$info [ 'groups' ] = null ;
if ( $enabled === 'yes' ) {
2013-01-21 16:18:11 -05:00
$active = true ;
2020-04-10 04:35:09 -04:00
} elseif ( $enabled === 'no' ) {
2013-01-21 16:18:11 -05:00
$active = false ;
2014-04-18 08:29:45 -04:00
} else {
$active = true ;
$info [ 'groups' ] = $enabled ;
2013-01-21 16:18:11 -05:00
}
$info [ 'active' ] = $active ;
2017-08-01 12:57:00 -04:00
if ( $appManager -> isShipped ( $app )) {
2014-04-17 09:30:27 -04:00
$info [ 'internal' ] = true ;
2015-03-30 09:58:20 -04:00
$info [ 'level' ] = self :: officialApp ;
2014-05-31 11:50:39 -04:00
$info [ 'removable' ] = false ;
2013-01-21 16:18:11 -05:00
} else {
2014-04-17 09:30:27 -04:00
$info [ 'internal' ] = false ;
2014-05-31 11:50:39 -04:00
$info [ 'removable' ] = true ;
2013-01-21 16:18:11 -05:00
}
2019-05-10 08:50:24 -04:00
if ( in_array ( $app , $supportedApps )) {
$info [ 'level' ] = self :: supportedApp ;
}
2016-02-14 14:57:09 -05:00
$appPath = self :: getAppPath ( $app );
if ( $appPath !== false ) {
$appIcon = $appPath . '/img/' . $app . '.svg' ;
2014-08-14 09:48:38 -04:00
if ( file_exists ( $appIcon )) {
2017-08-01 12:57:00 -04:00
$info [ 'preview' ] = $urlGenerator -> imagePath ( $app , $app . '.svg' );
2014-08-14 09:48:38 -04:00
$info [ 'previewAsIcon' ] = true ;
2016-02-14 14:57:09 -05:00
} else {
$appIcon = $appPath . '/img/app.svg' ;
if ( file_exists ( $appIcon )) {
2017-08-01 12:57:00 -04:00
$info [ 'preview' ] = $urlGenerator -> imagePath ( $app , 'app.svg' );
2016-02-14 14:57:09 -05:00
$info [ 'previewAsIcon' ] = true ;
}
2014-08-14 09:48:38 -04:00
}
}
2016-09-23 15:47:47 -04:00
// 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 ;
}
}
2023-05-31 15:13:58 -04:00
$info [ 'version' ] = $appManager -> getAppVersion ( $app );
2013-01-21 16:18:11 -05:00
$appList [] = $info ;
}
}
2013-10-14 04:54:38 -04:00
2016-10-27 11:41:15 -04:00
return $appList ;
2013-10-14 04:54:38 -04:00
}
2025-07-29 11:29:30 -04:00
/**
* @ deprecated 32.0 . 0 Use IAppManager :: isUpgradeRequired instead
*/
2018-02-17 09:37:57 -05:00
public static function shouldUpgrade ( string $app ) : bool {
2025-07-29 10:50:00 -04:00
return Server :: get ( \OCP\App\IAppManager :: class ) -> isUpgradeRequired ( $app );
2014-05-27 05:54:12 -04:00
}
2013-02-25 06:38:00 -05:00
/**
2024-09-17 08:41:25 -04:00
* Check whether the current Nextcloud version matches the given
2014-05-27 05:54:12 -04:00
* 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.
*
2024-09-17 08:41:25 -04:00
* @ param string $ocVersion Nextcloud version to check against
2015-02-02 08:47:38 -05:00
* @ param array $appInfo app info ( from xml )
2014-05-27 05:54:12 -04:00
*
2025-07-29 10:50:00 -04:00
* @ return bool true if compatible , otherwise false
2025-07-29 11:29:30 -04:00
* @ deprecated 32.0 . 0 Use IAppManager :: isAppCompatible instead
2013-02-25 06:38:00 -05:00
*/
2019-03-06 13:59:15 -05:00
public static function isAppCompatible ( string $ocVersion , array $appInfo , bool $ignoreMax = false ) : bool {
2025-07-29 10:50:00 -04:00
return Server :: get ( \OCP\App\IAppManager :: class ) -> isAppCompatible ( $ocVersion , $appInfo , $ignoreMax );
2013-02-25 06:38:00 -05:00
}
2012-03-30 07:48:44 -04:00
/**
2012-06-28 16:01:46 -04:00
* get the installed version of all apps
2025-03-25 11:18:51 -04:00
* @ deprecated 32.0 . 0 Use IAppManager :: getAppInstalledVersions or IAppConfig :: getAppInstalledVersions instead
2012-03-30 07:48:44 -04:00
*/
2025-03-25 11:18:51 -04:00
public static function getAppVersions () : array {
2025-06-04 15:38:43 -04:00
return Server :: get ( IAppConfig :: class ) -> getAppInstalledVersions ();
2012-03-30 07:48:44 -04:00
}
2011-12-11 16:08:01 -05:00
/**
* update the database for the app and call the update script
2014-04-17 09:30:27 -04:00
*
2025-07-10 10:01:09 -04:00
* @ deprecated 32.0 . 0 Use IAppManager :: upgradeApp instead
2011-12-11 16:08:01 -05:00
*/
2018-02-19 04:28:41 -05:00
public static function updateApp ( string $appId ) : bool {
2025-07-10 10:01:09 -04:00
try {
return Server :: get ( \OC\App\AppManager :: class ) -> upgradeApp ( $appId );
} catch ( \OCP\App\AppPathNotFoundException $e ) {
2020-06-30 15:47:31 -04:00
return false ;
}
2011-12-11 16:08:01 -05:00
}
2012-02-08 15:01:09 -05:00
2016-04-19 09:36:11 -04:00
/**
* @ param string $appId
* @ param string [] $steps
* @ throws \OC\NeedsUpdateException
*/
2018-02-17 09:37:57 -05:00
public static function executeRepairSteps ( string $appId , array $steps ) {
2016-04-19 09:36:11 -04:00
if ( empty ( $steps )) {
return ;
}
// load the app
2017-03-13 20:07:41 -04:00
self :: loadApp ( $appId );
2016-04-19 09:36:11 -04:00
2024-06-18 05:55:08 -04:00
$dispatcher = Server :: get ( IEventDispatcher :: class );
2016-04-19 09:36:11 -04:00
// load the steps
2024-06-18 05:55:08 -04:00
$r = Server :: get ( Repair :: class );
2016-04-19 09:36:11 -04:00
foreach ( $steps as $step ) {
try {
$r -> addStep ( $step );
} catch ( Exception $ex ) {
2022-08-22 11:59:26 -04:00
$dispatcher -> dispatchTyped ( new RepairErrorEvent ( $ex -> getMessage ()));
2024-06-18 05:55:08 -04:00
logger ( 'core' ) -> error ( 'Failed to add app migration step ' . $step , [ 'exception' => $ex ]);
2016-04-19 09:36:11 -04:00
}
}
// run the steps
$r -> run ();
}
2025-07-29 11:53:16 -04:00
/**
* @ deprecated 32.0 . 0 Use the IJobList directly instead
*/
2016-05-02 09:26:12 -04:00
public static function setupBackgroundJobs ( array $jobs ) {
$queue = \OC :: $server -> getJobList ();
foreach ( $jobs as $job ) {
$queue -> add ( $job );
}
}
2016-10-07 05:27:33 -04:00
/**
2017-01-11 04:57:26 -05:00
* @ param \OCP\IConfig $config
* @ param \OCP\IL10N $l
* @ param array $info
* @ throws \Exception
2016-10-07 05:27:33 -04:00
*/
2019-03-06 13:59:15 -05:00
public static function checkAppDependencies ( \OCP\IConfig $config , \OCP\IL10N $l , array $info , bool $ignoreMax ) {
2025-07-31 11:44:44 -04:00
$dependencyAnalyzer = Server :: get ( DependencyAnalyzer :: class );
2019-03-06 13:59:15 -05:00
$missing = $dependencyAnalyzer -> analyze ( $info , $ignoreMax );
2016-10-07 05:27:33 -04:00
if ( ! empty ( $missing )) {
2017-07-23 15:03:26 -04:00
$missingMsg = implode ( PHP_EOL , $missing );
2016-10-07 05:27:33 -04:00
throw new \Exception (
2018-10-09 08:32:14 -04:00
$l -> t ( 'App "%1$s" cannot be installed because the following dependencies are not fulfilled: %2$s' ,
2016-10-07 05:27:33 -04:00
[ $info [ 'name' ], $missingMsg ]
)
);
}
}
2011-03-03 15:55:32 -05:00
}