adjust backend and gui to update and changelog server
Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
This commit is contained in:
parent
4ed8ee1c1e
commit
25d9c3e529
|
@ -31,6 +31,8 @@ use OCP\AppFramework\Http\TemplateResponse;
|
|||
use OCP\IConfig;
|
||||
use OCP\IDateTimeFormatter;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IUserSession;
|
||||
use OCP\L10N\IFactory;
|
||||
use OCP\Settings\ISettings;
|
||||
use OCP\Util;
|
||||
|
||||
|
@ -43,21 +45,25 @@ class Admin implements ISettings {
|
|||
private $groupManager;
|
||||
/** @var IDateTimeFormatter */
|
||||
private $dateTimeFormatter;
|
||||
/** @var IUserSession */
|
||||
private $session;
|
||||
/** @var IFactory */
|
||||
private $l10nFactory;
|
||||
|
||||
/**
|
||||
* @param IConfig $config
|
||||
* @param UpdateChecker $updateChecker
|
||||
* @param IGroupManager $groupManager
|
||||
* @param IDateTimeFormatter $dateTimeFormatter
|
||||
*/
|
||||
public function __construct(IConfig $config,
|
||||
UpdateChecker $updateChecker,
|
||||
IGroupManager $groupManager,
|
||||
IDateTimeFormatter $dateTimeFormatter) {
|
||||
public function __construct(
|
||||
IConfig $config,
|
||||
UpdateChecker $updateChecker,
|
||||
IGroupManager $groupManager,
|
||||
IDateTimeFormatter $dateTimeFormatter,
|
||||
IUserSession $session,
|
||||
IFactory $l10nFactory
|
||||
) {
|
||||
$this->config = $config;
|
||||
$this->updateChecker = $updateChecker;
|
||||
$this->groupManager = $groupManager;
|
||||
$this->dateTimeFormatter = $dateTimeFormatter;
|
||||
$this->session = $session;
|
||||
$this->l10nFactory = $l10nFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,8 +99,7 @@ class Admin implements ISettings {
|
|||
'channels' => $channels,
|
||||
'newVersionString' => empty($updateState['updateVersion']) ? '' : $updateState['updateVersion'],
|
||||
'downloadLink' => empty($updateState['downloadLink']) ? '' : $updateState['downloadLink'],
|
||||
'changelogURL' => empty($updateState['changelog']) ? false : $updateState['changelog'],
|
||||
'whatsNew' => empty($updateState['whatsNew']) ? false : $updateState['whatsNew'],
|
||||
'changes' => $this->filterChanges($updateState['changes'] ?? []),
|
||||
'updaterEnabled' => empty($updateState['updaterEnabled']) ? false : $updateState['updaterEnabled'],
|
||||
'versionIsEol' => empty($updateState['versionIsEol']) ? false : $updateState['versionIsEol'],
|
||||
'isDefaultUpdateServerURL' => $updateServerURL === $defaultUpdateServerURL,
|
||||
|
@ -109,6 +114,48 @@ class Admin implements ISettings {
|
|||
return new TemplateResponse('updatenotification', 'admin', $params, '');
|
||||
}
|
||||
|
||||
protected function filterChanges(array $changes) {
|
||||
$filtered = [];
|
||||
if(isset($changes['changelogURL'])) {
|
||||
$filtered['changelogURL'] = $changes['changelogURL'];
|
||||
}
|
||||
if(!isset($changes['whatsNew'])) {
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
$isFirstCall = true;
|
||||
do {
|
||||
$lang = $this->l10nFactory->iterateLanguage($isFirstCall);
|
||||
if($this->findWhatsNewTranslation($lang, $filtered, $changes['whatsNew'])) {
|
||||
return $filtered;
|
||||
}
|
||||
$isFirstCall = false;
|
||||
} while($lang !== 'en');
|
||||
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
protected function getLangTrunk(string $lang):string {
|
||||
$pos = strpos($lang, '_');
|
||||
if($pos !== false) {
|
||||
$lang = substr($lang, 0, $pos);
|
||||
}
|
||||
return $lang;
|
||||
}
|
||||
|
||||
protected function findWhatsNewTranslation(string $lang, array &$result, array $whatsNew): bool {
|
||||
if(isset($whatsNew[$lang])) {
|
||||
$result['whatsNew'] = $whatsNew[$lang];
|
||||
return true;
|
||||
}
|
||||
$trunkedLang = $this->getLangTrunk($lang);
|
||||
if($trunkedLang !== $lang && isset($whatsNew[$trunkedLang])) {
|
||||
$result['whatsNew'] = $whatsNew[$trunkedLang];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $groupIds
|
||||
* @return array
|
||||
|
|
|
@ -25,17 +25,21 @@ declare(strict_types=1);
|
|||
|
||||
namespace OCA\UpdateNotification;
|
||||
|
||||
use OC\Updater\ChangesCheck;
|
||||
use OC\Updater\VersionCheck;
|
||||
|
||||
class UpdateChecker {
|
||||
/** @var VersionCheck */
|
||||
private $updater;
|
||||
/** @var ChangesCheck */
|
||||
private $changesCheck;
|
||||
|
||||
/**
|
||||
* @param VersionCheck $updater
|
||||
*/
|
||||
public function __construct(VersionCheck $updater) {
|
||||
public function __construct(VersionCheck $updater, ChangesCheck $changesCheck) {
|
||||
$this->updater = $updater;
|
||||
$this->changesCheck = $changesCheck;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,11 +60,12 @@ class UpdateChecker {
|
|||
if (strpos($data['url'], 'https://') === 0) {
|
||||
$result['downloadLink'] = $data['url'];
|
||||
}
|
||||
if (strpos($data['changelog'], 'https://') === 0) {
|
||||
$result['changelog'] = $data['changelog'];
|
||||
}
|
||||
if (is_array($data['whatsNew']) && count($data['whatsNew']) <= 3) {
|
||||
$result['whatsNew'] = $data['whatsNew'];
|
||||
if (strpos($data['changes'], 'https://') === 0) {
|
||||
try {
|
||||
$result['changes'] = $this->changesCheck->check($data['changes'], $data['version']);
|
||||
} catch (\Exception $e) {
|
||||
// no info, not a problem
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
|
|
@ -222,7 +222,9 @@
|
|||
},
|
||||
|
||||
whatsNew: function () {
|
||||
|
||||
if(this.whatsNewData.length === 0) {
|
||||
return null;
|
||||
}
|
||||
var whatsNew = [];
|
||||
for (var i in this.whatsNewData) {
|
||||
whatsNew[i] = { icon: 'icon-star-dark', longtext: this.whatsNewData[i] };
|
||||
|
@ -307,7 +309,6 @@
|
|||
beforeMount: function() {
|
||||
// Parse server data
|
||||
var data = JSON.parse($('#updatenotification').attr('data-json'));
|
||||
console.warn(data);
|
||||
|
||||
this.newVersionString = data.newVersionString;
|
||||
this.lastCheckedDate = data.lastChecked;
|
||||
|
@ -321,7 +322,15 @@
|
|||
this.notifyGroups = data.notifyGroups;
|
||||
this.isDefaultUpdateServerURL = data.isDefaultUpdateServerURL;
|
||||
this.versionIsEol = data.versionIsEol;
|
||||
this.whatsNewData = data.whatsNew;
|
||||
if(data.changes && data.changes.changelogURL) {
|
||||
this.changelogURL = data.changes.changelogURL;
|
||||
}
|
||||
if(data.changes && data.changes.whatsNew) {
|
||||
if(data.changes.whatsNew.admin) {
|
||||
this.whatsNewData = this.whatsNewData.concat(data.changes.whatsNew.admin);
|
||||
}
|
||||
this.whatsNewData = this.whatsNewData.concat(data.changes.whatsNew.regular);
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this._$el = $(this.$el);
|
||||
|
|
|
@ -99,8 +99,7 @@ class AdminTest extends TestCase {
|
|||
'updateAvailable' => true,
|
||||
'updateVersion' => '8.1.2',
|
||||
'downloadLink' => 'https://downloads.nextcloud.org/server',
|
||||
'changelog' => 'https://nextcloud.com/changelog/#8.1.2',
|
||||
'whatsNew' => ['Autoshare to mother-in-law', 'Faster backend', 'Sparkling frontend'],
|
||||
'changes' => 'https://updates.nextcloud.com/changelog_server/?version=8.1.2',
|
||||
'updaterEnabled' => true,
|
||||
'versionIsEol' => false,
|
||||
]);
|
||||
|
@ -126,8 +125,7 @@ class AdminTest extends TestCase {
|
|||
'channels' => $channels,
|
||||
'newVersionString' => '8.1.2',
|
||||
'downloadLink' => 'https://downloads.nextcloud.org/server',
|
||||
'changelogURL' => 'https://nextcloud.com/changelog/#8.1.2',
|
||||
'whatsNew' => ['Autoshare to mother-in-law', 'Faster backend', 'Sparkling frontend'],
|
||||
'changesURL' => 'https://updates.nextcloud.com/changelog_server/?version=8.1.2',
|
||||
'updaterEnabled' => true,
|
||||
'versionIsEol' => false,
|
||||
'isDefaultUpdateServerURL' => true,
|
||||
|
|
|
@ -25,11 +25,14 @@ declare(strict_types=1);
|
|||
|
||||
namespace OCA\UpdateNotification\Tests;
|
||||
|
||||
use OC\Updater\ChangesCheck;
|
||||
use OC\Updater\VersionCheck;
|
||||
use OCA\UpdateNotification\UpdateChecker;
|
||||
use Test\TestCase;
|
||||
|
||||
class UpdateCheckerTest extends TestCase {
|
||||
/** @var ChangesCheck|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $changesChecker;
|
||||
/** @var VersionCheck|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $updater;
|
||||
/** @var UpdateChecker */
|
||||
|
@ -39,7 +42,8 @@ class UpdateCheckerTest extends TestCase {
|
|||
parent::setUp();
|
||||
|
||||
$this->updater = $this->createMock(VersionCheck::class);
|
||||
$this->updateChecker = new UpdateChecker($this->updater);
|
||||
$this->changesChecker = $this->createMock(ChangesCheck::class);
|
||||
$this->updateChecker = new UpdateChecker($this->updater, $this->changesChecker);
|
||||
}
|
||||
|
||||
public function testGetUpdateStateWithUpdateAndInvalidLink() {
|
||||
|
@ -51,8 +55,7 @@ class UpdateCheckerTest extends TestCase {
|
|||
'versionstring' => 'Nextcloud 123',
|
||||
'web'=> 'javascript:alert(1)',
|
||||
'url'=> 'javascript:alert(2)',
|
||||
'changelog' => 'javascript:alert(3)',
|
||||
'whatsNew' => 'javascript:alert(4)',
|
||||
'changes' => 'javascript:alert(3)',
|
||||
'autoupdater'=> '0',
|
||||
'eol'=> '1',
|
||||
]);
|
||||
|
@ -67,20 +70,40 @@ class UpdateCheckerTest extends TestCase {
|
|||
}
|
||||
|
||||
public function testGetUpdateStateWithUpdateAndValidLink() {
|
||||
$changes = [
|
||||
'changelog' => 'https://nextcloud.com/changelog/#123-0-0',
|
||||
'whatsNew' => [
|
||||
'en' => [
|
||||
'regular' => [
|
||||
'Yardarm heave to brig spyglass smartly pillage',
|
||||
'Bounty gangway bilge skysail rope\'s end',
|
||||
'Maroon cutlass spirits nipperkin Plate Fleet',
|
||||
],
|
||||
'admin' => [
|
||||
'Scourge of the seven seas coffer doubloon',
|
||||
'Brig me splice the main brace',
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$this->updater
|
||||
->expects($this->once())
|
||||
->method('check')
|
||||
->willReturn([
|
||||
'version' => 123,
|
||||
'version' => '123',
|
||||
'versionstring' => 'Nextcloud 123',
|
||||
'web'=> 'https://docs.nextcloud.com/myUrl',
|
||||
'url'=> 'https://downloads.nextcloud.org/server',
|
||||
'changelog' => 'https://nextcloud.com/changelog/#123.0.0',
|
||||
'whatsNew' => ['Brews coffee', 'Makes appointments', 'Orchestrates Terminators'],
|
||||
'changes' => 'https://updates.nextcloud.com/changelog_server/?version=123.0.0',
|
||||
'autoupdater'=> '1',
|
||||
'eol'=> '0',
|
||||
]);
|
||||
|
||||
$this->changesChecker->expects($this->once())
|
||||
->method('check')
|
||||
->willReturn($changes);
|
||||
|
||||
$expected = [
|
||||
'updateAvailable' => true,
|
||||
'updateVersion' => 'Nextcloud 123',
|
||||
|
@ -88,8 +111,7 @@ class UpdateCheckerTest extends TestCase {
|
|||
'versionIsEol' => false,
|
||||
'updateLink' => 'https://docs.nextcloud.com/myUrl',
|
||||
'downloadLink' => 'https://downloads.nextcloud.org/server',
|
||||
'changelog' => 'https://nextcloud.com/changelog/#123.0.0',
|
||||
'whatsNew' => ['Brews coffee', 'Makes appointments', 'Orchestrates Terminators'],
|
||||
'changes' => $changes,
|
||||
];
|
||||
$this->assertSame($expected, $this->updateChecker->getUpdateState());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @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\Core\Migrations;
|
||||
|
||||
use OCP\DB\ISchemaWrapper;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
|
||||
class Version14000Date20180626223656 extends SimpleMigrationStep {
|
||||
public function changeSchema(\OCP\Migration\IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
if(!$schema->hasTable('whats_new')) {
|
||||
$table = $schema->createTable('whats_new');
|
||||
$table->addColumn('version', 'string', [
|
||||
'notnull' => true,
|
||||
'length' => 64,
|
||||
'default' => '11',
|
||||
]);
|
||||
$table->addColumn('etag', 'string', [
|
||||
'notnull' => true,
|
||||
'length' => 64,
|
||||
'default' => '',
|
||||
]);
|
||||
$table->addColumn('last_check', 'integer', [
|
||||
'notnull' => true,
|
||||
'length' => 4,
|
||||
'unsigned' => true,
|
||||
'default' => 0,
|
||||
]);
|
||||
$table->addColumn('data', 'text', [
|
||||
'notnull' => true,
|
||||
'default' => '',
|
||||
]);
|
||||
$table->setPrimaryKey(['version']);
|
||||
$table->addIndex(['version', 'etag'], 'version_etag_idx');
|
||||
}
|
||||
|
||||
return $schema;
|
||||
}
|
||||
}
|
|
@ -595,6 +595,7 @@ return array(
|
|||
'OC\\Core\\Migrations\\Version14000Date20180516101403' => $baseDir . '/core/Migrations/Version14000Date20180516101403.php',
|
||||
'OC\\Core\\Migrations\\Version14000Date20180518120534' => $baseDir . '/core/Migrations/Version14000Date20180518120534.php',
|
||||
'OC\\Core\\Migrations\\Version14000Date20180522074438' => $baseDir . '/core/Migrations/Version14000Date20180522074438.php',
|
||||
'OC\\Core\\Migrations\\Version14000Date20180626223656' => $baseDir . '/core/Migrations/Version14000Date20180626223656.php',
|
||||
'OC\\DB\\Adapter' => $baseDir . '/lib/private/DB/Adapter.php',
|
||||
'OC\\DB\\AdapterMySQL' => $baseDir . '/lib/private/DB/AdapterMySQL.php',
|
||||
'OC\\DB\\AdapterOCI8' => $baseDir . '/lib/private/DB/AdapterOCI8.php',
|
||||
|
@ -1003,6 +1004,9 @@ return array(
|
|||
'OC\\Template\\TemplateFileLocator' => $baseDir . '/lib/private/Template/TemplateFileLocator.php',
|
||||
'OC\\URLGenerator' => $baseDir . '/lib/private/URLGenerator.php',
|
||||
'OC\\Updater' => $baseDir . '/lib/private/Updater.php',
|
||||
'OC\\Updater\\ChangesCheck' => $baseDir . '/lib/private/Updater/ChangesCheck.php',
|
||||
'OC\\Updater\\ChangesMapper' => $baseDir . '/lib/private/Updater/ChangesMapper.php',
|
||||
'OC\\Updater\\ChangesResult' => $baseDir . '/lib/private/Updater/ChangesResult.php',
|
||||
'OC\\Updater\\VersionCheck' => $baseDir . '/lib/private/Updater/VersionCheck.php',
|
||||
'OC\\User\\Backend' => $baseDir . '/lib/private/User/Backend.php',
|
||||
'OC\\User\\Database' => $baseDir . '/lib/private/User/Database.php',
|
||||
|
|
|
@ -625,6 +625,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
|
|||
'OC\\Core\\Migrations\\Version14000Date20180516101403' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180516101403.php',
|
||||
'OC\\Core\\Migrations\\Version14000Date20180518120534' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180518120534.php',
|
||||
'OC\\Core\\Migrations\\Version14000Date20180522074438' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180522074438.php',
|
||||
'OC\\Core\\Migrations\\Version14000Date20180626223656' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180626223656.php',
|
||||
'OC\\DB\\Adapter' => __DIR__ . '/../../..' . '/lib/private/DB/Adapter.php',
|
||||
'OC\\DB\\AdapterMySQL' => __DIR__ . '/../../..' . '/lib/private/DB/AdapterMySQL.php',
|
||||
'OC\\DB\\AdapterOCI8' => __DIR__ . '/../../..' . '/lib/private/DB/AdapterOCI8.php',
|
||||
|
@ -1033,6 +1034,9 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
|
|||
'OC\\Template\\TemplateFileLocator' => __DIR__ . '/../../..' . '/lib/private/Template/TemplateFileLocator.php',
|
||||
'OC\\URLGenerator' => __DIR__ . '/../../..' . '/lib/private/URLGenerator.php',
|
||||
'OC\\Updater' => __DIR__ . '/../../..' . '/lib/private/Updater.php',
|
||||
'OC\\Updater\\ChangesCheck' => __DIR__ . '/../../..' . '/lib/private/Updater/ChangesCheck.php',
|
||||
'OC\\Updater\\ChangesMapper' => __DIR__ . '/../../..' . '/lib/private/Updater/ChangesMapper.php',
|
||||
'OC\\Updater\\ChangesResult' => __DIR__ . '/../../..' . '/lib/private/Updater/ChangesResult.php',
|
||||
'OC\\Updater\\VersionCheck' => __DIR__ . '/../../..' . '/lib/private/Updater/VersionCheck.php',
|
||||
'OC\\User\\Backend' => __DIR__ . '/../../..' . '/lib/private/User/Backend.php',
|
||||
'OC\\User\\Database' => __DIR__ . '/../../..' . '/lib/private/User/Database.php',
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace OC\L10N;
|
|||
|
||||
use OCP\IConfig;
|
||||
use OCP\IRequest;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserSession;
|
||||
use OCP\L10N\IFactory;
|
||||
|
||||
|
@ -321,6 +322,37 @@ class Factory implements IFactory {
|
|||
return array_search($lang, $languages) !== false;
|
||||
}
|
||||
|
||||
public function iterateLanguage(bool $reset = false): string {
|
||||
static $i = 0;
|
||||
if($reset) {
|
||||
$i = 0;
|
||||
}
|
||||
switch($i) {
|
||||
/** @noinspection PhpMissingBreakStatementInspection */
|
||||
case 0:
|
||||
$i++;
|
||||
$forcedLang = $this->config->getSystemValue('force_language', false);
|
||||
if(is_string($forcedLang)) {
|
||||
return $forcedLang;
|
||||
}
|
||||
/** @noinspection PhpMissingBreakStatementInspection */
|
||||
case 1:
|
||||
$i++;
|
||||
$user = $this->userSession->getUser();
|
||||
if($user instanceof IUser) {
|
||||
$userLang = $this->config->getUserValue($user->getUID(), 'core', 'lang', null);
|
||||
if(is_string($userLang)) {
|
||||
return $userLang;
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
$i++;
|
||||
return $this->config->getSystemValue('default_language', 'en');
|
||||
default:
|
||||
return 'en';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $locale
|
||||
* @return bool
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @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\Updater;
|
||||
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\Http\Client\IClientService;
|
||||
use OCP\Http\Client\IResponse;
|
||||
use OCP\ILogger;
|
||||
|
||||
class ChangesCheck {
|
||||
/** @var IClientService */
|
||||
protected $clientService;
|
||||
/** @var ChangesMapper */
|
||||
private $mapper;
|
||||
/** @var ILogger */
|
||||
private $logger;
|
||||
|
||||
const RESPONSE_NO_CONTENT = 0;
|
||||
const RESPONSE_USE_CACHE = 1;
|
||||
const RESPONSE_HAS_CONTENT = 2;
|
||||
|
||||
public function __construct(IClientService $clientService, ChangesMapper $mapper, ILogger $logger) {
|
||||
$this->clientService = $clientService;
|
||||
$this->mapper = $mapper;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function check(string $uri, string $version): array {
|
||||
try {
|
||||
$version = $this->normalizeVersion($version);
|
||||
$changesInfo = $this->mapper->getChanges($version);
|
||||
if($changesInfo->getLastCheck() + 1800 > time()) {
|
||||
return json_decode($changesInfo->getData(), true);
|
||||
}
|
||||
} catch (DoesNotExistException $e) {
|
||||
$changesInfo = new ChangesResult();
|
||||
}
|
||||
|
||||
$response = $this->queryChangesServer($uri, $changesInfo);
|
||||
|
||||
switch($this->evaluateResponse($response)) {
|
||||
case self::RESPONSE_NO_CONTENT:
|
||||
return [];
|
||||
case self::RESPONSE_USE_CACHE:
|
||||
return json_decode($changesInfo->getData(), true);
|
||||
case self::RESPONSE_HAS_CONTENT:
|
||||
default:
|
||||
$data = $this->extractData($response->getBody());
|
||||
$changesInfo->setData(json_encode($data));
|
||||
$changesInfo->setEtag($response->getHeader('Etag'));
|
||||
$this->cacheResult($changesInfo, $version);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
protected function evaluateResponse(IResponse $response): int {
|
||||
if($response->getStatusCode() === 304) {
|
||||
return self::RESPONSE_USE_CACHE;
|
||||
} else if($response->getStatusCode() === 404) {
|
||||
return self::RESPONSE_NO_CONTENT;
|
||||
} else if($response->getStatusCode() === 200) {
|
||||
return self::RESPONSE_HAS_CONTENT;
|
||||
}
|
||||
$this->logger->debug('Unexpected return code {code} from changelog server', [
|
||||
'app' => 'core',
|
||||
'code' => $response->getStatusCode(),
|
||||
]);
|
||||
return self::RESPONSE_NO_CONTENT;
|
||||
}
|
||||
|
||||
protected function cacheResult(ChangesResult $entry, string $version) {
|
||||
if($entry->getVersion() === $version) {
|
||||
$this->mapper->update($entry);
|
||||
} else {
|
||||
$entry->setVersion($version);
|
||||
$this->mapper->insert($entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function queryChangesServer(string $uri, ChangesResult $entry): IResponse {
|
||||
$headers = [];
|
||||
if($entry->getEtag() !== '') {
|
||||
$headers['If-None-Match'] = [$entry->getEtag()];
|
||||
}
|
||||
|
||||
$entry->setLastCheck(time());
|
||||
$client = $this->clientService->newClient();
|
||||
return $client->get($uri, [
|
||||
'headers' => $headers,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function extractData($body):array {
|
||||
$data = [];
|
||||
if ($body) {
|
||||
$loadEntities = libxml_disable_entity_loader(true);
|
||||
$xml = @simplexml_load_string($body);
|
||||
libxml_disable_entity_loader($loadEntities);
|
||||
if ($xml !== false) {
|
||||
$data['changelogURL'] = (string)$xml->changelog['href'];
|
||||
$data['whatsNew'] = [];
|
||||
foreach($xml->whatsNew as $infoSet) {
|
||||
$data['whatsNew'][(string)$infoSet['lang']] = [
|
||||
'regular' => (array)$infoSet->regular->item,
|
||||
'admin' => (array)$infoSet->admin->item,
|
||||
];
|
||||
}
|
||||
} else {
|
||||
libxml_clear_errors();
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a x.y.z form of the provided version. Extra numbers will be
|
||||
* omitted, missing ones added as zeros.
|
||||
*/
|
||||
protected function normalizeVersion(string $version): string {
|
||||
$versionNumbers = array_slice(explode('.', $version), 0, 3);
|
||||
$versionNumbers[0] = $versionNumbers[0] ?: '0'; // deal with empty input
|
||||
while(count($versionNumbers) < 3) {
|
||||
// changelog server expects x.y.z, pad 0 if it is too short
|
||||
$versionNumbers[] = 0;
|
||||
}
|
||||
return implode('.', $versionNumbers);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @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\Updater;
|
||||
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\QBMapper;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
class ChangesMapper extends QBMapper {
|
||||
const TABLE_NAME = 'whats_new';
|
||||
|
||||
public function __construct(IDBConnection $db) {
|
||||
parent::__construct($db, self::TABLE_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws DoesNotExistException
|
||||
*/
|
||||
public function getChanges(string $version): ChangesResult {
|
||||
/* @var $qb IQueryBuilder */
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$result = $qb->select('*')
|
||||
->from(self::TABLE_NAME)
|
||||
->where($qb->expr()->eq('version', $qb->createNamedParameter($version)))
|
||||
->execute();
|
||||
|
||||
$data = $result->fetch();
|
||||
$result->closeCursor();
|
||||
if ($data === false) {
|
||||
throw new DoesNotExistException('Changes info is not present');
|
||||
}
|
||||
return ChangesResult::fromRow($data);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @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\Updater;
|
||||
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
|
||||
/**
|
||||
* Class ChangesResult
|
||||
*
|
||||
* @package OC\Updater
|
||||
* @method string getVersion()=1
|
||||
* @method void setVersion(string $version)
|
||||
* @method string getEtag()
|
||||
* @method void setEtag(string $etag)
|
||||
* @method int getLastCheck()
|
||||
* @method void setLastCheck(int $lastCheck)
|
||||
* @method string getData()
|
||||
* @method void setData(string $data)
|
||||
*/
|
||||
class ChangesResult extends Entity {
|
||||
/** @var string */
|
||||
protected $version = '';
|
||||
|
||||
/** @var string */
|
||||
protected $etag = '';
|
||||
|
||||
/** @var int */
|
||||
protected $lastCheck = 0;
|
||||
|
||||
/** @var string */
|
||||
protected $data = '';
|
||||
|
||||
public function __construct() {
|
||||
$this->addType('version', 'string');
|
||||
$this->addType('etag', 'string');
|
||||
$this->addType('lastCheck', 'int');
|
||||
$this->addType('data', 'string');
|
||||
}
|
||||
}
|
|
@ -55,7 +55,7 @@ class VersionCheck {
|
|||
*/
|
||||
public function check() {
|
||||
// Look up the cache - it is invalidated all 30 minutes
|
||||
if (false && ((int)$this->config->getAppValue('core', 'lastupdatedat') + 1800) > time()) {
|
||||
if (((int)$this->config->getAppValue('core', 'lastupdatedat') + 1800) > time()) {
|
||||
return json_decode($this->config->getAppValue('core', 'lastupdateResult'), true);
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ class VersionCheck {
|
|||
$version = Util::getVersion();
|
||||
$version['installed'] = $this->config->getAppValue('core', 'installedat');
|
||||
$version['updated'] = $this->config->getAppValue('core', 'lastupdatedat');
|
||||
$version['updatechannel'] = 'stable'; //\OC_Util::getChannel();
|
||||
$version['updatechannel'] = \OC_Util::getChannel();
|
||||
$version['edition'] = '';
|
||||
$version['build'] = \OC_Util::getBuild();
|
||||
$version['php_major'] = PHP_MAJOR_VERSION;
|
||||
|
@ -97,10 +97,7 @@ class VersionCheck {
|
|||
$tmp['versionstring'] = (string)$data->versionstring;
|
||||
$tmp['url'] = (string)$data->url;
|
||||
$tmp['web'] = (string)$data->web;
|
||||
$tmp['changelog'] = isset($data->changelog) ? (string)$data->changelog : '';
|
||||
// TODO: one's it is decided, use the proper field…
|
||||
$tmp['whatsNew'] = isset($data->whatsNew) ? ((array)$data->whatsNew)['item'] : null;
|
||||
$tmp['whatsNew'] = isset($data->whatsNew_admin) ? ((array)$data->whatsNew_admin)['item'] : (string)$data->whatsNew;
|
||||
$tmp['changes'] = isset($data->changes) ? (string)$data->changes : '';
|
||||
$tmp['autoupdater'] = (string)$data->autoupdater;
|
||||
$tmp['eol'] = isset($data->eol) ? (string)$data->eol : '0';
|
||||
} else {
|
||||
|
|
|
@ -89,4 +89,14 @@ interface IFactory {
|
|||
* @since 14.0.0
|
||||
*/
|
||||
public function createPluralFunction($string);
|
||||
|
||||
/**
|
||||
* iterate through language settings (if provided) in this order:
|
||||
* 1. returns the forced language or:
|
||||
* 2. returns the user language or:
|
||||
* 3. returns the system default language or:
|
||||
* 4+∞. returns 'en'
|
||||
* @since 14.0.0
|
||||
*/
|
||||
public function iterateLanguage(bool $reset = false): string;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,344 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @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\Updater;
|
||||
|
||||
use OC\Updater\ChangesCheck;
|
||||
use OC\Updater\ChangesMapper;
|
||||
use OC\Updater\ChangesResult;
|
||||
use OCP\Http\Client\IClient;
|
||||
use OCP\Http\Client\IClientService;
|
||||
use OCP\Http\Client\IResponse;
|
||||
use OCP\ILogger;
|
||||
use const Solarium\QueryType\Select\Query\Component\Facet\INCLUDE_LOWER;
|
||||
use Test\TestCase;
|
||||
|
||||
class ChangesCheckTest extends TestCase {
|
||||
/** @var IClientService|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $clientService;
|
||||
|
||||
/** @var ChangesCheck */
|
||||
protected $checker;
|
||||
|
||||
/** @var ChangesMapper|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $mapper;
|
||||
|
||||
/** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $logger;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->clientService = $this->createMock(IClientService::class);
|
||||
$this->mapper = $this->createMock(ChangesMapper::class);
|
||||
$this->logger = $this->createMock(ILogger::class);
|
||||
|
||||
$this->checker = new ChangesCheck($this->clientService, $this->mapper, $this->logger);
|
||||
}
|
||||
|
||||
public function statusCodeProvider():array {
|
||||
return [
|
||||
[200, ChangesCheck::RESPONSE_HAS_CONTENT],
|
||||
[304, ChangesCheck::RESPONSE_USE_CACHE],
|
||||
[404, ChangesCheck::RESPONSE_NO_CONTENT],
|
||||
[418, ChangesCheck::RESPONSE_NO_CONTENT],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider statusCodeProvider
|
||||
*/
|
||||
public function testEvaluateResponse(int $statusCode, int $expected) {
|
||||
$response = $this->createMock(IResponse::class);
|
||||
$response->expects($this->atLeastOnce())
|
||||
->method('getStatusCode')
|
||||
->willReturn($statusCode);
|
||||
|
||||
if(!in_array($statusCode, [200, 304, 404])) {
|
||||
$this->logger->expects($this->once())
|
||||
->method('debug');
|
||||
}
|
||||
|
||||
$evaluation = $this->invokePrivate($this->checker, 'evaluateResponse', [$response]);
|
||||
$this->assertSame($expected, $evaluation);
|
||||
}
|
||||
|
||||
public function testCacheResultInsert() {
|
||||
$version = '13.0.4';
|
||||
$entry = $this->createMock(ChangesResult::class);
|
||||
$entry->expects($this->exactly(2))
|
||||
->method('__call')
|
||||
->withConsecutive(['getVersion'], ['setVersion', [$version]])
|
||||
->willReturnOnConsecutiveCalls('', null);
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('insert');
|
||||
$this->mapper->expects($this->never())
|
||||
->method('update');
|
||||
|
||||
$this->invokePrivate($this->checker, 'cacheResult', [$entry, $version]);
|
||||
}
|
||||
|
||||
public function testCacheResultUpdate() {
|
||||
$version = '13.0.4';
|
||||
$entry = $this->createMock(ChangesResult::class);
|
||||
$entry->expects($this->once())
|
||||
->method('__call')
|
||||
->willReturn($version);
|
||||
|
||||
$this->mapper->expects($this->never())
|
||||
->method('insert');
|
||||
$this->mapper->expects($this->once())
|
||||
->method('update');
|
||||
|
||||
$this->invokePrivate($this->checker, 'cacheResult', [$entry, $version]);
|
||||
}
|
||||
|
||||
public function changesXMLProvider(): array {
|
||||
return [
|
||||
[ # 0 - full example
|
||||
'<?xml version="1.0" encoding="utf-8" ?>
|
||||
<release xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://updates.nextcloud.com/changelog_server/schema.xsd"
|
||||
version="13.0.0">
|
||||
<changelog href="https://nextcloud.com/changelog/#13-0-0"/>
|
||||
<whatsNew lang="en">
|
||||
<regular>
|
||||
<item>Refined user interface</item>
|
||||
<item>End-to-end Encryption</item>
|
||||
<item>Video and Text Chat</item>
|
||||
</regular>
|
||||
<admin>
|
||||
<item>Changes to the Nginx configuration</item>
|
||||
<item>Theming: CSS files were consolidated</item>
|
||||
</admin>
|
||||
</whatsNew>
|
||||
<whatsNew lang="de">
|
||||
<regular>
|
||||
<item>Überarbeitete Benutzerschnittstelle</item>
|
||||
<item>Ende-zu-Ende Verschlüsselung</item>
|
||||
<item>Video- und Text-Chat</item>
|
||||
</regular>
|
||||
<admin>
|
||||
<item>Änderungen an der Nginx Konfiguration</item>
|
||||
<item>Theming: CSS Dateien wurden konsolidiert</item>
|
||||
</admin>
|
||||
</whatsNew>
|
||||
</release>',
|
||||
[
|
||||
'changelogURL' => 'https://nextcloud.com/changelog/#13-0-0',
|
||||
'whatsNew' => [
|
||||
'en' => [
|
||||
'regular' => [
|
||||
'Refined user interface',
|
||||
'End-to-end Encryption',
|
||||
'Video and Text Chat'
|
||||
],
|
||||
'admin' => [
|
||||
'Changes to the Nginx configuration',
|
||||
'Theming: CSS files were consolidated'
|
||||
],
|
||||
],
|
||||
'de' => [
|
||||
'regular' => [
|
||||
'Überarbeitete Benutzerschnittstelle',
|
||||
'Ende-zu-Ende Verschlüsselung',
|
||||
'Video- und Text-Chat'
|
||||
],
|
||||
'admin' => [
|
||||
'Änderungen an der Nginx Konfiguration',
|
||||
'Theming: CSS Dateien wurden konsolidiert'
|
||||
],
|
||||
],
|
||||
],
|
||||
]
|
||||
],
|
||||
[ # 1- admin part not translated
|
||||
'<?xml version="1.0" encoding="utf-8" ?>
|
||||
<release xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://updates.nextcloud.com/changelog_server/schema.xsd"
|
||||
version="13.0.0">
|
||||
<changelog href="https://nextcloud.com/changelog/#13-0-0"/>
|
||||
<whatsNew lang="en">
|
||||
<regular>
|
||||
<item>Refined user interface</item>
|
||||
<item>End-to-end Encryption</item>
|
||||
<item>Video and Text Chat</item>
|
||||
</regular>
|
||||
<admin>
|
||||
<item>Changes to the Nginx configuration</item>
|
||||
<item>Theming: CSS files were consolidated</item>
|
||||
</admin>
|
||||
</whatsNew>
|
||||
<whatsNew lang="de">
|
||||
<regular>
|
||||
<item>Überarbeitete Benutzerschnittstelle</item>
|
||||
<item>Ende-zu-Ende Verschlüsselung</item>
|
||||
<item>Video- und Text-Chat</item>
|
||||
</regular>
|
||||
</whatsNew>
|
||||
</release>',
|
||||
[
|
||||
'changelogURL' => 'https://nextcloud.com/changelog/#13-0-0',
|
||||
'whatsNew' => [
|
||||
'en' => [
|
||||
'regular' => [
|
||||
'Refined user interface',
|
||||
'End-to-end Encryption',
|
||||
'Video and Text Chat'
|
||||
],
|
||||
'admin' => [
|
||||
'Changes to the Nginx configuration',
|
||||
'Theming: CSS files were consolidated'
|
||||
],
|
||||
],
|
||||
'de' => [
|
||||
'regular' => [
|
||||
'Überarbeitete Benutzerschnittstelle',
|
||||
'Ende-zu-Ende Verschlüsselung',
|
||||
'Video- und Text-Chat'
|
||||
],
|
||||
'admin' => [
|
||||
],
|
||||
],
|
||||
],
|
||||
]
|
||||
],
|
||||
[ # 2 - minimal set
|
||||
'<?xml version="1.0" encoding="utf-8" ?>
|
||||
<release xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://updates.nextcloud.com/changelog_server/schema.xsd"
|
||||
version="13.0.0">
|
||||
<changelog href="https://nextcloud.com/changelog/#13-0-0"/>
|
||||
<whatsNew lang="en">
|
||||
<regular>
|
||||
<item>Refined user interface</item>
|
||||
<item>End-to-end Encryption</item>
|
||||
<item>Video and Text Chat</item>
|
||||
</regular>
|
||||
</whatsNew>
|
||||
</release>',
|
||||
[
|
||||
'changelogURL' => 'https://nextcloud.com/changelog/#13-0-0',
|
||||
'whatsNew' => [
|
||||
'en' => [
|
||||
'regular' => [
|
||||
'Refined user interface',
|
||||
'End-to-end Encryption',
|
||||
'Video and Text Chat'
|
||||
],
|
||||
'admin' => [],
|
||||
],
|
||||
],
|
||||
]
|
||||
],
|
||||
[ # 3 - minimal set (procrastinator edition)
|
||||
'<?xml version="1.0" encoding="utf-8" ?>
|
||||
<release xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://updates.nextcloud.com/changelog_server/schema.xsd"
|
||||
version="13.0.0">
|
||||
<changelog href="https://nextcloud.com/changelog/#13-0-0"/>
|
||||
<whatsNew lang="en">
|
||||
<regular>
|
||||
<item>Write this tomorrow</item>
|
||||
</regular>
|
||||
</whatsNew>
|
||||
</release>',
|
||||
[
|
||||
'changelogURL' => 'https://nextcloud.com/changelog/#13-0-0',
|
||||
'whatsNew' => [
|
||||
'en' => [
|
||||
'regular' => [
|
||||
'Write this tomorrow',
|
||||
],
|
||||
'admin' => [],
|
||||
],
|
||||
],
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider changesXMLProvider
|
||||
*/
|
||||
public function testExtractData(string $body, array $expected) {
|
||||
$actual = $this->invokePrivate($this->checker, 'extractData', [$body]);
|
||||
$this->assertSame($expected, $actual);
|
||||
}
|
||||
|
||||
public function etagProvider() {
|
||||
return [
|
||||
[''],
|
||||
['a27aab83d8205d73978435076e53d143']
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider etagProvider
|
||||
*/
|
||||
public function testQueryChangesServer(string $etag) {
|
||||
$uri = 'https://changes.nextcloud.server/?13.0.5';
|
||||
$entry = $this->createMock(ChangesResult::class);
|
||||
$entry->expects($this->any())
|
||||
->method('__call')
|
||||
->willReturn($etag);
|
||||
|
||||
$expectedHeaders = $etag === '' ? [] : ['If-None-Match: ' . $etag];
|
||||
|
||||
$client = $this->createMock(IClient::class);
|
||||
$client->expects($this->once())
|
||||
->method('get')
|
||||
->with($uri, ['headers' => $expectedHeaders])
|
||||
->willReturn($this->createMock(IResponse::class));
|
||||
|
||||
$this->clientService->expects($this->once())
|
||||
->method('newClient')
|
||||
->willReturn($client);
|
||||
|
||||
$response = $this->invokePrivate($this->checker, 'queryChangesServer', [$uri, $entry]);
|
||||
$this->assertInstanceOf(IResponse::class, $response);
|
||||
}
|
||||
|
||||
public function versionProvider(): array {
|
||||
return [
|
||||
['13.0.7', '13.0.7'],
|
||||
['13.0.7.3', '13.0.7'],
|
||||
['13.0.7.3.42', '13.0.7'],
|
||||
['13.0', '13.0.0'],
|
||||
['13', '13.0.0'],
|
||||
['', '0.0.0'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider versionProvider
|
||||
*/
|
||||
public function testNormalizeVersion(string $input, string $expected) {
|
||||
$normalized = $this->invokePrivate($this->checker, 'normalizeVersion', [$input]);
|
||||
$this->assertSame($expected, $normalized);
|
||||
}
|
||||
}
|
|
@ -62,6 +62,7 @@ class VersionCheckTest extends \Test\TestCase {
|
|||
'versionstring' => 'ownCloud 8.0.4',
|
||||
'url' => 'https://download.example.org/community/owncloud-8.0.4.zip',
|
||||
'web' => 'http://doc.example.org/server/8.0/admin_manual/maintenance/upgrade.html',
|
||||
'changes' => '',
|
||||
];
|
||||
|
||||
$this->config
|
||||
|
@ -84,8 +85,7 @@ class VersionCheckTest extends \Test\TestCase {
|
|||
'versionstring' => 'ownCloud 8.0.4',
|
||||
'url' => 'https://download.example.org/community/owncloud-8.0.4.zip',
|
||||
'web' => 'http://doc.example.org/server/8.0/admin_manual/maintenance/upgrade.html',
|
||||
'changelog' => '',
|
||||
'whatsNew' => '',
|
||||
'changes' => '',
|
||||
'autoupdater' => '0',
|
||||
'eol' => '1',
|
||||
];
|
||||
|
@ -183,8 +183,7 @@ class VersionCheckTest extends \Test\TestCase {
|
|||
'versionstring' => '',
|
||||
'url' => '',
|
||||
'web' => '',
|
||||
'changelog' => '',
|
||||
'whatsNew' => '',
|
||||
'changes' => '',
|
||||
'autoupdater' => '',
|
||||
'eol' => '0',
|
||||
];
|
||||
|
@ -279,8 +278,7 @@ class VersionCheckTest extends \Test\TestCase {
|
|||
'versionstring' => '',
|
||||
'url' => '',
|
||||
'web' => '',
|
||||
'changelog' => '',
|
||||
'whatsNew' => '',
|
||||
'changes' => '',
|
||||
'autoupdater' => '',
|
||||
'eol' => '0',
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue