%PDF- %PDF-
Direktori : /www/varak.net/nextcloud.varak.net/apps_old/apps/passwords/lib/Fetcher/ |
Current File : //www/varak.net/nextcloud.varak.net/apps_old/apps/passwords/lib/Fetcher/NightlyAppFetcher.php |
<?php /** * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch> * * @author Joas Schilling <coding@schilljs.com> * @author Lukas Reschke <lukas@statuscode.ch> * @author Morris Jobke <hey@morrisjobke.de> * @author Roeland Jago Douma <roeland@famdouma.nl> * * @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 OCA\Passwords\Fetcher; use Exception; use OC\App\AppStore\Fetcher\Fetcher; use OC\App\AppStore\Version\VersionParser; use OC\App\CompareVersion; use OC\Files\AppData\Factory; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Http\Client\IClientService; use OCP\IConfig; use OCP\ILogger; use OCP\Support\Subscription\IRegistry; use Psr\Log\LoggerInterface; use Throwable; /** * Class NightlyAppFetcher * * @package OCA\Passwords\Fetcher */ class NightlyAppFetcher extends Fetcher { /** * @var LoggerInterface */ protected LoggerInterface $psrLogger; /** * @var CompareVersion */ protected CompareVersion $compareVersion; /** * @var bool */ protected bool $ignoreMaxVersion; /** * @var bool */ protected bool $dbUpdated; /** * @param Factory $appDataFactory * @param IClientService $clientService * @param ITimeFactory $timeFactory * @param IConfig $config * @param CompareVersion $compareVersion * @param LoggerInterface $logger */ public function __construct( Factory $appDataFactory, IClientService $clientService, ITimeFactory $timeFactory, IConfig $config, CompareVersion $compareVersion, LoggerInterface $logger, IRegistry $registry ) { $parentLogger = $logger; parent::__construct( $appDataFactory, $clientService, $timeFactory, $config, $parentLogger, $registry ); $this->dbUpdated = false; $this->fileName = 'apps_nightly.json'; $this->endpointName = 'apps.json'; $this->ignoreMaxVersion = true; $this->psrLogger = $logger; $this->compareVersion = $compareVersion; } /** * Returns the array with the apps on the appstore server * * @param bool $allowUnstable * * @return array */ public function get($allowUnstable = false) { $this->dbUpdated = false; $eTag = $this->prepareAppDbForUpdate(); $result = parent::get($allowUnstable); $this->updateAppDbAfterUpdate($eTag); return $result; } /** * */ public function clearDb(): void { try { $this->config->deleteAppValue('passwords', 'nightly/etag'); $rootFolder = $this->appData->getFolder('/'); $file = $rootFolder->getFile($this->fileName); $file->delete(); $file = $rootFolder->getFile('apps.json'); $file->delete(); } catch(Exception $e) { $this->logException($e); } } /** * @return bool */ public function isDbUpdated(): bool { return $this->dbUpdated; } /** * Only returns the latest compatible app release in the releases array * * @param string $ETag * @param string $content * * @return array * @throws Exception */ protected function fetch($ETag, $content, $allowUnstable = false) { $json = parent::fetch($ETag, $content); if(!isset($json['data'])) return $json; foreach($json['data'] as $dataKey => $app) { $latest = null; if(empty($app['releases'])) continue; foreach($app['releases'] as $release) { if(($latest === null || version_compare($latest['version'], $release['version']) < 0) && $this->releaseAllowedInChannel($release, $app['id'], $allowUnstable) && $this->checkNextcloudRequirements($release) && $this->checkPhpRequirements($release)) { $latest = $release; } } if($latest !== null) { $json['data'][ $dataKey ]['releases'] = [$latest]; } else { unset($json['data'][ $dataKey ]); } } $json['data'] = array_values($json['data']); return $json; } /** * @param string $version * @param string $fileName * @param bool $ignoreMaxVersion */ public function setVersion(string $version, string $fileName = 'apps.json', bool $ignoreMaxVersion = true) { parent::setVersion($version); $this->ignoreMaxVersion = $ignoreMaxVersion; } /** * @param $release * @param $app * @param $allowUnstable * * @return bool */ protected function releaseAllowedInChannel($release, $app, $allowUnstable): bool { $isPreRelease = strpos($release['version'], '-'); $allowNightly = $allowUnstable|| $this->getChannel() === 'daily' || $app === 'passwords'; $allowPreReleases = $this->getChannel() === 'beta' || $allowNightly; return (!$isPreRelease && !$release['isNightly']) || ($allowNightly && $release['isNightly']) || ($allowPreReleases && $isPreRelease); } /** * @return string */ protected function prepareAppDbForUpdate(): string { try { $rootFolder = $this->appData->getFolder('/'); if(!$rootFolder->fileExists($this->fileName)) return ''; $file = $rootFolder->getFile($this->fileName); return $file->getETag(); } catch(Exception $e) { $this->logger->emergency($e, ['app' => 'nightlyAppstoreFetcher', 'level' => ILogger::WARN]); return ''; } } /** * @param $nightlyEtag */ protected function updateAppDbAfterUpdate($nightlyEtag): void { try { $appEtag = $this->config->getAppValue('passwords', 'nightly/etag', ''); $rootFolder = $this->appData->getFolder('/'); $nightlyDb = $rootFolder->getFile($this->fileName); if($rootFolder->fileExists('apps.json')) { $appDb = $rootFolder->getFile('apps.json'); } else { $appDb = $rootFolder->newFile('apps.json'); } if($nightlyEtag !== $nightlyDb->getETag() || $appEtag !== $appDb->getETag()) { $json = json_decode($nightlyDb->getContent()); $json->timestamp = strtotime('+1 day'); $appDb->putContent(json_encode($json)); $this->config->setAppValue('passwords', 'nightly/etag', $appDb->getETag()); $this->dbUpdated = true; } } catch(Exception $e) { $this->logException($e); } } /** * @param $release * * @return bool */ protected function checkNextcloudRequirements($release): bool { try { $versionParser = new VersionParser(); $version = $versionParser->getVersion($release['rawPlatformVersionSpec']); $ncVersion = $this->getVersion(); $min = $version->getMinimumVersion(); $max = $version->getMaximumVersion(); $minFulfilled = $this->compareVersion->isCompatible($ncVersion, $min, '>='); $maxFulfilled = $max !== '' && $this->compareVersion->isCompatible($ncVersion, $max, '<='); return $minFulfilled && ($this->ignoreMaxVersion || $maxFulfilled); } catch(Throwable $e) { $this->logException($e); } return false; } /** * @param $release * * @return bool */ protected function checkPhpRequirements($release): bool { try { if(($release['rawPhpVersionSpec'] ?? '*') === '*') return true; $versionParser = new VersionParser(); $phpVersion = $versionParser->getVersion($release['rawPhpVersionSpec']); $minPhpVersion = $phpVersion->getMinimumVersion(); $maxPhpVersion = $phpVersion->getMaximumVersion(); $minPhpFulfilled = $minPhpVersion === '' || $this->compareVersion->isCompatible( PHP_VERSION, $minPhpVersion, '>=' ); $maxPhpFulfilled = $maxPhpVersion === '' || $this->compareVersion->isCompatible( PHP_VERSION, $maxPhpVersion, '<=' ); return $minPhpFulfilled && $maxPhpFulfilled; } catch(Throwable $e) { $this->logException($e); } return false; } /** * @param Throwable $exception * @param array $context */ protected function logException(Throwable $exception, array $context = []): void { $context['app'] = 'nightlyAppstoreFetcher'; $context['exception'] = $exception; $this->psrLogger->emergency($exception->getMessage(), $context); } }