6464d433639c8151d6544b216b072ababb93c6fe
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Service / CoreVersionService.php
1 <?php
2 namespace TYPO3\CMS\Install\Service;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2013 Christian Kuhn <lolli@schwarzbu.ch>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29
30 use TYPO3\CMS\Core\Utility\GeneralUtility;
31 use TYPO3\CMS\Core\Utility\VersionNumberUtility;
32
33 /**
34 * Core version service
35 */
36 class CoreVersionService {
37
38 /**
39 * @var \TYPO3\CMS\Extbase\Object\ObjectManager
40 * @inject
41 */
42 protected $objectManager;
43
44 /**
45 * @var \TYPO3\CMS\Core\Registry
46 * @inject
47 */
48 protected $registry;
49
50 /**
51 * Base URI for TYPO3 downloads
52 *
53 * @var string
54 */
55 protected $downloadBaseUri;
56
57 /**
58 * @return mixed
59 */
60 public function getDownloadBaseUri() {
61 return $this->downloadBaseUri;
62 }
63
64 /**
65 * Initialize update URI
66 */
67 public function __construct() {
68 $this->downloadBaseUri = 'https://get.typo3.org/';
69 }
70
71 /**
72 * Update version matrix from remote and store in registry
73 *
74 * @return void
75 * @throws Exception\RemoteFetchException
76 */
77 public function updateVersionMatrix() {
78 $versionArray = $this->fetchVersionMatrixFromRemote();
79 // This is a 'hack' to keep the string stored in the registry small. We are usually only
80 // interested in information from 6.2 and up and older releases do not matter in current
81 // use cases. If this unset() is removed and everything is stored for some reason, the
82 // table sys_file field entry_value needs to be extended from blob to longblob.
83 unset($versionArray['6.1'], $versionArray['6.0'], $versionArray['4.7'], $versionArray['4.6'],
84 $versionArray['4.5'], $versionArray['4.4'], $versionArray['4.3'], $versionArray['4.2'],
85 $versionArray['4.1'], $versionArray['4.0'], $versionArray['3.8'], $versionArray['3.7'],
86 $versionArray['3.6'], $versionArray['3.5'], $versionArray['3.3']);
87 $this->registry->set('TYPO3.CMS.Install', 'coreVersionMatrix', $versionArray);
88 }
89
90 /**
91 * Development git checkout versions always end with '-dev'. They are
92 * not "released" as such and can not be updated.
93 *
94 * @return boolean FALSE If some development version is installed
95 */
96 public function isInstalledVersionAReleasedVersion() {
97 $version = $this->getInstalledVersion();
98 return substr($version, -4) !== '-dev';
99 }
100
101 /**
102 * Get current installed version number
103 *
104 * @return string
105 */
106 public function getInstalledVersion() {
107 return VersionNumberUtility::getCurrentTypo3Version();
108 }
109
110 /**
111 * Returns TRUE if a younger patch level release exists in version matrix.
112 *
113 * @return boolean TRUE if younger patch release is exists
114 */
115 public function isYoungerPatchReleaseAvailable() {
116 $result = FALSE;
117 $version = $this->getInstalledVersion();
118 $youngestVersion = $this->getYoungestPatchRelease();
119 if ($youngestVersion !== $version) {
120 $result = TRUE;
121 }
122 return $result;
123 }
124
125 /**
126 * Returns TRUE if a younger patch level release exists in version matrix that may be a development release.
127 *
128 * @return boolean TRUE if younger patch release is exists
129 */
130 public function isYoungerPatchDevelopmentReleaseAvailable() {
131 $result = FALSE;
132 $version = $this->getInstalledVersion();
133 $youngestVersion = $this->getYoungestPatchDevelopmentRelease();
134 if ($youngestVersion !== $version) {
135 $result = TRUE;
136 }
137 return $result;
138 }
139
140 /**
141 * Returns TRUE if an upgrade from current version is security relevant
142 *
143 * @return boolean TRUE if there is a pending security update
144 */
145 public function isUpdateSecurityRelevant() {
146 $result = FALSE;
147 $version = $this->getInstalledVersion();
148 $youngestVersion = $this->getYoungestReleaseByType(array('security'));
149 if ($youngestVersion !== $version) {
150 $result = TRUE;
151 }
152 return $result;
153 }
154
155 /**
156 * Youngest patch release, eg. 6.2.2
157 *
158 * @return string Version string of youngest patch level release
159 */
160 public function getYoungestPatchRelease() {
161 return $this->getYoungestReleaseByType(array('release', 'security', 'regular'));
162 }
163
164 /**
165 * Youngest development patch release, eg. 6.2.0alpha3 or 6.2-snapshot-20131004
166 *
167 * @return string
168 */
169 public function getYoungestPatchDevelopmentRelease() {
170 return $this->getYoungestReleaseByType(array('release', 'security', 'regular', 'development'));
171 }
172
173 /**
174 * Get youngest release version string.
175 * Returns same version number if no younger release was found.
176 *
177 * @param array $types List of allowed types: development, release, security, regular
178 * @throws Exception\CoreVersionServiceException
179 * @return string Youngest release, eg. 6.2.3 or 6.2.alpha3
180 */
181 protected function getYoungestReleaseByType(array $types) {
182 $version = $this->getInstalledVersion();
183
184 $minorVersion = $this->getMinorVersion($version);
185 $versionMatrix = $this->getVersionMatrix();
186
187 $youngestRelease = $version;
188 $versionReleaseTimestamp = $this->getReleaseTimestampOfVersion($version);
189
190 $patchLevelVersions = $versionMatrix[$minorVersion]['releases'];
191 foreach ($patchLevelVersions as $aVersionNumber => $aVersionDetails) {
192 if (!array_key_exists('type', $aVersionDetails)) {
193 throw new Exception\CoreVersionServiceException(
194 'Release type of version ' . $aVersionNumber . ' not found in version matrix.'
195 . ' This is probably a bug on get.typo3.org.',
196 1380909029
197 );
198 }
199 $type = $aVersionDetails['type'];
200 $aVersionNumberReleaseTimestamp = $this->getReleaseTimestampOfVersion($aVersionNumber);
201 if (
202 $aVersionNumberReleaseTimestamp > $versionReleaseTimestamp
203 && in_array($type, $types)
204 ) {
205 $youngestRelease = $aVersionNumber;
206 $versionReleaseTimestamp = $aVersionNumberReleaseTimestamp;
207 }
208 }
209 return $youngestRelease;
210 }
211
212 /**
213 * Get 'minor version' from version string, eg '6.2' from '6.2.2'
214 *
215 * @return string For example 6.2
216 */
217 protected function getInstalledMinorVersion() {
218 return $this->getMinorVersion($this->getInstalledVersion());
219 }
220
221 /**
222 * Get 'minor version' of version, eg. '6.2' from '6.2.2'
223 *
224 * @param string $version to check
225 * @return string Minor version, eg. '6.2'
226 */
227 protected function getMinorVersion($version) {
228 $explodedVersion = explode('.', $version);
229 $minor = explode('-', $explodedVersion[1]);
230 return $explodedVersion[0] . '.' . $minor[0];
231 }
232
233 /**
234 * Get version matrix from registry
235 *
236 * @return array
237 * @throws Exception
238 */
239 protected function getVersionMatrix() {
240 $versionMatrix = $this->registry->get('TYPO3.CMS.Install', 'coreVersionMatrix');
241 if (empty($versionMatrix) || !is_array($versionMatrix)) {
242 throw new Exception\CoreVersionServiceException(
243 'No version matrix found in registry, call updateVersionMatrix() first.',
244 1380898792
245 );
246 }
247 return $versionMatrix;
248 }
249
250 /**
251 * Get available version string from get.typo3.org
252 *
253 * @return array
254 * @throws Exception\RemoteFetchException
255 */
256 protected function fetchVersionMatrixFromRemote() {
257 $url = $this->downloadBaseUri . 'json';
258 $versionJson = GeneralUtility::getUrl($url);
259 if (!$versionJson) {
260 throw new Exception\RemoteFetchException(
261 'Fetching ' . $url . ' failed. Maybe this instance can not connect to the remote system properly.',
262 1380897593
263 );
264 }
265 return json_decode($versionJson, TRUE);
266 }
267
268 /**
269 * Returns release timestamp of a specific version
270 *
271 * @param $version String to check in version matrix, eg. 6.2.0alpha3 or 6.2.2
272 * @throws Exception\CoreVersionServiceException
273 * @return integer Timestamp of release
274 */
275 protected function getReleaseTimestampOfVersion($version) {
276 $minorVersion = $this->getMinorVersion($version);
277 $versionMatrix = $this->getVersionMatrix();
278 $this->ensureVersionExistsInMatrix($version);
279 if (!array_key_exists('date', $versionMatrix[$minorVersion]['releases'][$version])) {
280 throw new Exception\CoreVersionServiceException(
281 'Release date of version ' . $version . ' not found in version matrix. This is probably a bug on get.typo3.org',
282 1380905853
283 );
284 }
285 $dateString = $versionMatrix[$minorVersion]['releases'][$version]['date'];
286 $date = new \DateTime($dateString);
287 return $date->getTimestamp();
288 }
289
290 /**
291 * Throws an exception if specified version does not exist in version matrix
292 *
293 * @param $version String to check in version matrix, eg. 6.2.0alpha3 or 6.2.2
294 * @throws Exception\CoreVersionServiceException
295 */
296 protected function ensureVersionExistsInMatrix($version) {
297 $minorVersion = $this->getMinorVersion($version);
298 $versionMatrix = $this->getVersionMatrix();
299 if (!array_key_exists($minorVersion, $versionMatrix)) {
300 throw new Exception\CoreVersionServiceException(
301 'Minor release ' . $minorVersion . ' not found in version matrix.',
302 1380905851
303 );
304 }
305 if (!array_key_exists($version, $versionMatrix[$minorVersion]['releases'])) {
306 throw new Exception\CoreVersionServiceException(
307 'Patch level release ' . $version . ' not found in version matrix.',
308 1380905852
309 );
310 }
311 }
312 }