Allow to force enable apps via CLItags/v18.0.0beta3
@@ -549,13 +549,7 @@ class AppSettingsController extends Controller { | |||
public function force(string $appId): JSONResponse { | |||
$appId = OC_App::cleanAppId($appId); | |||
$ignoreMaxApps = $this->config->getSystemValue('app_install_overwrite', []); | |||
if (!in_array($appId, $ignoreMaxApps, true)) { | |||
$ignoreMaxApps[] = $appId; | |||
$this->config->setSystemValue('app_install_overwrite', $ignoreMaxApps); | |||
} | |||
$this->appManager->ignoreNextcloudRequirementForApp($appId); | |||
return new JSONResponse(); | |||
} | |||
@@ -73,15 +73,22 @@ class Enable extends Command implements CompletionAwareInterface { | |||
'g', | |||
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, | |||
'enable the app only for a list of groups' | |||
) | |||
->addOption( | |||
'force', | |||
'f', | |||
InputOption::VALUE_NONE, | |||
'enable the app regardless of the Nextcloud version requirement' | |||
); | |||
} | |||
protected function execute(InputInterface $input, OutputInterface $output) { | |||
$appIds = $input->getArgument('app-id'); | |||
$groups = $this->resolveGroupIds($input->getOption('groups')); | |||
$forceEnable = (bool) $input->getOption('force'); | |||
foreach ($appIds as $appId) { | |||
$this->enableApp($appId, $groups, $output); | |||
$this->enableApp($appId, $groups, $forceEnable, $output); | |||
} | |||
return $this->exitCode; | |||
@@ -90,9 +97,10 @@ class Enable extends Command implements CompletionAwareInterface { | |||
/** | |||
* @param string $appId | |||
* @param array $groupIds | |||
* @param bool $forceEnable | |||
* @param OutputInterface $output | |||
*/ | |||
private function enableApp(string $appId, array $groupIds, OutputInterface $output): void { | |||
private function enableApp(string $appId, array $groupIds, bool $forceEnable, OutputInterface $output): void { | |||
$groupNames = array_map(function (IGroup $group) { | |||
return $group->getDisplayName(); | |||
}, $groupIds); | |||
@@ -106,13 +114,13 @@ class Enable extends Command implements CompletionAwareInterface { | |||
$installer->downloadApp($appId); | |||
} | |||
$installer->installApp($appId); | |||
$installer->installApp($appId, $forceEnable); | |||
if ($groupIds === []) { | |||
$this->appManager->enableApp($appId); | |||
$this->appManager->enableApp($appId, $forceEnable); | |||
$output->writeln($appId . ' enabled'); | |||
} else { | |||
$this->appManager->enableAppForGroups($appId, $groupIds); | |||
$this->appManager->enableAppForGroups($appId, $groupIds, $forceEnable); | |||
$output->writeln($appId . ' enabled for groups: ' . implode(', ', $groupNames)); | |||
} | |||
} catch (AppPathNotFoundException $e) { |
@@ -42,6 +42,7 @@ use OCP\App\AppPathNotFoundException; | |||
use OCP\App\IAppManager; | |||
use OCP\App\ManagerEvent; | |||
use OCP\ICacheFactory; | |||
use OCP\IConfig; | |||
use OCP\IGroup; | |||
use OCP\IGroupManager; | |||
use OCP\ILogger; | |||
@@ -66,6 +67,9 @@ class AppManager implements IAppManager { | |||
/** @var IUserSession */ | |||
private $userSession; | |||
/** @var IConfig */ | |||
private $config; | |||
/** @var AppConfig */ | |||
private $appConfig; | |||
@@ -101,18 +105,21 @@ class AppManager implements IAppManager { | |||
/** | |||
* @param IUserSession $userSession | |||
* @param IConfig $config | |||
* @param AppConfig $appConfig | |||
* @param IGroupManager $groupManager | |||
* @param ICacheFactory $memCacheFactory | |||
* @param EventDispatcherInterface $dispatcher | |||
*/ | |||
public function __construct(IUserSession $userSession, | |||
IConfig $config, | |||
AppConfig $appConfig, | |||
IGroupManager $groupManager, | |||
ICacheFactory $memCacheFactory, | |||
EventDispatcherInterface $dispatcher, | |||
ILogger $logger) { | |||
$this->userSession = $userSession; | |||
$this->config = $config; | |||
$this->appConfig = $appConfig; | |||
$this->groupManager = $groupManager; | |||
$this->memCacheFactory = $memCacheFactory; | |||
@@ -296,16 +303,29 @@ class AppManager implements IAppManager { | |||
return isset($installedApps[$appId]); | |||
} | |||
public function ignoreNextcloudRequirementForApp(string $appId): void { | |||
$ignoreMaxApps = $this->config->getSystemValue('app_install_overwrite', []); | |||
if (!in_array($appId, $ignoreMaxApps, true)) { | |||
$ignoreMaxApps[] = $appId; | |||
$this->config->setSystemValue('app_install_overwrite', $ignoreMaxApps); | |||
} | |||
} | |||
/** | |||
* Enable an app for every user | |||
* | |||
* @param string $appId | |||
* @param bool $forceEnable | |||
* @throws AppPathNotFoundException | |||
*/ | |||
public function enableApp($appId) { | |||
public function enableApp(string $appId, bool $forceEnable = false): void { | |||
// Check if app exists | |||
$this->getAppPath($appId); | |||
if ($forceEnable) { | |||
$this->ignoreNextcloudRequirementForApp($appId); | |||
} | |||
$this->installedAppsCache[$appId] = 'yes'; | |||
$this->appConfig->setValue($appId, 'enabled', 'yes'); | |||
$this->dispatcher->dispatch(ManagerEvent::EVENT_APP_ENABLE, new ManagerEvent( | |||
@@ -334,10 +354,11 @@ class AppManager implements IAppManager { | |||
* | |||
* @param string $appId | |||
* @param \OCP\IGroup[] $groups | |||
* @param bool $forceEnable | |||
* @throws \InvalidArgumentException if app can't be enabled for groups | |||
* @throws AppPathNotFoundException | |||
*/ | |||
public function enableAppForGroups($appId, $groups) { | |||
public function enableAppForGroups(string $appId, array $groups, bool $forceEnable = false): void { | |||
// Check if app exists | |||
$this->getAppPath($appId); | |||
@@ -346,6 +367,10 @@ class AppManager implements IAppManager { | |||
throw new \InvalidArgumentException("$appId can't be enabled for groups."); | |||
} | |||
if ($forceEnable) { | |||
$this->ignoreNextcloudRequirementForApp($appId); | |||
} | |||
$groupIds = array_map(function ($group) { | |||
/** @var \OCP\IGroup $group */ | |||
return ($group instanceof IGroup) |
@@ -94,10 +94,11 @@ class Installer { | |||
* Installs an app that is located in one of the app folders already | |||
* | |||
* @param string $appId App to install | |||
* @param bool $forceEnable | |||
* @throws \Exception | |||
* @return string app ID | |||
*/ | |||
public function installApp($appId) { | |||
public function installApp(string $appId, bool $forceEnable = false): string { | |||
$app = \OC_App::findAppInDirectories($appId); | |||
if($app === false) { | |||
throw new \Exception('App not found in any app directory'); | |||
@@ -117,7 +118,7 @@ class Installer { | |||
} | |||
$ignoreMaxApps = $this->config->getSystemValue('app_install_overwrite', []); | |||
$ignoreMax = in_array($appId, $ignoreMaxApps); | |||
$ignoreMax = $forceEnable || in_array($appId, $ignoreMaxApps, true); | |||
$version = implode('.', \OCP\Util::getVersion()); | |||
if (!\OC_App::isAppCompatible($version, $info, $ignoreMax)) { |
@@ -798,6 +798,7 @@ class Server extends ServerContainer implements IServerContainer { | |||
$this->registerService(AppManager::class, function (Server $c) { | |||
return new \OC\App\AppManager( | |||
$c->getUserSession(), | |||
$c->getConfig(), | |||
$c->query(\OC\AppConfig::class), | |||
$c->getGroupManager(), | |||
$c->getMemCacheFactory(), |
@@ -86,10 +86,11 @@ interface IAppManager { | |||
* Enable an app for every user | |||
* | |||
* @param string $appId | |||
* @param bool $forceEnable | |||
* @throws AppPathNotFoundException | |||
* @since 8.0.0 | |||
*/ | |||
public function enableApp($appId); | |||
public function enableApp(string $appId, bool $forceEnable = false): void; | |||
/** | |||
* Whether a list of types contains a protected app type | |||
@@ -105,10 +106,11 @@ interface IAppManager { | |||
* | |||
* @param string $appId | |||
* @param \OCP\IGroup[] $groups | |||
* @param bool $forceEnable | |||
* @throws \Exception | |||
* @since 8.0.0 | |||
*/ | |||
public function enableAppForGroups($appId, $groups); | |||
public function enableAppForGroups(string $appId, array $groups, bool $forceEnable = false): void; | |||
/** | |||
* Disable an app for every user |
@@ -1,4 +1,4 @@ | |||
<?php | |||
<?php declare(strict_types=1); | |||
/** | |||
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> | |||
@@ -11,20 +11,17 @@ namespace Test\App; | |||
use OC\App\AppManager; | |||
use OC\AppConfig; | |||
use OC\Group\Group; | |||
use OC\User\User; | |||
use OCP\App\AppPathNotFoundException; | |||
use OCP\App\IAppManager; | |||
use OCP\IAppConfig; | |||
use OCP\ICache; | |||
use OCP\ICacheFactory; | |||
use OCP\IConfig; | |||
use OCP\IGroup; | |||
use OCP\IGroupManager; | |||
use OCP\ILogger; | |||
use OCP\IURLGenerator; | |||
use OCP\IUser; | |||
use OCP\IUserSession; | |||
use PHPUnit\Framework\MockObject\MockObject; | |||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |||
use Test\TestCase; | |||
@@ -35,7 +32,7 @@ use Test\TestCase; | |||
*/ | |||
class AppManagerTest extends TestCase { | |||
/** | |||
* @return AppConfig|\PHPUnit_Framework_MockObject_MockObject | |||
* @return AppConfig|MockObject | |||
*/ | |||
protected function getAppConfig() { | |||
$appConfig = array(); | |||
@@ -73,25 +70,28 @@ class AppManagerTest extends TestCase { | |||
return $config; | |||
} | |||
/** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IUserSession|MockObject */ | |||
protected $userSession; | |||
/** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IConfig|MockObject */ | |||
private $config; | |||
/** @var IGroupManager|MockObject */ | |||
protected $groupManager; | |||
/** @var AppConfig|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var AppConfig|MockObject */ | |||
protected $appConfig; | |||
/** @var ICache|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var ICache|MockObject */ | |||
protected $cache; | |||
/** @var ICacheFactory|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var ICacheFactory|MockObject */ | |||
protected $cacheFactory; | |||
/** @var EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var EventDispatcherInterface|MockObject */ | |||
protected $eventDispatcher; | |||
/** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var ILogger|MockObject */ | |||
protected $logger; | |||
/** @var IAppManager */ | |||
@@ -102,6 +102,7 @@ class AppManagerTest extends TestCase { | |||
$this->userSession = $this->createMock(IUserSession::class); | |||
$this->groupManager = $this->createMock(IGroupManager::class); | |||
$this->config = $this->createMock(IConfig::class); | |||
$this->appConfig = $this->getAppConfig(); | |||
$this->cacheFactory = $this->createMock(ICacheFactory::class); | |||
$this->cache = $this->createMock(ICache::class); | |||
@@ -111,7 +112,15 @@ class AppManagerTest extends TestCase { | |||
->method('createDistributed') | |||
->with('settings') | |||
->willReturn($this->cache); | |||
$this->manager = new AppManager($this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger); | |||
$this->manager = new AppManager( | |||
$this->userSession, | |||
$this->config, | |||
$this->appConfig, | |||
$this->groupManager, | |||
$this->cacheFactory, | |||
$this->eventDispatcher, | |||
$this->logger | |||
); | |||
} | |||
protected function expectClearCache() { | |||
@@ -161,10 +170,10 @@ class AppManagerTest extends TestCase { | |||
$groups = [$group1, $group2]; | |||
$this->expectClearCache(); | |||
/** @var AppManager|\PHPUnit_Framework_MockObject_MockObject $manager */ | |||
/** @var AppManager|MockObject $manager */ | |||
$manager = $this->getMockBuilder(AppManager::class) | |||
->setConstructorArgs([ | |||
$this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger | |||
$this->userSession, $this->config, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger | |||
]) | |||
->setMethods([ | |||
'getAppPath', | |||
@@ -208,10 +217,10 @@ class AppManagerTest extends TestCase { | |||
$groups = [$group1, $group2]; | |||
$this->expectClearCache(); | |||
/** @var AppManager|\PHPUnit_Framework_MockObject_MockObject $manager */ | |||
/** @var AppManager|MockObject $manager */ | |||
$manager = $this->getMockBuilder(AppManager::class) | |||
->setConstructorArgs([ | |||
$this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger | |||
$this->userSession, $this->config, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger | |||
]) | |||
->setMethods([ | |||
'getAppPath', | |||
@@ -262,10 +271,10 @@ class AppManagerTest extends TestCase { | |||
$groups = [$group1, $group2]; | |||
/** @var AppManager|\PHPUnit_Framework_MockObject_MockObject $manager */ | |||
/** @var AppManager|MockObject $manager */ | |||
$manager = $this->getMockBuilder(AppManager::class) | |||
->setConstructorArgs([ | |||
$this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger | |||
$this->userSession, $this->config, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger | |||
]) | |||
->setMethods([ | |||
'getAppPath', | |||
@@ -426,9 +435,9 @@ class AppManagerTest extends TestCase { | |||
} | |||
public function testGetAppsNeedingUpgrade() { | |||
/** @var AppManager|\PHPUnit_Framework_MockObject_MockObject $manager */ | |||
/** @var AppManager|MockObject $manager */ | |||
$manager = $this->getMockBuilder(AppManager::class) | |||
->setConstructorArgs([$this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger]) | |||
->setConstructorArgs([$this->userSession, $this->config, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger]) | |||
->setMethods(['getAppInfo']) | |||
->getMock(); | |||
@@ -476,9 +485,9 @@ class AppManagerTest extends TestCase { | |||
} | |||
public function testGetIncompatibleApps() { | |||
/** @var AppManager|\PHPUnit_Framework_MockObject_MockObject $manager */ | |||
/** @var AppManager|MockObject $manager */ | |||
$manager = $this->getMockBuilder(AppManager::class) | |||
->setConstructorArgs([$this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger]) | |||
->setConstructorArgs([$this->userSession, $this->config, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->logger]) | |||
->setMethods(['getAppInfo']) | |||
->getMock(); | |||
@@ -549,6 +549,7 @@ class AppTest extends \Test\TestCase { | |||
$this->overwriteService('AppConfig', $appConfig); | |||
$this->overwriteService('AppManager', new \OC\App\AppManager( | |||
\OC::$server->getUserSession(), | |||
\OC::$server->getConfig(), | |||
$appConfig, | |||
\OC::$server->getGroupManager(), | |||
\OC::$server->getMemCacheFactory(), |