getInstalledVersion(); return substr($version, -4) !== '-dev'; } /** * Get current installed version number */ public function getInstalledVersion(): string { return (string)GeneralUtility::makeInstance(Typo3Version::class); } public function getMaintenanceWindow(): MaintenanceWindow { $url = 'major/' . $this->getInstalledMajorVersion(); $result = $this->fetchFromRemote($url); return MaintenanceWindow::fromApiResponse($result); } /** * @todo docblock * @return array{community: string[], elts: string[]} */ public function getSupportedMajorReleases(): array { $url = 'major'; $result = $this->fetchFromRemote($url); $majorReleases = [ 'community' => [], 'elts' => [], ]; foreach ($result as $release) { $majorRelease = MajorRelease::fromApiResponse($release); $maintenanceWindow = $majorRelease->getMaintenanceWindow(); if ($maintenanceWindow->isSupportedByCommunity()) { $group = 'community'; } elseif ($maintenanceWindow->isSupportedByElts()) { $group = 'elts'; } else { // Major version is unsupported continue; } $majorReleases[$group][] = $majorRelease->getLts() ?? $majorRelease->getVersion(); } return $majorReleases; } public function isPatchReleaseSuitableForUpdate(CoreRelease $coreRelease): bool { return version_compare($this->getInstalledVersion(), $coreRelease->getVersion()) === -1; } /** * Returns TRUE if an upgrade from current version is security relevant * * @return bool TRUE if there is a pending security update * @throws \TYPO3\CMS\Install\Service\Exception\RemoteFetchException */ public function isUpdateSecurityRelevant(CoreRelease $releaseToCheck): bool { $url = 'major/' . $this->getInstalledMajorVersion() . '/release'; $result = $this->fetchFromRemote($url); $installedVersion = $this->getInstalledVersion(); foreach ($result as $release) { $coreRelease = CoreRelease::fromApiResponse($release); if ($coreRelease->isSecurityUpdate() && version_compare($installedVersion, $coreRelease->getVersion()) === -1 // installed version is lower than release && version_compare($releaseToCheck->getVersion(), $coreRelease->getVersion()) > -1 // release to check is equal or higher than release ) { return true; } } return false; } public function isCurrentInstalledVersionElts(): bool { $url = 'major/' . $this->getInstalledMajorVersion() . '/release'; $result = $this->fetchFromRemote($url); $installedVersion = $this->getInstalledVersion(); foreach ($result as $release) { if (version_compare($installedVersion, $release['version']) === 0) { return $release['elts'] ?? false; } } return false; } /** * Youngest patch release * * @throws \TYPO3\CMS\Install\Service\Exception\RemoteFetchException */ public function getYoungestPatchRelease(): CoreRelease { $url = 'major/' . $this->getInstalledMajorVersion() . '/release/latest'; $result = $this->fetchFromRemote($url); return CoreRelease::fromApiResponse($result); } public function getYoungestCommunityPatchRelease(): CoreRelease { $url = 'major/' . $this->getInstalledMajorVersion() . '/release'; $result = $this->fetchFromRemote($url); // Make sure all releases are sorted by their version $columns = array_column($result, 'version'); array_multisort($columns, SORT_NATURAL, $result); // Remove any ELTS release $releases = array_filter($result, static function (array $release) { return ($release['elts'] ?? false) === false; }); $latestRelease = end($releases); return CoreRelease::fromApiResponse($latestRelease); } /** * @throws \TYPO3\CMS\Install\Service\Exception\RemoteFetchException */ protected function fetchFromRemote(string $url): array { $url = $this->apiBaseUrl . $url; $json = GeneralUtility::getUrl($url); if (!$json) { $this->throwFetchException($url); } return json_decode($json, true); } /** * Get 'major version' from installed version of TYPO3, e.g., '7' from '7.3.0' * * @return string For example 7 */ protected function getInstalledMajorVersion(): string { return (string)GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion(); } /** * Helper method to throw same exception in multiple places * * @throws \TYPO3\CMS\Install\Service\Exception\RemoteFetchException */ protected function throwFetchException(string $url): void { throw new RemoteFetchException( 'Fetching ' . $url . ' failed. Maybe this instance can not connect to the remote system properly.', 1380897593 ); } }