[BUGFIX] TceformsUpdateWizard shows up too often
[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 text file 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 sha1 of a version from version matrix
103 *
104 * @param string $version A version to get sha1 of
105 * @return string sha1 of version
106 * @throws Exception\CoreVersionServiceException
107 */
108 public function getTarGzSha1OfVersion($version) {
109 $this->ensureVersionExistsInMatrix($version);
110
111 $minorVersion = $this->getMinorVersion($version);
112 $versionMatrix = $this->getVersionMatrix();
113
114 if (empty($versionMatrix[$minorVersion]['releases'][$version]['checksums']['tar']['sha1'])) {
115 throw new Exception\CoreVersionServiceException(
116 'Release sha1 of version ' . $version . ' not found in version matrix.'
117 . ' This is probably a bug on get.typo3.org.',
118 1381263173
119 );
120 }
121
122 return $versionMatrix[$minorVersion]['releases'][$version]['checksums']['tar']['sha1'];
123 }
124
125 /**
126 * Get current installed version number
127 *
128 * @return string
129 */
130 public function getInstalledVersion() {
131 return VersionNumberUtility::getCurrentTypo3Version();
132 }
133
134 /**
135 * Returns TRUE if a younger patch level release exists in version matrix.
136 *
137 * @return boolean TRUE if younger patch release is exists
138 */
139 public function isYoungerPatchReleaseAvailable() {
140 $result = FALSE;
141 $version = $this->getInstalledVersion();
142 $youngestVersion = $this->getYoungestPatchRelease();
143 if ($youngestVersion !== $version) {
144 $result = TRUE;
145 }
146 return $result;
147 }
148
149 /**
150 * Returns TRUE if a younger patch level release exists in version matrix that may be a development release.
151 *
152 * @return boolean TRUE if younger patch release is exists
153 */
154 public function isYoungerPatchDevelopmentReleaseAvailable() {
155 $result = FALSE;
156 $version = $this->getInstalledVersion();
157 $youngestVersion = $this->getYoungestPatchDevelopmentRelease();
158 if ($youngestVersion !== $version) {
159 $result = TRUE;
160 }
161 return $result;
162 }
163
164 /**
165 * Returns TRUE if an upgrade from current version is security relevant
166 *
167 * @return boolean TRUE if there is a pending security update
168 */
169 public function isUpdateSecurityRelevant() {
170 $result = FALSE;
171 $version = $this->getInstalledVersion();
172 $youngestVersion = $this->getYoungestReleaseByType(array('security'));
173 if ($youngestVersion !== $version) {
174 $result = TRUE;
175 }
176 return $result;
177 }
178
179 /**
180 * Youngest patch release, eg. 6.2.2
181 *
182 * @return string Version string of youngest patch level release
183 */
184 public function getYoungestPatchRelease() {
185 return $this->getYoungestReleaseByType(array('release', 'security', 'regular'));
186 }
187
188 /**
189 * Youngest development patch release, eg. 6.2.0alpha3 or 6.2-snapshot-20131004
190 *
191 * @return string
192 */
193 public function getYoungestPatchDevelopmentRelease() {
194 return $this->getYoungestReleaseByType(array('release', 'security', 'regular', 'development'));
195 }
196
197 /**
198 * Get youngest release version string.
199 * Returns same version number if no younger release was found.
200 *
201 * @param array $types List of allowed types: development, release, security, regular
202 * @throws Exception\CoreVersionServiceException
203 * @return string Youngest release, eg. 6.2.3 or 6.2.alpha3
204 */
205 protected function getYoungestReleaseByType(array $types) {
206 $version = $this->getInstalledVersion();
207
208 $minorVersion = $this->getMinorVersion($version);
209 $versionMatrix = $this->getVersionMatrix();
210
211 $youngestRelease = $version;
212 $versionReleaseTimestamp = $this->getReleaseTimestampOfVersion($version);
213
214 $patchLevelVersions = $versionMatrix[$minorVersion]['releases'];
215 foreach ($patchLevelVersions as $aVersionNumber => $aVersionDetails) {
216 if (!array_key_exists('type', $aVersionDetails)) {
217 throw new Exception\CoreVersionServiceException(
218 'Release type of version ' . $aVersionNumber . ' not found in version matrix.'
219 . ' This is probably a bug on get.typo3.org.',
220 1380909029
221 );
222 }
223 $type = $aVersionDetails['type'];
224 $aVersionNumberReleaseTimestamp = $this->getReleaseTimestampOfVersion($aVersionNumber);
225 if (
226 $aVersionNumberReleaseTimestamp > $versionReleaseTimestamp
227 && in_array($type, $types)
228 ) {
229 $youngestRelease = $aVersionNumber;
230 $versionReleaseTimestamp = $aVersionNumberReleaseTimestamp;
231 }
232 }
233 return $youngestRelease;
234 }
235
236 /**
237 * Get 'minor version' from version string, eg '6.2' from '6.2.2'
238 *
239 * @return string For example 6.2
240 */
241 protected function getInstalledMinorVersion() {
242 return $this->getMinorVersion($this->getInstalledVersion());
243 }
244
245 /**
246 * Get 'minor version' of version, eg. '6.2' from '6.2.2'
247 *
248 * @param string $version to check
249 * @return string Minor version, eg. '6.2'
250 */
251 protected function getMinorVersion($version) {
252 $explodedVersion = explode('.', $version);
253 $minor = explode('-', $explodedVersion[1]);
254 return $explodedVersion[0] . '.' . $minor[0];
255 }
256
257 /**
258 * Get version matrix from registry
259 *
260 * @return array
261 * @throws Exception
262 */
263 protected function getVersionMatrix() {
264 $versionMatrix = $this->registry->get('TYPO3.CMS.Install', 'coreVersionMatrix');
265 if (empty($versionMatrix) || !is_array($versionMatrix)) {
266 throw new Exception\CoreVersionServiceException(
267 'No version matrix found in registry, call updateVersionMatrix() first.',
268 1380898792
269 );
270 }
271 return $versionMatrix;
272 }
273
274 /**
275 * Get available version string from get.typo3.org
276 *
277 * @return array
278 * @throws Exception\RemoteFetchException
279 */
280 protected function fetchVersionMatrixFromRemote() {
281 $url = $this->downloadBaseUri . 'json';
282 $versionJson = GeneralUtility::getUrl($url);
283 if (!$versionJson) {
284 throw new Exception\RemoteFetchException(
285 'Fetching ' . $url . ' failed. Maybe this instance can not connect to the remote system properly.',
286 1380897593
287 );
288 }
289 return json_decode($versionJson, TRUE);
290 }
291
292 /**
293 * Returns release timestamp of a specific version
294 *
295 * @param $version String to check in version matrix, eg. 6.2.0alpha3 or 6.2.2
296 * @throws Exception\CoreVersionServiceException
297 * @return integer Timestamp of release
298 */
299 protected function getReleaseTimestampOfVersion($version) {
300 $minorVersion = $this->getMinorVersion($version);
301 $versionMatrix = $this->getVersionMatrix();
302 $this->ensureVersionExistsInMatrix($version);
303 if (!array_key_exists('date', $versionMatrix[$minorVersion]['releases'][$version])) {
304 throw new Exception\CoreVersionServiceException(
305 'Release date of version ' . $version . ' not found in version matrix. This is probably a bug on get.typo3.org',
306 1380905853
307 );
308 }
309 $dateString = $versionMatrix[$minorVersion]['releases'][$version]['date'];
310 $date = new \DateTime($dateString);
311 return $date->getTimestamp();
312 }
313
314 /**
315 * Throws an exception if specified version does not exist in version matrix
316 *
317 * @param $version String to check in version matrix, eg. 6.2.0alpha3 or 6.2.2
318 * @throws Exception\CoreVersionServiceException
319 */
320 protected function ensureVersionExistsInMatrix($version) {
321 $minorVersion = $this->getMinorVersion($version);
322 $versionMatrix = $this->getVersionMatrix();
323 if (!array_key_exists($minorVersion, $versionMatrix)) {
324 throw new Exception\CoreVersionServiceException(
325 'Minor release ' . $minorVersion . ' not found in version matrix.',
326 1380905851
327 );
328 }
329 if (!array_key_exists($version, $versionMatrix[$minorVersion]['releases'])) {
330 throw new Exception\CoreVersionServiceException(
331 'Patch level release ' . $version . ' not found in version matrix.',
332 1380905852
333 );
334 }
335 }
336 }