Merge pull request #4454 from nextcloud/add-bundles-to-install-page

Add app bundles to the apps page and unbundle enterprise apps
This commit is contained in:
Morris Jobke 2017-04-26 18:20:40 -03:00 committed by GitHub
commit aad0794500
33 changed files with 1230 additions and 95 deletions

View File

@ -935,14 +935,15 @@ class OC {
// emergency app disabling // emergency app disabling
if ($requestPath === '/disableapp' if ($requestPath === '/disableapp'
&& $request->getMethod() === 'POST' && $request->getMethod() === 'POST'
&& ((string)$request->getParam('appid')) !== '' && ((array)$request->getParam('appid')) !== ''
) { ) {
\OCP\JSON::callCheck(); \OCP\JSON::callCheck();
\OCP\JSON::checkAdminUser(); \OCP\JSON::checkAdminUser();
$appId = (string)$request->getParam('appid'); $appIds = (array)$request->getParam('appid');
$appId = \OC_App::cleanAppId($appId); foreach($appIds as $appId) {
$appId = \OC_App::cleanAppId($appId);
\OC_App::disable($appId); \OC_App::disable($appId);
}
\OC_JSON::success(); \OC_JSON::success();
exit(); exit();
} }

View File

@ -318,6 +318,12 @@ return array(
'OC\\AppFramework\\Utility\\TimeFactory' => $baseDir . '/lib/private/AppFramework/Utility/TimeFactory.php', 'OC\\AppFramework\\Utility\\TimeFactory' => $baseDir . '/lib/private/AppFramework/Utility/TimeFactory.php',
'OC\\AppHelper' => $baseDir . '/lib/private/AppHelper.php', 'OC\\AppHelper' => $baseDir . '/lib/private/AppHelper.php',
'OC\\App\\AppManager' => $baseDir . '/lib/private/App/AppManager.php', 'OC\\App\\AppManager' => $baseDir . '/lib/private/App/AppManager.php',
'OC\\App\\AppStore\\Bundles\\Bundle' => $baseDir . '/lib/private/App/AppStore/Bundles/Bundle.php',
'OC\\App\\AppStore\\Bundles\\BundleFetcher' => $baseDir . '/lib/private/App/AppStore/Bundles/BundleFetcher.php',
'OC\\App\\AppStore\\Bundles\\CoreBundle' => $baseDir . '/lib/private/App/AppStore/Bundles/CoreBundle.php',
'OC\\App\\AppStore\\Bundles\\EnterpriseBundle' => $baseDir . '/lib/private/App/AppStore/Bundles/EnterpriseBundle.php',
'OC\\App\\AppStore\\Bundles\\GroupwareBundle' => $baseDir . '/lib/private/App/AppStore/Bundles/GroupwareBundle.php',
'OC\\App\\AppStore\\Bundles\\SocialSharingBundle' => $baseDir . '/lib/private/App/AppStore/Bundles/SocialSharingBundle.php',
'OC\\App\\AppStore\\Fetcher\\AppFetcher' => $baseDir . '/lib/private/App/AppStore/Fetcher/AppFetcher.php', 'OC\\App\\AppStore\\Fetcher\\AppFetcher' => $baseDir . '/lib/private/App/AppStore/Fetcher/AppFetcher.php',
'OC\\App\\AppStore\\Fetcher\\CategoryFetcher' => $baseDir . '/lib/private/App/AppStore/Fetcher/CategoryFetcher.php', 'OC\\App\\AppStore\\Fetcher\\CategoryFetcher' => $baseDir . '/lib/private/App/AppStore/Fetcher/CategoryFetcher.php',
'OC\\App\\AppStore\\Fetcher\\Fetcher' => $baseDir . '/lib/private/App/AppStore/Fetcher/Fetcher.php', 'OC\\App\\AppStore\\Fetcher\\Fetcher' => $baseDir . '/lib/private/App/AppStore/Fetcher/Fetcher.php',
@ -727,6 +733,7 @@ return array(
'OC\\Repair\\NC11\\FixMountStorages' => $baseDir . '/lib/private/Repair/NC11/FixMountStorages.php', 'OC\\Repair\\NC11\\FixMountStorages' => $baseDir . '/lib/private/Repair/NC11/FixMountStorages.php',
'OC\\Repair\\NC11\\MoveAvatars' => $baseDir . '/lib/private/Repair/NC11/MoveAvatars.php', 'OC\\Repair\\NC11\\MoveAvatars' => $baseDir . '/lib/private/Repair/NC11/MoveAvatars.php',
'OC\\Repair\\NC11\\MoveAvatarsBackgroundJob' => $baseDir . '/lib/private/Repair/NC11/MoveAvatarsBackgroundJob.php', 'OC\\Repair\\NC11\\MoveAvatarsBackgroundJob' => $baseDir . '/lib/private/Repair/NC11/MoveAvatarsBackgroundJob.php',
'OC\\Repair\\NC12\\InstallCoreBundle' => $baseDir . '/lib/private/Repair/NC12/InstallCoreBundle.php',
'OC\\Repair\\NC12\\UpdateLanguageCodes' => $baseDir . '/lib/private/Repair/NC12/UpdateLanguageCodes.php', 'OC\\Repair\\NC12\\UpdateLanguageCodes' => $baseDir . '/lib/private/Repair/NC12/UpdateLanguageCodes.php',
'OC\\Repair\\OldGroupMembershipShares' => $baseDir . '/lib/private/Repair/OldGroupMembershipShares.php', 'OC\\Repair\\OldGroupMembershipShares' => $baseDir . '/lib/private/Repair/OldGroupMembershipShares.php',
'OC\\Repair\\RemoveRootShares' => $baseDir . '/lib/private/Repair/RemoveRootShares.php', 'OC\\Repair\\RemoveRootShares' => $baseDir . '/lib/private/Repair/RemoveRootShares.php',

View File

@ -348,6 +348,12 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\AppFramework\\Utility\\TimeFactory' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Utility/TimeFactory.php', 'OC\\AppFramework\\Utility\\TimeFactory' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Utility/TimeFactory.php',
'OC\\AppHelper' => __DIR__ . '/../../..' . '/lib/private/AppHelper.php', 'OC\\AppHelper' => __DIR__ . '/../../..' . '/lib/private/AppHelper.php',
'OC\\App\\AppManager' => __DIR__ . '/../../..' . '/lib/private/App/AppManager.php', 'OC\\App\\AppManager' => __DIR__ . '/../../..' . '/lib/private/App/AppManager.php',
'OC\\App\\AppStore\\Bundles\\Bundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/Bundle.php',
'OC\\App\\AppStore\\Bundles\\BundleFetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/BundleFetcher.php',
'OC\\App\\AppStore\\Bundles\\CoreBundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/CoreBundle.php',
'OC\\App\\AppStore\\Bundles\\EnterpriseBundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/EnterpriseBundle.php',
'OC\\App\\AppStore\\Bundles\\GroupwareBundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/GroupwareBundle.php',
'OC\\App\\AppStore\\Bundles\\SocialSharingBundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/SocialSharingBundle.php',
'OC\\App\\AppStore\\Fetcher\\AppFetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Fetcher/AppFetcher.php', 'OC\\App\\AppStore\\Fetcher\\AppFetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Fetcher/AppFetcher.php',
'OC\\App\\AppStore\\Fetcher\\CategoryFetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Fetcher/CategoryFetcher.php', 'OC\\App\\AppStore\\Fetcher\\CategoryFetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Fetcher/CategoryFetcher.php',
'OC\\App\\AppStore\\Fetcher\\Fetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Fetcher/Fetcher.php', 'OC\\App\\AppStore\\Fetcher\\Fetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Fetcher/Fetcher.php',
@ -757,6 +763,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Repair\\NC11\\FixMountStorages' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/FixMountStorages.php', 'OC\\Repair\\NC11\\FixMountStorages' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/FixMountStorages.php',
'OC\\Repair\\NC11\\MoveAvatars' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/MoveAvatars.php', 'OC\\Repair\\NC11\\MoveAvatars' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/MoveAvatars.php',
'OC\\Repair\\NC11\\MoveAvatarsBackgroundJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/MoveAvatarsBackgroundJob.php', 'OC\\Repair\\NC11\\MoveAvatarsBackgroundJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/MoveAvatarsBackgroundJob.php',
'OC\\Repair\\NC12\\InstallCoreBundle' => __DIR__ . '/../../..' . '/lib/private/Repair/NC12/InstallCoreBundle.php',
'OC\\Repair\\NC12\\UpdateLanguageCodes' => __DIR__ . '/../../..' . '/lib/private/Repair/NC12/UpdateLanguageCodes.php', 'OC\\Repair\\NC12\\UpdateLanguageCodes' => __DIR__ . '/../../..' . '/lib/private/Repair/NC12/UpdateLanguageCodes.php',
'OC\\Repair\\OldGroupMembershipShares' => __DIR__ . '/../../..' . '/lib/private/Repair/OldGroupMembershipShares.php', 'OC\\Repair\\OldGroupMembershipShares' => __DIR__ . '/../../..' . '/lib/private/Repair/OldGroupMembershipShares.php',
'OC\\Repair\\RemoveRootShares' => __DIR__ . '/../../..' . '/lib/private/Repair/RemoveRootShares.php', 'OC\\Repair\\RemoveRootShares' => __DIR__ . '/../../..' . '/lib/private/Repair/RemoveRootShares.php',

View File

@ -0,0 +1,59 @@
<?php
/**
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\App\AppStore\Bundles;
use OCP\IL10N;
abstract class Bundle {
/** @var IL10N */
protected $l10n;
/**
* @param IL10N $l10n
*/
public function __construct(IL10N $l10n) {
$this->l10n = $l10n;
}
/**
* Get the identifier of the bundle
*
* @return string
*/
public final function getIdentifier() {
return substr(strrchr(get_class($this), '\\'), 1);
}
/**
* Get the name of the bundle
*
* @return string
*/
public abstract function getName();
/**
* Get the list of app identifiers in the bundle
*
* @return array
*/
public abstract function getAppIdentifiers();
}

View File

@ -0,0 +1,80 @@
<?php
/**
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\App\AppStore\Bundles;
use OCP\IL10N;
class BundleFetcher {
/** @var IL10N */
private $l10n;
/**
* @param IL10N $l10n
*/
public function __construct(IL10N $l10n) {
$this->l10n = $l10n;
}
/**
* @return Bundle[]
*/
public function getBundles() {
return [
new EnterpriseBundle($this->l10n),
new GroupwareBundle($this->l10n),
new SocialSharingBundle($this->l10n),
];
}
/**
* Bundles that should be installed by default after installation
*
* @return Bundle[]
*/
public function getDefaultInstallationBundle() {
return [
new CoreBundle($this->l10n),
];
}
/**
* Get the bundle with the specified identifier
*
* @param string $identifier
* @return Bundle
* @throws \BadMethodCallException If the bundle does not exist
*/
public function getBundleByIdentifier($identifier) {
/** @var Bundle[] $bundles */
$bundles = array_merge(
$this->getBundles(),
$this->getDefaultInstallationBundle()
);
foreach($bundles as $bundle) {
if($bundle->getIdentifier() === $identifier) {
return $bundle;
}
}
throw new \BadMethodCallException('Bundle with specified identifier does not exist');
}
}

View File

@ -0,0 +1,42 @@
<?php
/**
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\App\AppStore\Bundles;
class CoreBundle extends Bundle {
/**
* {@inheritDoc}
*/
public function getName() {
return 'Core bundle';
}
/**
* {@inheritDoc}
*/
public function getAppIdentifiers() {
return [
'bruteforcesettings',
];
}
}

View File

@ -0,0 +1,47 @@
<?php
/**
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\App\AppStore\Bundles;
class EnterpriseBundle extends Bundle {
/**
* {@inheritDoc}
*/
public function getName() {
return (string)$this->l10n->t('Enterprise bundle');
}
/**
* {@inheritDoc}
*/
public function getAppIdentifiers() {
return [
'admin_audit',
'user_ldap',
'files_retention',
'files_automatedtagging',
'user_saml',
'files_accesscontrol',
];
}
}

View File

@ -0,0 +1,44 @@
<?php
/**
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\App\AppStore\Bundles;
class GroupwareBundle extends Bundle {
/**
* {@inheritDoc}
*/
public function getName() {
return (string)$this->l10n->t('Groupware bundle');
}
/**
* {@inheritDoc}
*/
public function getAppIdentifiers() {
return [
'calendar',
'contacts',
'spreed',
];
}
}

View File

@ -0,0 +1,46 @@
<?php
/**
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\App\AppStore\Bundles;
class SocialSharingBundle extends Bundle {
/**
* {@inheritDoc}
*/
public function getName() {
return (string)$this->l10n->t('Social sharing bundle');
}
/**
* {@inheritDoc}
*/
public function getAppIdentifiers() {
return [
'socialsharing_twitter',
'socialsharing_googleplus',
'socialsharing_facebook',
'socialsharing_email',
'socialsharing_diaspora',
];
}
}

View File

@ -42,6 +42,8 @@
namespace OC; namespace OC;
use Doctrine\DBAL\Exception\TableExistsException; use Doctrine\DBAL\Exception\TableExistsException;
use OC\App\AppManager;
use OC\App\AppStore\Bundles\Bundle;
use OC\App\AppStore\Fetcher\AppFetcher; use OC\App\AppStore\Fetcher\AppFetcher;
use OC\App\CodeChecker\CodeChecker; use OC\App\CodeChecker\CodeChecker;
use OC\App\CodeChecker\EmptyCheck; use OC\App\CodeChecker\EmptyCheck;
@ -50,7 +52,9 @@ use OC\Archive\TAR;
use OC_App; use OC_App;
use OC_DB; use OC_DB;
use OC_Helper; use OC_Helper;
use OCP\App\IAppManager;
use OCP\Http\Client\IClientService; use OCP\Http\Client\IClientService;
use OCP\IConfig;
use OCP\ILogger; use OCP\ILogger;
use OCP\ITempManager; use OCP\ITempManager;
use phpseclib\File\X509; use phpseclib\File\X509;
@ -67,21 +71,26 @@ class Installer {
private $tempManager; private $tempManager;
/** @var ILogger */ /** @var ILogger */
private $logger; private $logger;
/** @var IConfig */
private $config;
/** /**
* @param AppFetcher $appFetcher * @param AppFetcher $appFetcher
* @param IClientService $clientService * @param IClientService $clientService
* @param ITempManager $tempManager * @param ITempManager $tempManager
* @param ILogger $logger * @param ILogger $logger
* @param IConfig $config
*/ */
public function __construct(AppFetcher $appFetcher, public function __construct(AppFetcher $appFetcher,
IClientService $clientService, IClientService $clientService,
ITempManager $tempManager, ITempManager $tempManager,
ILogger $logger) { ILogger $logger,
IConfig $config) {
$this->appFetcher = $appFetcher; $this->appFetcher = $appFetcher;
$this->clientService = $clientService; $this->clientService = $clientService;
$this->tempManager = $tempManager; $this->tempManager = $tempManager;
$this->logger = $logger; $this->logger = $logger;
$this->config = $config;
} }
/** /**
@ -109,6 +118,7 @@ class Installer {
} }
} }
\OC_App::registerAutoloading($appId, $basedir);
\OC_App::setupBackgroundJobs($info['background-jobs']); \OC_App::setupBackgroundJobs($info['background-jobs']);
//run appinfo/install.php //run appinfo/install.php
@ -419,6 +429,27 @@ class Installer {
} }
/**
* Installs the app within the bundle and marks the bundle as installed
*
* @param Bundle $bundle
* @throws \Exception If app could not get installed
*/
public function installAppBundle(Bundle $bundle) {
$appIds = $bundle->getAppIdentifiers();
foreach($appIds as $appId) {
if(!$this->isDownloaded($appId)) {
$this->downloadApp($appId);
}
$this->installApp($appId);
$app = new OC_App();
$app->enable($appId);
}
$bundles = json_decode($this->config->getAppValue('core', 'installed.bundles', json_encode([])), true);
$bundles[] = $bundle->getIdentifier();
$this->config->setAppValue('core', 'installed.bundles', json_encode($bundles));
}
/** /**
* Installs shipped apps * Installs shipped apps
* *

View File

@ -30,12 +30,14 @@
namespace OC; namespace OC;
use OC\App\AppStore\Bundles\BundleFetcher;
use OC\Repair\CleanTags; use OC\Repair\CleanTags;
use OC\Repair\Collation; use OC\Repair\Collation;
use OC\Repair\MoveUpdaterStepFile; use OC\Repair\MoveUpdaterStepFile;
use OC\Repair\NC11\CleanPreviews; use OC\Repair\NC11\CleanPreviews;
use OC\Repair\NC11\FixMountStorages; use OC\Repair\NC11\FixMountStorages;
use OC\Repair\NC11\MoveAvatars; use OC\Repair\NC11\MoveAvatars;
use OC\Repair\NC12\InstallCoreBundle;
use OC\Repair\NC12\UpdateLanguageCodes; use OC\Repair\NC12\UpdateLanguageCodes;
use OC\Repair\OldGroupMembershipShares; use OC\Repair\OldGroupMembershipShares;
use OC\Repair\RemoveRootShares; use OC\Repair\RemoveRootShares;
@ -136,6 +138,11 @@ class Repair implements IOutput{
), ),
new FixMountStorages(\OC::$server->getDatabaseConnection()), new FixMountStorages(\OC::$server->getDatabaseConnection()),
new UpdateLanguageCodes(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()), new UpdateLanguageCodes(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()),
new InstallCoreBundle(
\OC::$server->query(BundleFetcher::class),
\OC::$server->getConfig(),
\OC::$server->query(Installer::class)
)
]; ];
} }

View File

@ -0,0 +1,78 @@
<?php
/**
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\Repair\NC12;
use OC\App\AppStore\Bundles\BundleFetcher;
use OC\Installer;
use OCP\IConfig;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;
class InstallCoreBundle implements IRepairStep {
/** @var BundleFetcher */
private $bundleFetcher;
/** @var IConfig */
private $config;
/** @var Installer */
private $installer;
/**
* @param BundleFetcher $bundleFetcher
* @param IConfig $config
* @param Installer $installer
*/
public function __construct(BundleFetcher $bundleFetcher,
IConfig $config,
Installer $installer) {
$this->bundleFetcher = $bundleFetcher;
$this->config = $config;
$this->installer = $installer;
}
/**
* {@inheritdoc}
*/
public function getName() {
return 'Install new core bundle components';
}
/**
* {@inheritdoc}
*/
public function run(IOutput $output) {
$versionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0');
if (version_compare($versionFromBeforeUpdate, '12.0.0.14', '>')) {
return;
}
$defaultBundle = $this->bundleFetcher->getDefaultInstallationBundle();
foreach($defaultBundle as $bundle) {
try {
$this->installer->installAppBundle($bundle);
$output->info('Successfully installed core app bundle.');
} catch (\Exception $e) {
$output->warning('Could not install core app bundle: ' . $e->getMessage());
}
}
}
}

View File

@ -43,6 +43,7 @@ namespace OC;
use bantu\IniGetWrapper\IniGetWrapper; use bantu\IniGetWrapper\IniGetWrapper;
use OC\App\AppManager; use OC\App\AppManager;
use OC\App\AppStore\Bundles\BundleFetcher;
use OC\App\AppStore\Fetcher\AppFetcher; use OC\App\AppStore\Fetcher\AppFetcher;
use OC\App\AppStore\Fetcher\CategoryFetcher; use OC\App\AppStore\Fetcher\CategoryFetcher;
use OC\AppFramework\Http\Request; use OC\AppFramework\Http\Request;
@ -816,7 +817,12 @@ class Server extends ServerContainer implements IServerContainer {
); );
}); });
$this->registerAlias('MimeTypeLoader', \OCP\Files\IMimeTypeLoader::class); $this->registerAlias('MimeTypeLoader', \OCP\Files\IMimeTypeLoader::class);
$this->registerService(BundleFetcher::class, function () {
return new BundleFetcher($this->getL10N('lib'));
});
$this->registerService(AppFetcher::class, function() {
return $this->getAppFetcher();
});
$this->registerService(\OCP\Notification\IManager::class, function (Server $c) { $this->registerService(\OCP\Notification\IManager::class, function (Server $c) {
return new Manager( return new Manager(
$c->query(IValidator::class) $c->query(IValidator::class)

View File

@ -41,6 +41,7 @@ namespace OC;
use bantu\IniGetWrapper\IniGetWrapper; use bantu\IniGetWrapper\IniGetWrapper;
use Exception; use Exception;
use OC\App\AppStore\Bundles\BundleFetcher;
use OCP\Defaults; use OCP\Defaults;
use OCP\IL10N; use OCP\IL10N;
use OCP\ILogger; use OCP\ILogger;
@ -63,11 +64,12 @@ class Setup {
/** /**
* @param SystemConfig $config * @param SystemConfig $config
* @param IniGetWrapper $iniWrapper * @param IniGetWrapper $iniWrapper
* @param IL10N $l10n
* @param Defaults $defaults * @param Defaults $defaults
* @param ILogger $logger * @param ILogger $logger
* @param ISecureRandom $random * @param ISecureRandom $random
*/ */
function __construct(SystemConfig $config, public function __construct(SystemConfig $config,
IniGetWrapper $iniWrapper, IniGetWrapper $iniWrapper,
IL10N $l10n, IL10N $l10n,
Defaults $defaults, Defaults $defaults,
@ -364,8 +366,22 @@ class Setup {
$group =\OC::$server->getGroupManager()->createGroup('admin'); $group =\OC::$server->getGroupManager()->createGroup('admin');
$group->addUser($user); $group->addUser($user);
//guess what this does // Install shipped apps and specified app bundles
Installer::installShippedApps(); Installer::installShippedApps();
$installer = new Installer(
\OC::$server->getAppFetcher(),
\OC::$server->getHTTPClientService(),
\OC::$server->getTempManager(),
\OC::$server->getLogger(),
\OC::$server->getConfig()
);
$bundleFetcher = new BundleFetcher(\OC::$server->getL10N('lib'));
$defaultInstallationBundles = $bundleFetcher->getDefaultInstallationBundle();
foreach($defaultInstallationBundles as $bundle) {
try {
$installer->installAppBundle($bundle);
} catch (Exception $e) {}
}
// create empty file in data dir, so we can later find // create empty file in data dir, so we can later find
// out that this is indeed an ownCloud data directory // out that this is indeed an ownCloud data directory

View File

@ -243,11 +243,11 @@ class Updater extends BasicEmitter {
} }
// update all shipped apps // update all shipped apps
$disabledApps = $this->checkAppsRequirements(); $this->checkAppsRequirements();
$this->doAppUpgrade(); $this->doAppUpgrade();
// upgrade appstore apps // upgrade appstore apps
$this->upgradeAppStoreApps($disabledApps); $this->upgradeAppStoreApps(\OC::$server->getAppManager()->getInstalledApps());
// install new shipped apps on upgrade // install new shipped apps on upgrade
OC_App::loadApps('authentication'); OC_App::loadApps('authentication');
@ -441,7 +441,8 @@ class Updater extends BasicEmitter {
\OC::$server->getAppFetcher(), \OC::$server->getAppFetcher(),
\OC::$server->getHTTPClientService(), \OC::$server->getHTTPClientService(),
\OC::$server->getTempManager(), \OC::$server->getTempManager(),
$this->log $this->log,
\OC::$server->getConfig()
); );
if (Installer::isUpdateAvailable($app, \OC::$server->getAppFetcher())) { if (Installer::isUpdateAvailable($app, \OC::$server->getAppFetcher())) {
$this->emit('\OC\Updater', 'upgradeAppStoreApp', [$app]); $this->emit('\OC\Updater', 'upgradeAppStoreApp', [$app]);

View File

@ -365,7 +365,8 @@ class OC_App {
\OC::$server->getAppFetcher(), \OC::$server->getAppFetcher(),
\OC::$server->getHTTPClientService(), \OC::$server->getHTTPClientService(),
\OC::$server->getTempManager(), \OC::$server->getTempManager(),
\OC::$server->getLogger() \OC::$server->getLogger(),
\OC::$server->getConfig()
); );
$isDownloaded = $installer->isDownloaded($appId); $isDownloaded = $installer->isDownloaded($appId);
@ -427,7 +428,8 @@ class OC_App {
\OC::$server->getAppFetcher(), \OC::$server->getAppFetcher(),
\OC::$server->getHTTPClientService(), \OC::$server->getHTTPClientService(),
\OC::$server->getTempManager(), \OC::$server->getTempManager(),
\OC::$server->getLogger() \OC::$server->getLogger(),
\OC::$server->getConfig()
); );
return $installer->removeApp($app); return $installer->removeApp($app);
} }

View File

@ -27,6 +27,7 @@
namespace OC\Settings\Controller; namespace OC\Settings\Controller;
use OC\App\AppStore\Bundles\BundleFetcher;
use OC\App\AppStore\Fetcher\AppFetcher; use OC\App\AppStore\Fetcher\AppFetcher;
use OC\App\AppStore\Fetcher\CategoryFetcher; use OC\App\AppStore\Fetcher\CategoryFetcher;
use OC\App\AppStore\Version\VersionParser; use OC\App\AppStore\Version\VersionParser;
@ -50,6 +51,7 @@ class AppSettingsController extends Controller {
const CAT_ENABLED = 0; const CAT_ENABLED = 0;
const CAT_DISABLED = 1; const CAT_DISABLED = 1;
const CAT_ALL_INSTALLED = 2; const CAT_ALL_INSTALLED = 2;
const CAT_APP_BUNDLES = 3;
/** @var \OCP\IL10N */ /** @var \OCP\IL10N */
private $l10n; private $l10n;
@ -65,6 +67,8 @@ class AppSettingsController extends Controller {
private $appFetcher; private $appFetcher;
/** @var IFactory */ /** @var IFactory */
private $l10nFactory; private $l10nFactory;
/** @var BundleFetcher */
private $bundleFetcher;
/** /**
* @param string $appName * @param string $appName
@ -76,6 +80,7 @@ class AppSettingsController extends Controller {
* @param CategoryFetcher $categoryFetcher * @param CategoryFetcher $categoryFetcher
* @param AppFetcher $appFetcher * @param AppFetcher $appFetcher
* @param IFactory $l10nFactory * @param IFactory $l10nFactory
* @param BundleFetcher $bundleFetcher
*/ */
public function __construct($appName, public function __construct($appName,
IRequest $request, IRequest $request,
@ -85,7 +90,8 @@ class AppSettingsController extends Controller {
IAppManager $appManager, IAppManager $appManager,
CategoryFetcher $categoryFetcher, CategoryFetcher $categoryFetcher,
AppFetcher $appFetcher, AppFetcher $appFetcher,
IFactory $l10nFactory) { IFactory $l10nFactory,
BundleFetcher $bundleFetcher) {
parent::__construct($appName, $request); parent::__construct($appName, $request);
$this->l10n = $l10n; $this->l10n = $l10n;
$this->config = $config; $this->config = $config;
@ -94,6 +100,7 @@ class AppSettingsController extends Controller {
$this->categoryFetcher = $categoryFetcher; $this->categoryFetcher = $categoryFetcher;
$this->appFetcher = $appFetcher; $this->appFetcher = $appFetcher;
$this->l10nFactory = $l10nFactory; $this->l10nFactory = $l10nFactory;
$this->bundleFetcher = $bundleFetcher;
} }
/** /**
@ -120,18 +127,14 @@ class AppSettingsController extends Controller {
return $templateResponse; return $templateResponse;
} }
/** private function getAllCategories() {
* Get all available categories
*
* @return JSONResponse
*/
public function listCategories() {
$currentLanguage = substr($this->l10nFactory->findLanguage(), 0, 2); $currentLanguage = substr($this->l10nFactory->findLanguage(), 0, 2);
$formattedCategories = [ $formattedCategories = [
['id' => self::CAT_ALL_INSTALLED, 'ident' => 'installed', 'displayName' => (string)$this->l10n->t('Your apps')], ['id' => self::CAT_ALL_INSTALLED, 'ident' => 'installed', 'displayName' => (string)$this->l10n->t('Your apps')],
['id' => self::CAT_ENABLED, 'ident' => 'enabled', 'displayName' => (string)$this->l10n->t('Enabled apps')], ['id' => self::CAT_ENABLED, 'ident' => 'enabled', 'displayName' => (string)$this->l10n->t('Enabled apps')],
['id' => self::CAT_DISABLED, 'ident' => 'disabled', 'displayName' => (string)$this->l10n->t('Disabled apps')], ['id' => self::CAT_DISABLED, 'ident' => 'disabled', 'displayName' => (string)$this->l10n->t('Disabled apps')],
['id' => self::CAT_APP_BUNDLES, 'ident' => 'app-bundles', 'displayName' => (string)$this->l10n->t('App bundles')],
]; ];
$categories = $this->categoryFetcher->get(); $categories = $this->categoryFetcher->get();
foreach($categories as $category) { foreach($categories as $category) {
@ -142,7 +145,16 @@ class AppSettingsController extends Controller {
]; ];
} }
return new JSONResponse($formattedCategories); return $formattedCategories;
}
/**
* Get all available categories
*
* @return JSONResponse
*/
public function listCategories() {
return new JSONResponse($this->getAllCategories());
} }
/** /**
@ -334,6 +346,41 @@ class AppSettingsController extends Controller {
return ($a < $b) ? -1 : 1; return ($a < $b) ? -1 : 1;
}); });
break; break;
case 'app-bundles':
$bundles = $this->bundleFetcher->getBundles();
$apps = [];
foreach($bundles as $bundle) {
$newCategory = true;
$allApps = $appClass->listAllApps();
$categories = $this->getAllCategories();
foreach($categories as $singleCategory) {
$newApps = $this->getAppsForCategory($singleCategory['id']);
foreach($allApps as $app) {
foreach($newApps as $key => $newApp) {
if($app['id'] === $newApp['id']) {
unset($newApps[$key]);
}
}
}
$allApps = array_merge($allApps, $newApps);
}
foreach($bundle->getAppIdentifiers() as $identifier) {
foreach($allApps as $app) {
if($app['id'] === $identifier) {
if($newCategory) {
$app['newCategory'] = true;
$app['categoryName'] = $bundle->getName();
}
$app['bundleId'] = $bundle->getIdentifier();
$newCategory = false;
$apps[] = $app;
continue;
}
}
}
}
break;
default: default:
$apps = $this->getAppsForCategory($category); $apps = $this->getAppsForCategory($category);

View File

@ -36,8 +36,9 @@ if (!array_key_exists('appid', $_POST)) {
exit; exit;
} }
$appId = (string)$_POST['appid']; $appIds = (array)$_POST['appid'];
$appId = OC_App::cleanAppId($appId); foreach($appIds as $appId) {
$appId = OC_App::cleanAppId($appId);
OC_App::disable($appId); OC_App::disable($appId);
}
OC_JSON::success(); OC_JSON::success();

View File

@ -36,13 +36,20 @@ if ($lastConfirm < (time() - 30 * 60 + 15)) { // allow 15 seconds delay
} }
$groups = isset($_POST['groups']) ? (array)$_POST['groups'] : null; $groups = isset($_POST['groups']) ? (array)$_POST['groups'] : null;
$appIds = isset($_POST['appIds']) ? (array)$_POST['appIds'] : [];
try { try {
$app = new OC_App(); $updateRequired = false;
$appId = (string)$_POST['appid']; foreach($appIds as $appId) {
$appId = OC_App::cleanAppId($appId); $app = new OC_App();
$app->enable($appId, $groups); $appId = OC_App::cleanAppId($appId);
OC_JSON::success(['data' => ['update_required' => \OC_App::shouldUpgrade($appId)]]); $app->enable($appId, $groups);
if(\OC_App::shouldUpgrade($appId)) {
$updateRequired = true;
}
}
OC_JSON::success(['data' => ['update_required' => $updateRequired]]);
} catch (Exception $e) { } catch (Exception $e) {
\OCP\Util::writeLog('core', $e->getMessage(), \OCP\Util::ERROR); \OCP\Util::writeLog('core', $e->getMessage(), \OCP\Util::ERROR);
OC_JSON::error(array("data" => array("message" => $e->getMessage()) )); OC_JSON::error(array("data" => array("message" => $e->getMessage()) ));

View File

@ -44,7 +44,8 @@ try {
\OC::$server->getAppFetcher(), \OC::$server->getAppFetcher(),
\OC::$server->getHTTPClientService(), \OC::$server->getHTTPClientService(),
\OC::$server->getTempManager(), \OC::$server->getTempManager(),
\OC::$server->getLogger() \OC::$server->getLogger(),
\OC::$server->getConfig()
); );
$result = $installer->updateAppstoreApp($appId); $result = $installer->updateAppstoreApp($appId);
$config->setSystemValue('maintenance', false); $config->setSystemValue('maintenance', false);

View File

@ -519,13 +519,37 @@ input.userFilter {width: 200px;}
/* APPS */ /* APPS */
/* Bundle header */
#apps-list .apps-header {
display: table-row;
position: relative;
}
#apps-list .apps-header div {
display: table-cell;
height: 70px;
}
#apps-list .apps-header h2 {
display: table-cell;
position: absolute;
padding-left: 6px;
padding-top: 15px;
}
#apps-list .apps-header h2 .enable {
position: relative;
top: -1px;
margin-left: 12px;
}
#apps-list .apps-header h2 + .section {
margin-top: 50px;
}
#app-content > svg.app-filter { #app-content > svg.app-filter {
float: left; float: left;
height: 0; height: 0;
width: 0; width: 0;
} }
#app-category-disabled { #app-category-app-bundles {
margin-bottom: 20px; margin-bottom: 20px;
} }
@ -558,6 +582,10 @@ span.version {
border-radius: 3px; border-radius: 3px;
padding: 3px 6px; padding: 3px 6px;
} }
.app-level a {
padding: 10px;
white-space: nowrap;
}
.app-level .official { .app-level .official {
border-color: #37ce02; border-color: #37ce02;
background-position: left center; background-position: left center;
@ -737,6 +765,7 @@ form.section {
display: table; display: table;
width: 100%; width: 100%;
height: auto; height: auto;
margin-bottom: 100px;
} }
#apps-list.installed .section { #apps-list.installed .section {

View File

@ -29,6 +29,7 @@ OC.Settings.Apps = OC.Settings.Apps || {
State: { State: {
currentCategory: null, currentCategory: null,
currentCategoryElements: null,
apps: null, apps: null,
$updateNotification: null, $updateNotification: null,
availableUpdates: 0 availableUpdates: 0
@ -90,14 +91,15 @@ OC.Settings.Apps = OC.Settings.Apps || {
}), { }), {
type:'GET', type:'GET',
success: function (apps) { success: function (apps) {
OC.Settings.Apps.State.currentCategoryElements = apps.apps;
var appListWithIndex = _.indexBy(apps.apps, 'id'); var appListWithIndex = _.indexBy(apps.apps, 'id');
OC.Settings.Apps.State.apps = appListWithIndex; OC.Settings.Apps.State.apps = appListWithIndex;
var appList = _.map(appListWithIndex, function(app) { var appList = _.map(appListWithIndex, function(app) {
// default values for missing fields // default values for missing fields
return _.extend({level: 0}, app); return _.extend({level: 0}, app);
}); });
var source var source;
if (categoryId === 'enabled' || categoryId === 'disabled' || categoryId === 'installed') { if (categoryId === 'enabled' || categoryId === 'disabled' || categoryId === 'installed' || categoryId === 'app-bundles') {
source = $("#app-template-installed").html(); source = $("#app-template-installed").html();
$('#apps-list').addClass('installed'); $('#apps-list').addClass('installed');
} else { } else {
@ -107,17 +109,19 @@ OC.Settings.Apps = OC.Settings.Apps || {
var template = Handlebars.compile(source); var template = Handlebars.compile(source);
if (appList.length) { if (appList.length) {
appList.sort(function(a,b) { if(categoryId !== 'app-bundles') {
if (a.active !== b.active) { appList.sort(function (a, b) {
return (a.active ? -1 : 1) if (a.active !== b.active) {
} else { return (a.active ? -1 : 1)
var levelDiff = b.level - a.level; } else {
if (levelDiff === 0) { var levelDiff = b.level - a.level;
return OC.Util.naturalSortCompare(a.name, b.name); if (levelDiff === 0) {
return OC.Util.naturalSortCompare(a.name, b.name);
}
return levelDiff;
} }
return levelDiff; });
} }
});
var firstExperimental = false; var firstExperimental = false;
_.each(appList, function(app) { _.each(appList, function(app) {
@ -303,56 +307,126 @@ OC.Settings.Apps = OC.Settings.Apps || {
return $.get(OC.generateUrl('apps/files')); return $.get(OC.generateUrl('apps/files'));
}, },
enableApp:function(appId, active, element, groups) { enableAppBundle:function(bundleId, active, element, groups) {
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) { if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.enableApp, this, appId, active, element, groups)); OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.enableAppBundle, this, bundleId, active, element, groups));
return; return;
} }
var apps = OC.Settings.Apps.State.currentCategoryElements;
var appsToEnable = [];
apps.forEach(function(app) {
if(app['bundleId'] === bundleId) {
if(app['active'] === false) {
appsToEnable.push(app['id']);
}
}
});
OC.Settings.Apps.enableApp(appsToEnable, false, groups);
},
/**
* @param {string[]} appId
* @param {boolean} active
* @param {array} groups
*/
enableApp:function(appId, active, groups) {
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.enableApp, this, appId, active, groups));
return;
}
var elements = [];
appId.forEach(function(appId) {
elements.push($('#app-'+appId+' .enable'));
});
var self = this; var self = this;
OC.Settings.Apps.hideErrorMessage(appId); appId.forEach(function(appId) {
OC.Settings.Apps.hideErrorMessage(appId);
});
groups = groups || []; groups = groups || [];
var appItem = $('div#app-'+appId+''); var appItems = [];
appId.forEach(function(appId) {
appItems.push($('div#app-'+appId+''));
});
if(active && !groups.length) { if(active && !groups.length) {
element.val(t('settings','Disabling app …')); elements.forEach(function(element) {
element.val(t('settings','Disabling app …'));
});
$.post(OC.filePath('settings','ajax','disableapp.php'),{appid:appId},function(result) { $.post(OC.filePath('settings','ajax','disableapp.php'),{appid:appId},function(result) {
if(!result || result.status !== 'success') { if(!result || result.status !== 'success') {
if (result.data && result.data.message) { if (result.data && result.data.message) {
OC.Settings.Apps.showErrorMessage(appId, result.data.message); OC.Settings.Apps.showErrorMessage(appId, result.data.message);
appItem.data('errormsg', result.data.message); appItems.forEach(function(appItem) {
appItem.data('errormsg', result.data.message);
})
} else { } else {
OC.Settings.Apps.showErrorMessage(appId, t('settings', 'Error while disabling app')); OC.Settings.Apps.showErrorMessage(appId, t('settings', 'Error while disabling app'));
appItem.data('errormsg', t('settings', 'Error while disabling app')); appItems.forEach(function(appItem) {
appItem.data('errormsg', t('settings', 'Error while disabling app'));
});
} }
element.val(t('settings','Disable')); elements.forEach(function(element) {
appItem.addClass('appwarning'); element.val(t('settings','Disable'));
});
appItems.forEach(function(appItem) {
appItem.addClass('appwarning');
});
} else { } else {
OC.Settings.Apps.rebuildNavigation(); OC.Settings.Apps.rebuildNavigation();
appItem.data('active',false); appItems.forEach(function(appItem) {
appItem.data('groups', ''); appItem.data('active', false);
element.data('active',false); appItem.data('groups', '');
appItem.removeClass('active'); });
element.val(t('settings','Enable')); elements.forEach(function(element) {
element.parent().find(".groups-enable").hide(); element.data('active', false);
element.parent().find('#group_select').hide().val(null); });
appItems.forEach(function(appItem) {
appItem.removeClass('active');
});
elements.forEach(function(element) {
element.val(t('settings', 'Enable'));
element.parent().find(".groups-enable").hide();
element.parent().find('#group_select').hide().val(null);
});
OC.Settings.Apps.State.apps[appId].active = false; OC.Settings.Apps.State.apps[appId].active = false;
} }
},'json'); },'json');
} else { } else {
// TODO: display message to admin to not refresh the page! // TODO: display message to admin to not refresh the page!
// TODO: lock UI to prevent further operations // TODO: lock UI to prevent further operations
element.val(t('settings','Enabling app …')); elements.forEach(function(element) {
$.post(OC.filePath('settings','ajax','enableapp.php'),{appid: appId, groups: groups},function(result) { element.val(t('settings', 'Enabling app …'));
});
var appIdArray = [];
if( typeof appId === 'string' ) {
appIdArray = [appId];
} else {
appIdArray = appId;
}
$.post(OC.filePath('settings','ajax','enableapp.php'),{appIds: appIdArray, groups: groups},function(result) {
if(!result || result.status !== 'success') { if(!result || result.status !== 'success') {
if (result.data && result.data.message) { if (result.data && result.data.message) {
OC.Settings.Apps.showErrorMessage(appId, result.data.message); OC.Settings.Apps.showErrorMessage(appId, result.data.message);
appItem.data('errormsg', result.data.message); appItems.forEach(function(appItem) {
appItem.data('errormsg', result.data.message);
});
} else { } else {
OC.Settings.Apps.showErrorMessage(appId, t('settings', 'Error while enabling app')); OC.Settings.Apps.showErrorMessage(appId, t('settings', 'Error while enabling app'));
appItem.data('errormsg', t('settings', 'Error while disabling app')); appItems.forEach(function(appItem) {
appItem.data('errormsg', t('settings', 'Error while disabling app'));
});
} }
element.val(t('settings','Enable')); elements.forEach(function(element) {
appItem.addClass('appwarning'); element.val(t('settings', 'Enable'));
});
appItems.forEach(function(appItem) {
appItem.addClass('appwarning');
});
} else { } else {
self._checkServerHealth().done(function() { self._checkServerHealth().done(function() {
if (result.data.update_required) { if (result.data.update_required) {
@ -364,24 +438,40 @@ OC.Settings.Apps = OC.Settings.Apps || {
} }
OC.Settings.Apps.rebuildNavigation(); OC.Settings.Apps.rebuildNavigation();
appItem.data('active',true); appItems.forEach(function(appItem) {
element.data('active',true); appItem.data('active', true);
appItem.addClass('active'); });
element.val(t('settings','Disable')); elements.forEach(function(element) {
element.data('active', true);
});
appItems.forEach(function(appItem) {
appItem.addClass('active');
});
elements.forEach(function(element) {
element.val(t('settings', 'Disable'));
});
var app = OC.Settings.Apps.State.apps[appId]; var app = OC.Settings.Apps.State.apps[appId];
app.active = true; app.active = true;
if (OC.Settings.Apps.isType(app, 'filesystem') || OC.Settings.Apps.isType(app, 'prelogin') || if (OC.Settings.Apps.isType(app, 'filesystem') || OC.Settings.Apps.isType(app, 'prelogin') ||
OC.Settings.Apps.isType(app, 'authentication') || OC.Settings.Apps.isType(app, 'logging')) { OC.Settings.Apps.isType(app, 'authentication') || OC.Settings.Apps.isType(app, 'logging')) {
element.parent().find(".groups-enable").prop('checked', true); elements.forEach(function(element) {
element.parent().find(".groups-enable").hide(); element.parent().find(".groups-enable").prop('checked', true);
element.parent().find('#group_select').hide().val(null); element.parent().find(".groups-enable").hide();
element.parent().find('#group_select').hide().val(null);
});
} else { } else {
element.parent().find("#groups-enable").show(); elements.forEach(function(element) {
element.parent().find("#groups-enable").show();
});
if (groups) { if (groups) {
appItem.data('groups', JSON.stringify(groups)); appItems.forEach(function(appItem) {
appItem.data('groups', JSON.stringify(groups));
});
} else { } else {
appItem.data('groups', ''); appItems.forEach(function(appItem) {
appItem.data('groups', '');
});
} }
} }
}).fail(function() { }).fail(function() {
@ -391,26 +481,40 @@ OC.Settings.Apps = OC.Settings.Apps || {
appId, appId,
t('settings', 'Error: this app cannot be enabled because it makes the server unstable') t('settings', 'Error: this app cannot be enabled because it makes the server unstable')
); );
appItem.data('errormsg', t('settings', 'Error while enabling app')); appItems.forEach(function(appItem) {
element.val(t('settings','Enable')); appItem.data('errormsg', t('settings', 'Error while enabling app'));
appItem.addClass('appwarning'); });
elements.forEach(function(element) {
element.val(t('settings', 'Enable'));
});
appItems.forEach(function(appItem) {
appItem.addClass('appwarning');
});
}).fail(function() { }).fail(function() {
OC.Settings.Apps.showErrorMessage( OC.Settings.Apps.showErrorMessage(
appId, appId,
t('settings', 'Error: could not disable broken app') t('settings', 'Error: could not disable broken app')
); );
appItem.data('errormsg', t('settings', 'Error while disabling broken app')); appItems.forEach(function(appItem) {
element.val(t('settings','Enable')); appItem.data('errormsg', t('settings', 'Error while disabling broken app'));
});
elements.forEach(function(element) {
element.val(t('settings', 'Enable'));
});
}); });
}); });
} }
},'json') },'json')
.fail(function() { .fail(function() {
OC.Settings.Apps.showErrorMessage(appId, t('settings', 'Error while enabling app')); OC.Settings.Apps.showErrorMessage(appId, t('settings', 'Error while enabling app'));
appItem.data('errormsg', t('settings', 'Error while enabling app')); appItems.forEach(function(appItem) {
appItem.data('active',false); appItem.data('errormsg', t('settings', 'Error while enabling app'));
appItem.addClass('appwarning'); appItem.data('active', false);
element.val(t('settings','Enable')); appItem.addClass('appwarning');
});
elements.forEach(function(element) {
element.val(t('settings', 'Enable'));
});
}); });
} }
}, },
@ -774,10 +878,17 @@ OC.Settings.Apps = OC.Settings.Apps || {
$(document).on('click', '#apps-list input.enable', function () { $(document).on('click', '#apps-list input.enable', function () {
var appId = $(this).data('appid'); var appId = $(this).data('appid');
var bundleId = $(this).data('bundleid');
var element = $(this); var element = $(this);
var active = $(this).data('active'); var active = $(this).data('active');
OC.Settings.Apps.enableApp(appId, active, element); var category = $('#app-navigation').attr('data-category');
if(bundleId) {
OC.Settings.Apps.enableAppBundle(bundleId, active, element);
element.val(t('settings', 'Enable all'));
} else {
OC.Settings.Apps.enableApp([appId], active);
}
}); });
$(document).on('click', '#apps-list input.uninstall', function () { $(document).on('click', '#apps-list input.uninstall', function () {
@ -805,7 +916,7 @@ OC.Settings.Apps = OC.Settings.Apps || {
var appId = element.data('appid'); var appId = element.data('appid');
if (appId) { if (appId) {
OC.Settings.Apps.enableApp(appId, false, element, groups); OC.Settings.Apps.enableApp([appId], false, groups);
OC.Settings.Apps.State.apps[appId].groups = groups; OC.Settings.Apps.State.apps[appId].groups = groups;
} }
}); });

View File

@ -29,8 +29,17 @@ script(
<?php endif; ?> <?php endif; ?>
</script> </script>
<script id="app-template-installed" type="text/x-handlebars"> <script id="app-template-installed" type="text/x-handlebars">
{{#if newCategory}}
<div class="apps-header">
<div class="app-image"></div>
<h2>{{categoryName}} <input class="enable" type="submit" data-bundleid="{{bundleId}}" data-active="true" value="<?php p($l->t('Enable all'));?>"/></h2>
<div class="app-version"></div>
<div class="app-level"></div>
<div class="app-groups"></div>
<div class="actions">&nbsp;</div>
</div>
{{/if}}
<div class="section" id="app-{{id}}"> <div class="section" id="app-{{id}}">
<div class="app-image app-image-icon"></div> <div class="app-image app-image-icon"></div>
<div class="app-name"> <div class="app-name">

View File

@ -22,6 +22,7 @@
namespace Tests\Settings\Controller; namespace Tests\Settings\Controller;
use OC\App\AppStore\Bundles\BundleFetcher;
use OC\App\AppStore\Fetcher\AppFetcher; use OC\App\AppStore\Fetcher\AppFetcher;
use OC\App\AppStore\Fetcher\CategoryFetcher; use OC\App\AppStore\Fetcher\CategoryFetcher;
use OC\Settings\Controller\AppSettingsController; use OC\Settings\Controller\AppSettingsController;
@ -60,6 +61,8 @@ class AppSettingsControllerTest extends TestCase {
private $appFetcher; private $appFetcher;
/** @var IFactory|\PHPUnit_Framework_MockObject_MockObject */ /** @var IFactory|\PHPUnit_Framework_MockObject_MockObject */
private $l10nFactory; private $l10nFactory;
/** @var BundleFetcher|\PHPUnit_Framework_MockObject_MockObject */
private $bundleFetcher;
public function setUp() { public function setUp() {
parent::setUp(); parent::setUp();
@ -75,6 +78,7 @@ class AppSettingsControllerTest extends TestCase {
$this->categoryFetcher = $this->createMock(CategoryFetcher::class); $this->categoryFetcher = $this->createMock(CategoryFetcher::class);
$this->appFetcher = $this->createMock(AppFetcher::class); $this->appFetcher = $this->createMock(AppFetcher::class);
$this->l10nFactory = $this->createMock(IFactory::class); $this->l10nFactory = $this->createMock(IFactory::class);
$this->bundleFetcher = $this->createMock(BundleFetcher::class);
$this->appSettingsController = new AppSettingsController( $this->appSettingsController = new AppSettingsController(
'settings', 'settings',
@ -85,7 +89,8 @@ class AppSettingsControllerTest extends TestCase {
$this->appManager, $this->appManager,
$this->categoryFetcher, $this->categoryFetcher,
$this->appFetcher, $this->appFetcher,
$this->l10nFactory $this->l10nFactory,
$this->bundleFetcher
); );
} }
@ -106,6 +111,11 @@ class AppSettingsControllerTest extends TestCase {
'ident' => 'disabled', 'ident' => 'disabled',
'displayName' => 'Disabled apps', 'displayName' => 'Disabled apps',
], ],
[
'id' => 3,
'ident' => 'app-bundles',
'displayName' => 'App bundles',
],
[ [
'id' => 'auth', 'id' => 'auth',
'ident' => 'auth', 'ident' => 'auth',

View File

@ -0,0 +1,60 @@
<?php
/**
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace Test\App\AppStore\Bundles;
use OC\App\AppStore\Bundles\Bundle;
use OCP\IL10N;
use Test\TestCase;
abstract class BundleBase extends TestCase {
/** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */
protected $l10n;
/** @var Bundle */
protected $bundle;
/** @var string */
protected $bundleIdentifier;
/** @var string */
protected $bundleName;
/** @var array */
protected $bundleAppIds;
public function setUp() {
parent::setUp();
$this->l10n = $this->createMock(IL10N::class);
$this->l10n->method('t')
->will($this->returnCallback(function ($text, $parameters = []) {
return vsprintf($text, $parameters);
}));
}
public function testGetIdentifier() {
$this->assertSame($this->bundleIdentifier, $this->bundle->getIdentifier());
}
public function testGetName() {
$this->assertSame($this->bundleName, $this->bundle->getName());
}
public function testGetAppIdentifiers() {
$this->assertSame($this->bundleAppIds, $this->bundle->getAppIdentifiers());
}
}

View File

@ -0,0 +1,78 @@
<?php
/**
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace Test\App\AppStore\Bundles;
use OC\App\AppStore\Bundles\BundleFetcher;
use OC\App\AppStore\Bundles\CoreBundle;
use OC\App\AppStore\Bundles\EnterpriseBundle;
use OC\App\AppStore\Bundles\GroupwareBundle;
use OC\App\AppStore\Bundles\SocialSharingBundle;
use OCP\IL10N;
use Test\TestCase;
class BundleFetcherTest extends TestCase {
/** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */
private $l10n;
/** @var BundleFetcher */
private $bundleFetcher;
public function setUp() {
parent::setUp();
$this->l10n = $this->createMock(IL10N::class);
$this->bundleFetcher = new BundleFetcher(
$this->l10n
);
}
public function testGetBundles() {
$expected = [
new EnterpriseBundle($this->l10n),
new GroupwareBundle($this->l10n),
new SocialSharingBundle($this->l10n),
];
$this->assertEquals($expected, $this->bundleFetcher->getBundles());
}
public function testGetDefaultInstallationBundle() {
$expected = [
new CoreBundle($this->l10n),
];
$this->assertEquals($expected, $this->bundleFetcher->getDefaultInstallationBundle());
}
public function testGetBundleByIdentifier() {
$this->assertEquals(new EnterpriseBundle($this->l10n), $this->bundleFetcher->getBundleByIdentifier('EnterpriseBundle'));
$this->assertEquals(new CoreBundle($this->l10n), $this->bundleFetcher->getBundleByIdentifier('CoreBundle'));
$this->assertEquals(new GroupwareBundle($this->l10n), $this->bundleFetcher->getBundleByIdentifier('GroupwareBundle'));
}
/**
* @expectedException \BadMethodCallException
* @expectedExceptionMessage Bundle with specified identifier does not exist
*/
public function testGetBundleByIdentifierWithException() {
$this->bundleFetcher->getBundleByIdentifier('NotExistingBundle');
}
}

View File

@ -0,0 +1,36 @@
<?php
/**
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace Test\App\AppStore\Bundles;
use OC\App\AppStore\Bundles\CoreBundle;
class CoreBundleTest extends BundleBase {
public function setUp() {
parent::setUp();
$this->bundle = new CoreBundle($this->l10n);
$this->bundleIdentifier = 'CoreBundle';
$this->bundleName = 'Core bundle';
$this->bundleAppIds = [
'bruteforcesettings',
];
}
}

View File

@ -0,0 +1,41 @@
<?php
/**
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace Test\App\AppStore\Bundles;
use OC\App\AppStore\Bundles\EnterpriseBundle;
class EnterpriseBundleTest extends BundleBase {
public function setUp() {
parent::setUp();
$this->bundle = new EnterpriseBundle($this->l10n);
$this->bundleIdentifier = 'EnterpriseBundle';
$this->bundleName = 'Enterprise bundle';
$this->bundleAppIds = [
'admin_audit',
'user_ldap',
'files_retention',
'files_automatedtagging',
'user_saml',
'files_accesscontrol',
];
}
}

View File

@ -0,0 +1,38 @@
<?php
/**
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace Test\App\AppStore\Bundles;
use OC\App\AppStore\Bundles\GroupwareBundle;
class GroupwareBundleTest extends BundleBase {
public function setUp() {
parent::setUp();
$this->bundle = new GroupwareBundle($this->l10n);
$this->bundleIdentifier = 'GroupwareBundle';
$this->bundleName = 'Groupware bundle';
$this->bundleAppIds = [
'calendar',
'contacts',
'spreed',
];
}
}

View File

@ -0,0 +1,40 @@
<?php
/**
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace Test\App\AppStore\Bundles;
use OC\App\AppStore\Bundles\SocialSharingBundle;
class SocialSharingBundleTest extends BundleBase {
public function setUp() {
parent::setUp();
$this->bundle = new SocialSharingBundle($this->l10n);
$this->bundleIdentifier = 'SocialSharingBundle';
$this->bundleName = 'Social sharing bundle';
$this->bundleAppIds = [
'socialsharing_twitter',
'socialsharing_googleplus',
'socialsharing_facebook',
'socialsharing_email',
'socialsharing_diaspora',
];
}
}

View File

@ -9,11 +9,13 @@
namespace Test; namespace Test;
use OC\App\AppStore\Bundles\Bundle;
use OC\App\AppStore\Fetcher\AppFetcher; use OC\App\AppStore\Fetcher\AppFetcher;
use OC\Archive\ZIP; use OC\Archive\ZIP;
use OC\Installer; use OC\Installer;
use OCP\Http\Client\IClient; use OCP\Http\Client\IClient;
use OCP\Http\Client\IClientService; use OCP\Http\Client\IClientService;
use OCP\IConfig;
use OCP\ILogger; use OCP\ILogger;
use OCP\ITempManager; use OCP\ITempManager;
@ -29,6 +31,8 @@ class InstallerTest extends TestCase {
private $tempManager; private $tempManager;
/** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */ /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */
private $logger; private $logger;
/** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
private $config;
/** @var Installer */ /** @var Installer */
private $installer; private $installer;
@ -40,11 +44,13 @@ class InstallerTest extends TestCase {
$this->clientService = $this->createMock(IClientService::class); $this->clientService = $this->createMock(IClientService::class);
$this->tempManager = $this->createMock(ITempManager::class); $this->tempManager = $this->createMock(ITempManager::class);
$this->logger = $this->createMock(ILogger::class); $this->logger = $this->createMock(ILogger::class);
$this->config = $this->createMock(IConfig::class);
$this->installer = new Installer( $this->installer = new Installer(
$this->appFetcher, $this->appFetcher,
$this->clientService, $this->clientService,
$this->tempManager, $this->tempManager,
$this->logger $this->logger,
$this->config
); );
$config = \OC::$server->getConfig(); $config = \OC::$server->getConfig();
@ -54,7 +60,8 @@ class InstallerTest extends TestCase {
\OC::$server->getAppFetcher(), \OC::$server->getAppFetcher(),
\OC::$server->getHTTPClientService(), \OC::$server->getHTTPClientService(),
\OC::$server->getTempManager(), \OC::$server->getTempManager(),
\OC::$server->getLogger() \OC::$server->getLogger(),
$config
); );
$installer->removeApp(self::$appid); $installer->removeApp(self::$appid);
} }
@ -64,7 +71,8 @@ class InstallerTest extends TestCase {
\OC::$server->getAppFetcher(), \OC::$server->getAppFetcher(),
\OC::$server->getHTTPClientService(), \OC::$server->getHTTPClientService(),
\OC::$server->getTempManager(), \OC::$server->getTempManager(),
\OC::$server->getLogger() \OC::$server->getLogger(),
\OC::$server->getConfig()
); );
$installer->removeApp(self::$appid); $installer->removeApp(self::$appid);
\OC::$server->getConfig()->setSystemValue('appstoreenabled', $this->appstore); \OC::$server->getConfig()->setSystemValue('appstoreenabled', $this->appstore);
@ -86,7 +94,8 @@ class InstallerTest extends TestCase {
\OC::$server->getAppFetcher(), \OC::$server->getAppFetcher(),
\OC::$server->getHTTPClientService(), \OC::$server->getHTTPClientService(),
\OC::$server->getTempManager(), \OC::$server->getTempManager(),
\OC::$server->getLogger() \OC::$server->getLogger(),
\OC::$server->getConfig()
); );
$installer->installApp(self::$appid); $installer->installApp(self::$appid);
$isInstalled = Installer::isInstalled(self::$appid); $isInstalled = Installer::isInstalled(self::$appid);

View File

@ -0,0 +1,144 @@
<?php
/**
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
*
* @author Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace Test\Repair\NC12;
use OC\App\AppStore\Bundles\Bundle;
use OC\App\AppStore\Bundles\BundleFetcher;
use OC\Installer;
use OC\Repair\NC12\InstallCoreBundle;
use OCP\IConfig;
use OCP\Migration\IOutput;
use Test\TestCase;
class InstallCoreBundleTest extends TestCase {
/** @var BundleFetcher|\PHPUnit_Framework_MockObject_MockObject */
private $bundleFetcher;
/** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
private $config;
/** @var Installer|\PHPUnit_Framework_MockObject_MockObject */
private $installer;
/** @var InstallCoreBundle */
private $installCoreBundle;
public function setUp() {
parent::setUp();
$this->bundleFetcher = $this->createMock(BundleFetcher::class);
$this->config = $this->createMock(IConfig::class);
$this->installer = $this->createMock(Installer::class);
$this->installCoreBundle = new InstallCoreBundle(
$this->bundleFetcher,
$this->config,
$this->installer
);
}
public function testGetName() {
$this->assertSame('Install new core bundle components', $this->installCoreBundle->getName());
}
public function testRunOlder() {
$this->config
->expects($this->once())
->method('getSystemValue')
->with('version', '0.0.0')
->willReturn('12.0.0.15');
$this->bundleFetcher
->expects($this->never())
->method('getDefaultInstallationBundle');
/** @var IOutput|\PHPUnit_Framework_MockObject_MockObject $output */
$output = $this->createMock(IOutput::class);
$output
->expects($this->never())
->method('info');
$output
->expects($this->never())
->method('warning');
$this->installCoreBundle->run($output);
}
public function testRunWithException() {
$this->config
->expects($this->once())
->method('getSystemValue')
->with('version', '0.0.0')
->willReturn('12.0.0.14');
$bundle = $this->createMock(Bundle::class);
$this->bundleFetcher
->expects($this->once())
->method('getDefaultInstallationBundle')
->willReturn([
$bundle,
]);
$this->installer
->expects($this->once())
->method('installAppBundle')
->with($bundle)
->willThrowException(new \Exception('ExceptionText'));
/** @var IOutput|\PHPUnit_Framework_MockObject_MockObject $output */
$output = $this->createMock(IOutput::class);
$output
->expects($this->never())
->method('info');
$output
->expects($this->once())
->method('warning')
->with('Could not install core app bundle: ExceptionText');
$this->installCoreBundle->run($output);
}
public function testRun() {
$this->config
->expects($this->once())
->method('getSystemValue')
->with('version', '0.0.0')
->willReturn('12.0.0.14');
$bundle = $this->createMock(Bundle::class);
$this->bundleFetcher
->expects($this->once())
->method('getDefaultInstallationBundle')
->willReturn([
$bundle,
]);
$this->installer
->expects($this->once())
->method('installAppBundle')
->with($bundle);
/** @var IOutput|\PHPUnit_Framework_MockObject_MockObject $output */
$output = $this->createMock(IOutput::class);
$output
->expects($this->once())
->method('info')
->with('Successfully installed core app bundle.');
$output
->expects($this->never())
->method('warning');
$this->installCoreBundle->run($output);
}
}

View File

@ -26,7 +26,7 @@
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel // between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
// when updating major/minor version number. // when updating major/minor version number.
$OC_Version = array(12, 0, 0, 14); $OC_Version = array(12, 0, 0, 15);
// The human readable string // The human readable string
$OC_VersionString = '12.0 alpha'; $OC_VersionString = '12.0 alpha';