Merge pull request #24444 from owncloud/update-notifications-for-core-and-apps
Update notifications for core and apps
This commit is contained in:
commit
c36cf30ade
10 changed files with 911 additions and 1 deletions
|
@ -38,4 +38,18 @@ if(\OC::$server->getConfig()->getSystemValue('updatechecker', true) === true) {
|
|||
\OC_App::registerAdmin('updatenotification', 'admin');
|
||||
}
|
||||
}
|
||||
|
||||
$manager = \OC::$server->getNotificationManager();
|
||||
$manager->registerNotifier(function() use ($manager) {
|
||||
return new \OCA\UpdateNotification\Notification\Notifier(
|
||||
$manager,
|
||||
\OC::$server->getL10NFactory()
|
||||
);
|
||||
}, function() {
|
||||
$l = \OC::$server->getL10N('updatenotification');
|
||||
return [
|
||||
'id' => 'updatenotification',
|
||||
'name' => $l->t('Update notifications'),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,10 +5,14 @@
|
|||
<description>Displays update notifications for ownCloud and provides the SSO for the updater.</description>
|
||||
<licence>AGPL</licence>
|
||||
<author>Lukas Reschke</author>
|
||||
<version>0.2.0</version>
|
||||
<version>0.2.1</version>
|
||||
<namespace>UpdateNotification</namespace>
|
||||
<default_enable/>
|
||||
<dependencies>
|
||||
<owncloud min-version="9.1" max-version="9.1" />
|
||||
</dependencies>
|
||||
|
||||
<background-jobs>
|
||||
<job>OCA\UpdateNotification\Notification\BackgroundJob</job>
|
||||
</background-jobs>
|
||||
</info>
|
||||
|
|
|
@ -39,8 +39,16 @@ $(document).ready(function(){
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
$('#release-channel').change(function() {
|
||||
var newChannel = $('#release-channel').find(":selected").val();
|
||||
|
||||
if (newChannel === 'git' || newChannel === 'daily') {
|
||||
$('#oca_updatenotification_groups em').removeClass('hidden');
|
||||
} else {
|
||||
$('#oca_updatenotification_groups em').addClass('hidden');
|
||||
}
|
||||
|
||||
$.post(
|
||||
OC.generateUrl('/apps/updatenotification/channel'),
|
||||
{
|
||||
|
@ -51,4 +59,12 @@ $(document).ready(function(){
|
|||
}
|
||||
);
|
||||
});
|
||||
|
||||
var $notificationTargetGroups = $('#oca_updatenotification_groups_list');
|
||||
OC.Settings.setupGroupsSelect($notificationTargetGroups);
|
||||
$notificationTargetGroups.change(function(ev) {
|
||||
var groups = ev.val || [];
|
||||
groups = JSON.stringify(groups);
|
||||
OC.AppConfig.setValue('updatenotification', 'notify_groups', groups);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -100,12 +100,17 @@ class AdminController extends Controller {
|
|||
unset($channels[$key]);
|
||||
}
|
||||
$updateState = $this->updateChecker->getUpdateState();
|
||||
|
||||
$notifyGroups = json_decode($this->config->getAppValue('updatenotification', 'notify_groups', '["admin"]'), true);
|
||||
|
||||
$params = [
|
||||
'isNewVersionAvailable' => ($updateState === []) ? false : true,
|
||||
'lastChecked' => $lastUpdateCheck,
|
||||
'currentChannel' => $currentChannel,
|
||||
'channels' => $channels,
|
||||
'newVersionString' => ($updateState === []) ? '' : $updateState['updateVersion'],
|
||||
|
||||
'notify_groups' => implode('|', $notifyGroups),
|
||||
];
|
||||
|
||||
return new TemplateResponse($this->appName, 'admin', $params, '');
|
||||
|
|
213
apps/updatenotification/lib/Notification/BackgroundJob.php
Normal file
213
apps/updatenotification/lib/Notification/BackgroundJob.php
Normal file
|
@ -0,0 +1,213 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Joas Schilling <nickvergessen@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\UpdateNotification\Notification;
|
||||
|
||||
|
||||
use OC\BackgroundJob\TimedJob;
|
||||
use OC\Installer;
|
||||
use OC\Updater\VersionCheck;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\Http\Client\IClientService;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroup;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\Notification\IManager;
|
||||
|
||||
class BackgroundJob extends TimedJob {
|
||||
|
||||
/** @var IConfig */
|
||||
protected $config;
|
||||
|
||||
/** @var IManager */
|
||||
protected $notificationManager;
|
||||
|
||||
/** @var IGroupManager */
|
||||
protected $groupManager;
|
||||
|
||||
/** @var IAppManager */
|
||||
protected $appManager;
|
||||
|
||||
/** @var IClientService */
|
||||
protected $client;
|
||||
|
||||
/** @var IURLGenerator */
|
||||
protected $urlGenerator;
|
||||
|
||||
/** @var IUser[] */
|
||||
protected $users;
|
||||
|
||||
/**
|
||||
* NotificationBackgroundJob constructor.
|
||||
*
|
||||
* @param IConfig $config
|
||||
* @param IManager $notificationManager
|
||||
* @param IGroupManager $groupManager
|
||||
* @param IAppManager $appManager
|
||||
* @param IClientService $client
|
||||
* @param IURLGenerator $urlGenerator
|
||||
*/
|
||||
public function __construct(IConfig $config, IManager $notificationManager, IGroupManager $groupManager, IAppManager $appManager, IClientService $client, IURLGenerator $urlGenerator) {
|
||||
// Run once a day
|
||||
$this->setInterval(60 * 60 * 24);
|
||||
|
||||
$this->config = $config;
|
||||
$this->notificationManager = $notificationManager;
|
||||
$this->groupManager = $groupManager;
|
||||
$this->appManager = $appManager;
|
||||
$this->client = $client;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
}
|
||||
|
||||
protected function run($argument) {
|
||||
$this->checkCoreUpdate();
|
||||
$this->checkAppUpdates();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for ownCloud update
|
||||
*/
|
||||
protected function checkCoreUpdate() {
|
||||
if (in_array($this->getChannel(), ['daily', 'git'])) {
|
||||
// "These aren't the update channels you're looking for." - Ben Obi-Wan Kenobi
|
||||
return;
|
||||
}
|
||||
|
||||
$updater = $this->createVersionCheck();
|
||||
|
||||
$status = $updater->check();
|
||||
if (isset($status['version'])) {
|
||||
$url = $this->urlGenerator->linkToRouteAbsolute('settings_admin') . '#updater';
|
||||
$this->createNotifications('core', $status['version'], $url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check all installed apps for updates
|
||||
*/
|
||||
protected function checkAppUpdates() {
|
||||
$apps = $this->appManager->getInstalledApps();
|
||||
foreach ($apps as $app) {
|
||||
$update = $this->isUpdateAvailable($app);
|
||||
if ($update !== false) {
|
||||
$url = $this->urlGenerator->linkToRouteAbsolute('settings.AppSettings.viewApps') . '#app-' . $app;
|
||||
$this->createNotifications($app, $update, $url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create notifications for this app version
|
||||
*
|
||||
* @param string $app
|
||||
* @param string $version
|
||||
* @param string $url
|
||||
*/
|
||||
protected function createNotifications($app, $version, $url) {
|
||||
$lastNotification = $this->config->getAppValue('updatenotification', $app, false);
|
||||
if ($lastNotification === $version) {
|
||||
// We already notified about this update
|
||||
return;
|
||||
} else if ($lastNotification !== false) {
|
||||
// Delete old updates
|
||||
$this->deleteOutdatedNotifications($app, $lastNotification);
|
||||
}
|
||||
|
||||
|
||||
$notification = $this->notificationManager->createNotification();
|
||||
$notification->setApp('updatenotification')
|
||||
->setDateTime(new \DateTime())
|
||||
->setObject($app, $version)
|
||||
->setSubject('update_available')
|
||||
->setLink($url);
|
||||
|
||||
foreach ($this->getUsersToNotify() as $uid) {
|
||||
$notification->setUser($uid);
|
||||
$this->notificationManager->notify($notification);
|
||||
}
|
||||
|
||||
$this->config->setAppValue('updatenotification', $app, $version);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getUsersToNotify() {
|
||||
if ($this->users !== null) {
|
||||
return $this->users;
|
||||
}
|
||||
|
||||
$notifyGroups = json_decode($this->config->getAppValue('updatenotification', 'notify_groups', '["admin"]'), true);
|
||||
$this->users = [];
|
||||
foreach ($notifyGroups as $group) {
|
||||
$groupToNotify = $this->groupManager->get($group);
|
||||
if ($groupToNotify instanceof IGroup) {
|
||||
foreach ($groupToNotify->getUsers() as $user) {
|
||||
$this->users[$user->getUID()] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->users = array_keys($this->users);
|
||||
|
||||
return $this->users;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete notifications for old updates
|
||||
*
|
||||
* @param string $app
|
||||
* @param string $version
|
||||
*/
|
||||
protected function deleteOutdatedNotifications($app, $version) {
|
||||
$notification = $this->notificationManager->createNotification();
|
||||
$notification->setApp('updatenotification')
|
||||
->setObject($app, $version);
|
||||
$this->notificationManager->markProcessed($notification);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return VersionCheck
|
||||
*/
|
||||
protected function createVersionCheck() {
|
||||
return new VersionCheck(
|
||||
$this->client,
|
||||
$this->config
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getChannel() {
|
||||
return \OC_Util::getChannel();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $app
|
||||
* @return string|false
|
||||
*/
|
||||
protected function isUpdateAvailable($app) {
|
||||
return Installer::isUpdateAvailable($app);
|
||||
}
|
||||
}
|
108
apps/updatenotification/lib/Notification/Notifier.php
Normal file
108
apps/updatenotification/lib/Notification/Notifier.php
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Joas Schilling <nickvergessen@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\UpdateNotification\Notification;
|
||||
|
||||
|
||||
use OCP\L10N\IFactory;
|
||||
use OCP\Notification\IManager;
|
||||
use OCP\Notification\INotification;
|
||||
use OCP\Notification\INotifier;
|
||||
|
||||
class Notifier implements INotifier {
|
||||
|
||||
/** @var IManager */
|
||||
protected $notificationManager;
|
||||
|
||||
/** @var IFactory */
|
||||
protected $l10NFactory;
|
||||
|
||||
/** @var string[] */
|
||||
protected $appVersions;
|
||||
|
||||
/**
|
||||
* Notifier constructor.
|
||||
*
|
||||
* @param IManager $notificationManager
|
||||
* @param IFactory $l10NFactory
|
||||
*/
|
||||
public function __construct(IManager $notificationManager, IFactory $l10NFactory) {
|
||||
$this->notificationManager = $notificationManager;
|
||||
$this->l10NFactory = $l10NFactory;
|
||||
$this->appVersions = $this->getAppVersions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param INotification $notification
|
||||
* @param string $languageCode The code of the language that should be used to prepare the notification
|
||||
* @return INotification
|
||||
* @throws \InvalidArgumentException When the notification was not prepared by a notifier
|
||||
* @since 9.0.0
|
||||
*/
|
||||
public function prepare(INotification $notification, $languageCode) {
|
||||
if ($notification->getApp() !== 'updatenotification') {
|
||||
throw new \InvalidArgumentException();
|
||||
}
|
||||
|
||||
$l = $this->l10NFactory->get('updatenotification', $languageCode);
|
||||
if ($notification->getObjectType() === 'core') {
|
||||
$appName = $l->t('ownCloud core');
|
||||
|
||||
$this->updateAlreadyInstalledCheck($notification, $this->getCoreVersions());
|
||||
} else {
|
||||
$appInfo = $this->getAppInfo($notification->getObjectType());
|
||||
$appName = ($appInfo === null) ? $notification->getObjectType() : $appInfo['name'];
|
||||
|
||||
if (isset($this->appVersions[$notification->getObjectType()])) {
|
||||
$this->updateAlreadyInstalledCheck($notification, $this->appVersions[$notification->getObjectType()]);
|
||||
}
|
||||
}
|
||||
|
||||
$notification->setParsedSubject($l->t('Update for %1$s to version %2$s is available.', [$appName, $notification->getObjectId()]));
|
||||
return $notification;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the notification and prevent rendering, when the update is installed
|
||||
*
|
||||
* @param INotification $notification
|
||||
* @param string $installedVersion
|
||||
* @throws \InvalidArgumentException When the update is already installed
|
||||
*/
|
||||
protected function updateAlreadyInstalledCheck(INotification $notification, $installedVersion) {
|
||||
if (version_compare($notification->getObjectId(), $installedVersion, '<=')) {
|
||||
$this->notificationManager->markProcessed($notification);
|
||||
throw new \InvalidArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
protected function getCoreVersions() {
|
||||
return implode('.', \OCP\Util::getVersion());
|
||||
}
|
||||
|
||||
protected function getAppVersions() {
|
||||
return \OC_App::getAppVersions();
|
||||
}
|
||||
|
||||
protected function getAppInfo($appId) {
|
||||
return \OC_App::getAppInfo($appId);
|
||||
}
|
||||
}
|
|
@ -39,4 +39,15 @@
|
|||
<p>
|
||||
<em><?php p($l->t('You can always update to a newer version / experimental channel. But you can never downgrade to a more stable channel.')); ?></em>
|
||||
</p>
|
||||
|
||||
|
||||
<p id="oca_updatenotification_groups">
|
||||
<br />
|
||||
<?php p($l->t('Notify members of the following groups about available updates:')); ?>
|
||||
<input name="oca_updatenotification_groups_list" type="hidden" id="oca_updatenotification_groups_list" value="<?php p($_['notify_groups']) ?>" style="width: 400px">
|
||||
<em class="<?php if (!in_array($currentChannel, ['daily', 'git'])) p('hidden'); ?>">
|
||||
<br />
|
||||
<?php p($l->t('Only notification for app updates are available, because the selected update channel for ownCloud itself does not allow notifications.')); ?>
|
||||
</em>
|
||||
</p>
|
||||
</form>
|
||||
|
|
430
apps/updatenotification/tests/Notification/BackgroundJobTest.php
Normal file
430
apps/updatenotification/tests/Notification/BackgroundJobTest.php
Normal file
|
@ -0,0 +1,430 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Joas Schilling <nickvergessen@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\UpdateNotification\Tests\Notification;
|
||||
|
||||
|
||||
use OCA\UpdateNotification\Notification\BackgroundJob;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\Http\Client\IClientService;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\Notification\IManager;
|
||||
use Test\TestCase;
|
||||
|
||||
class BackgroundJobTest extends TestCase {
|
||||
|
||||
/** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $config;
|
||||
/** @var IManager|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $notificationManager;
|
||||
/** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $groupManager;
|
||||
/** @var IAppManager|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $appManager;
|
||||
/** @var IClientService|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $client;
|
||||
/** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $urlGenerator;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->config = $this->getMock('OCP\IConfig');
|
||||
$this->notificationManager = $this->getMock('OCP\Notification\IManager');
|
||||
$this->groupManager = $this->getMock('OCP\IGroupManager');
|
||||
$this->appManager = $this->getMock('OCP\App\IAppManager');
|
||||
$this->client = $this->getMock('OCP\Http\Client\IClientService');
|
||||
$this->urlGenerator = $this->getMock('OCP\IURLGenerator');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $methods
|
||||
* @return BackgroundJob|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected function getJob(array $methods = []) {
|
||||
if (empty($methods)) {
|
||||
return new BackgroundJob(
|
||||
$this->config,
|
||||
$this->notificationManager,
|
||||
$this->groupManager,
|
||||
$this->appManager,
|
||||
$this->client,
|
||||
$this->urlGenerator
|
||||
);
|
||||
} {
|
||||
return $this->getMockBuilder('OCA\UpdateNotification\Notification\BackgroundJob')
|
||||
->setConstructorArgs([
|
||||
$this->config,
|
||||
$this->notificationManager,
|
||||
$this->groupManager,
|
||||
$this->appManager,
|
||||
$this->client,
|
||||
$this->urlGenerator,
|
||||
])
|
||||
->setMethods($methods)
|
||||
->getMock();
|
||||
}
|
||||
}
|
||||
|
||||
public function testRun() {
|
||||
$job = $this->getJob([
|
||||
'checkCoreUpdate',
|
||||
'checkAppUpdates',
|
||||
]);
|
||||
|
||||
$job->expects($this->once())
|
||||
->method('checkCoreUpdate');
|
||||
$job->expects($this->once())
|
||||
->method('checkAppUpdates');
|
||||
|
||||
$this->invokePrivate($job, 'run', [null]);
|
||||
}
|
||||
|
||||
public function dataCheckCoreUpdate() {
|
||||
return [
|
||||
['daily', null, null],
|
||||
['git', null, null],
|
||||
['beta', false, null],
|
||||
['beta', [
|
||||
'version' => '9.2.0',
|
||||
], '9.2.0'],
|
||||
['stable', false, null],
|
||||
['stable', [
|
||||
'version' => '9.2.0',
|
||||
], '9.2.0'],
|
||||
['production', false, null],
|
||||
['production', [
|
||||
'version' => '9.2.0',
|
||||
], '9.2.0'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataCheckCoreUpdate
|
||||
*
|
||||
* @param string $channel
|
||||
* @param mixed $versionCheck
|
||||
* @param null|string $notification
|
||||
*/
|
||||
public function testCheckCoreUpdate($channel, $versionCheck, $notification) {
|
||||
$job = $this->getJob([
|
||||
'getChannel',
|
||||
'createVersionCheck',
|
||||
'createNotifications',
|
||||
]);
|
||||
|
||||
$job->expects($this->once())
|
||||
->method('getChannel')
|
||||
->willReturn($channel);
|
||||
|
||||
if ($versionCheck === null) {
|
||||
$job->expects($this->never())
|
||||
->method('createVersionCheck');
|
||||
} else {
|
||||
$check = $this->getMockBuilder('OC\Updater\VersionCheck')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$check->expects($this->once())
|
||||
->method('check')
|
||||
->willReturn($versionCheck);
|
||||
|
||||
$job->expects($this->once())
|
||||
->method('createVersionCheck')
|
||||
->willReturn($check);
|
||||
}
|
||||
|
||||
if ($notification === null) {
|
||||
$this->urlGenerator->expects($this->never())
|
||||
->method('linkToRouteAbsolute');
|
||||
|
||||
$job->expects($this->never())
|
||||
->method('createNotifications');
|
||||
} else {
|
||||
$this->urlGenerator->expects($this->once())
|
||||
->method('linkToRouteAbsolute')
|
||||
->with('settings_admin')
|
||||
->willReturn('admin-url');
|
||||
|
||||
$job->expects($this->once())
|
||||
->method('createNotifications')
|
||||
->willReturn('core', $notification, 'admin-url#updater');
|
||||
}
|
||||
|
||||
$this->invokePrivate($job, 'checkCoreUpdate');
|
||||
}
|
||||
|
||||
public function dataCheckAppUpdates() {
|
||||
return [
|
||||
[
|
||||
['app1', 'app2'],
|
||||
[
|
||||
['app1', false],
|
||||
['app2', '1.9.2'],
|
||||
],
|
||||
[
|
||||
['app2', '1.9.2', 'apps-url#app-app2'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataCheckAppUpdates
|
||||
*
|
||||
* @param string[] $apps
|
||||
* @param array $isUpdateAvailable
|
||||
* @param array $notifications
|
||||
*/
|
||||
public function testCheckAppUpdates(array $apps, array $isUpdateAvailable, array $notifications) {
|
||||
$job = $this->getJob([
|
||||
'isUpdateAvailable',
|
||||
'createNotifications',
|
||||
]);
|
||||
|
||||
$this->appManager->expects($this->once())
|
||||
->method('getInstalledApps')
|
||||
->willReturn($apps);
|
||||
|
||||
$job->expects($this->exactly(sizeof($apps)))
|
||||
->method('isUpdateAvailable')
|
||||
->willReturnMap($isUpdateAvailable);
|
||||
|
||||
$this->urlGenerator->expects($this->exactly(sizeof($notifications)))
|
||||
->method('linkToRouteAbsolute')
|
||||
->with('settings.AppSettings.viewApps')
|
||||
->willReturn('apps-url');
|
||||
|
||||
$mockedMethod = $job->expects($this->exactly(sizeof($notifications)))
|
||||
->method('createNotifications');
|
||||
call_user_func_array([$mockedMethod, 'withConsecutive'], $notifications);
|
||||
|
||||
$this->invokePrivate($job, 'checkAppUpdates');
|
||||
}
|
||||
|
||||
public function dataCreateNotifications() {
|
||||
return [
|
||||
['app1', '1.0.0', 'link1', '1.0.0', false, false, null, null],
|
||||
['app2', '1.0.1', 'link2', '1.0.0', '1.0.0', true, ['user1'], [['user1']]],
|
||||
['app3', '1.0.1', 'link3', false, false, true, ['user2', 'user3'], [['user2'], ['user3']]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataCreateNotifications
|
||||
*
|
||||
* @param string $app
|
||||
* @param string $version
|
||||
* @param string $url
|
||||
* @param string|false $lastNotification
|
||||
* @param string|false $callDelete
|
||||
* @param bool $createNotification
|
||||
* @param string[]|null $users
|
||||
* @param array|null $userNotifications
|
||||
*/
|
||||
public function testCreateNotifications($app, $version, $url, $lastNotification, $callDelete, $createNotification, $users, $userNotifications) {
|
||||
$job = $this->getJob([
|
||||
'deleteOutdatedNotifications',
|
||||
'getUsersToNotify',
|
||||
]);
|
||||
|
||||
$this->config->expects($this->once())
|
||||
->method('getAppValue')
|
||||
->with('updatenotification', $app, false)
|
||||
->willReturn($lastNotification);
|
||||
|
||||
if ($lastNotification !== $version) {
|
||||
$this->config->expects($this->once())
|
||||
->method('setAppValue')
|
||||
->with('updatenotification', $app, $version);
|
||||
}
|
||||
|
||||
if ($callDelete === false) {
|
||||
$job->expects($this->never())
|
||||
->method('deleteOutdatedNotifications');
|
||||
} else {
|
||||
$job->expects($this->once())
|
||||
->method('deleteOutdatedNotifications')
|
||||
->with($app, $callDelete);
|
||||
}
|
||||
|
||||
if ($users === null) {
|
||||
$job->expects($this->never())
|
||||
->method('getUsersToNotify');
|
||||
} else {
|
||||
$job->expects($this->once())
|
||||
->method('getUsersToNotify')
|
||||
->willReturn($users);
|
||||
}
|
||||
|
||||
if ($createNotification) {
|
||||
$notification = $this->getMock('OCP\Notification\INotification');
|
||||
$notification->expects($this->once())
|
||||
->method('setApp')
|
||||
->with('updatenotification')
|
||||
->willReturnSelf();
|
||||
$notification->expects($this->once())
|
||||
->method('setDateTime')
|
||||
->willReturnSelf();
|
||||
$notification->expects($this->once())
|
||||
->method('setObject')
|
||||
->with($app, $version)
|
||||
->willReturnSelf();
|
||||
$notification->expects($this->once())
|
||||
->method('setSubject')
|
||||
->with('update_available')
|
||||
->willReturnSelf();
|
||||
$notification->expects($this->once())
|
||||
->method('setLink')
|
||||
->with($url)
|
||||
->willReturnSelf();
|
||||
|
||||
if ($userNotifications !== null) {
|
||||
$mockedMethod = $notification->expects($this->exactly(sizeof($userNotifications)))
|
||||
->method('setUser')
|
||||
->willReturnSelf();
|
||||
call_user_func_array([$mockedMethod, 'withConsecutive'], $userNotifications);
|
||||
|
||||
$this->notificationManager->expects($this->exactly(sizeof($userNotifications)))
|
||||
->method('notify')
|
||||
->willReturn($notification);
|
||||
}
|
||||
|
||||
$this->notificationManager->expects($this->once())
|
||||
->method('createNotification')
|
||||
->willReturn($notification);
|
||||
} else {
|
||||
$this->notificationManager->expects($this->never())
|
||||
->method('createNotification');
|
||||
}
|
||||
|
||||
$this->invokePrivate($job, 'createNotifications', [$app, $version, $url]);
|
||||
}
|
||||
|
||||
public function dataGetUsersToNotify() {
|
||||
return [
|
||||
[['g1', 'g2'], ['g1' => null, 'g2' => ['u1', 'u2']], ['u1', 'u2']],
|
||||
[['g3', 'g4'], ['g3' => ['u1', 'u2'], 'g4' => ['u2', 'u3']], ['u1', 'u2', 'u3']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataGetUsersToNotify
|
||||
* @param string[] $groups
|
||||
* @param array $groupUsers
|
||||
* @param string[] $expected
|
||||
*/
|
||||
public function testGetUsersToNotify($groups, array $groupUsers, array $expected) {
|
||||
$job = $this->getJob();
|
||||
|
||||
$this->config->expects($this->once())
|
||||
->method('getAppValue')
|
||||
->with('updatenotification', 'notify_groups', '["admin"]')
|
||||
->willReturn(json_encode($groups));
|
||||
|
||||
$groupMap = [];
|
||||
foreach ($groupUsers as $gid => $uids) {
|
||||
if ($uids === null) {
|
||||
$group = null;
|
||||
} else {
|
||||
$group = $this->getGroup($gid);
|
||||
$group->expects($this->any())
|
||||
->method('getUsers')
|
||||
->willReturn($this->getUsers($uids));
|
||||
}
|
||||
$groupMap[] = [$gid, $group];
|
||||
}
|
||||
$this->groupManager->expects($this->exactly(sizeof($groups)))
|
||||
->method('get')
|
||||
->willReturnMap($groupMap);
|
||||
|
||||
$result = $this->invokePrivate($job, 'getUsersToNotify');
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
// Test caching
|
||||
$result = $this->invokePrivate($job, 'getUsersToNotify');
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
public function dataDeleteOutdatedNotifications() {
|
||||
return [
|
||||
['app1', '1.1.0'],
|
||||
['app2', '1.2.0'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataDeleteOutdatedNotifications
|
||||
* @param string $app
|
||||
* @param string $version
|
||||
*/
|
||||
public function testDeleteOutdatedNotifications($app, $version) {
|
||||
$notification = $this->getMock('OCP\Notification\INotification');
|
||||
$notification->expects($this->once())
|
||||
->method('setApp')
|
||||
->with('updatenotification')
|
||||
->willReturnSelf();
|
||||
$notification->expects($this->once())
|
||||
->method('setObject')
|
||||
->with($app, $version)
|
||||
->willReturnSelf();
|
||||
|
||||
$this->notificationManager->expects($this->once())
|
||||
->method('createNotification')
|
||||
->willReturn($notification);
|
||||
$this->notificationManager->expects($this->once())
|
||||
->method('markProcessed')
|
||||
->with($notification);
|
||||
|
||||
$job = $this->getJob();
|
||||
$this->invokePrivate($job, 'deleteOutdatedNotifications', [$app, $version]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $userIds
|
||||
* @return IUser[]|\PHPUnit_Framework_MockObject_MockObject[]
|
||||
*/
|
||||
protected function getUsers(array $userIds) {
|
||||
$users = [];
|
||||
foreach ($userIds as $uid) {
|
||||
$user = $this->getMock('OCP\IUser');
|
||||
$user->expects($this->any())
|
||||
->method('getUID')
|
||||
->willReturn($uid);
|
||||
$users[] = $user;
|
||||
}
|
||||
return $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $gid
|
||||
* @return \OCP\IGroup|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected function getGroup($gid) {
|
||||
$group = $this->getMock('OCP\IGroup');
|
||||
$group->expects($this->any())
|
||||
->method('getGID')
|
||||
->willReturn($gid);
|
||||
return $group;
|
||||
}
|
||||
}
|
105
apps/updatenotification/tests/Notification/NotifierTest.php
Normal file
105
apps/updatenotification/tests/Notification/NotifierTest.php
Normal file
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Joas Schilling <nickvergessen@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\UpdateNotification\Tests\Notification;
|
||||
|
||||
|
||||
use OCA\UpdateNotification\Notification\Notifier;
|
||||
use OCP\L10N\IFactory;
|
||||
use OCP\Notification\IManager;
|
||||
use Test\TestCase;
|
||||
|
||||
class NotifierTest extends TestCase {
|
||||
|
||||
/** @var IManager|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $notificationManager;
|
||||
/** @var IFactory|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $l10nFactory;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->notificationManager = $this->getMock('OCP\Notification\IManager');
|
||||
$this->l10nFactory = $this->getMock('OCP\L10n\IFactory');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $methods
|
||||
* @return Notifier|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected function getNotifier(array $methods = []) {
|
||||
if (empty($methods)) {
|
||||
return new Notifier(
|
||||
$this->notificationManager,
|
||||
$this->l10nFactory
|
||||
);
|
||||
} {
|
||||
return $this->getMockBuilder('OCA\UpdateNotification\Notification\Notifier')
|
||||
->setConstructorArgs([
|
||||
$this->notificationManager,
|
||||
$this->l10nFactory,
|
||||
])
|
||||
->setMethods($methods)
|
||||
->getMock();
|
||||
}
|
||||
}
|
||||
|
||||
public function dataUpdateAlreadyInstalledCheck() {
|
||||
return [
|
||||
['1.1.0', '1.0.0', false],
|
||||
['1.1.0', '1.1.0', true],
|
||||
['1.1.0', '1.2.0', true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataUpdateAlreadyInstalledCheck
|
||||
*
|
||||
* @param string $versionNotification
|
||||
* @param string $versionInstalled
|
||||
* @param bool $exception
|
||||
*/
|
||||
public function testUpdateAlreadyInstalledCheck($versionNotification, $versionInstalled, $exception) {
|
||||
$notifier = $this->getNotifier();
|
||||
|
||||
$notification = $this->getMock('OCP\Notification\INotification');
|
||||
$notification->expects($this->once())
|
||||
->method('getObjectId')
|
||||
->willReturn($versionNotification);
|
||||
|
||||
if ($exception) {
|
||||
$this->notificationManager->expects($this->once())
|
||||
->method('markProcessed')
|
||||
->with($notification);
|
||||
} else {
|
||||
$this->notificationManager->expects($this->never())
|
||||
->method('markProcessed');
|
||||
}
|
||||
|
||||
try {
|
||||
$this->invokePrivate($notifier, 'updateAlreadyInstalledCheck', [$notification, $versionInstalled]);
|
||||
$this->assertFalse($exception);
|
||||
} catch (\Exception $e) {
|
||||
$this->assertTrue($exception);
|
||||
$this->assertInstanceOf('InvalidArgumentException', $e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -157,6 +157,10 @@ class DIContainer extends SimpleContainer implements IAppContainer {
|
|||
return $this->getServer()->getGroupManager();
|
||||
});
|
||||
|
||||
$this->registerService('OCP\\Http\\Client\\IClientService', function() {
|
||||
return $this->getServer()->getHTTPClientService();
|
||||
});
|
||||
|
||||
$this->registerService('OCP\\IL10N', function($c) {
|
||||
return $this->getServer()->getL10N($c->query('AppName'));
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue