‪TYPO3CMS  9.5
InstallStatusReport.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
23 
29 {
30  protected const ‪WRAP_FLAT = 1;
31  protected const ‪WRAP_NESTED = 2;
32 
33  protected ‪$useMarkup;
34 
35  public function ‪__construct(bool ‪$useMarkup = true)
36  {
37  $this->useMarkup = ‪$useMarkup;
38  }
39 
45  public function ‪getStatus()
46  {
47  return [
48  'FileSystem' => $this->‪getFileSystemStatus(),
49  'RemainingUpdates' => $this->‪getRemainingUpdatesStatus(),
50  'NewVersion' => $this->‪getNewVersionStatus(),
51  ];
52  }
53 
59  protected function ‪getFileSystemStatus()
60  {
61  $languageService = $this->‪getLanguageService();
62  $value = $languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_writable');
63  $message = '';
64  $severity = ‪Status::OK;
65  // Requirement level
66  // -1 = not required, but if it exists may be writable or not
67  // 0 = not required, if it exists the dir should be writable
68  // 1 = required, doesn't have to be writable
69  // 2 = required, has to be writable
70  $varPath = ‪Environment::getVarPath();
71  $sitePath = ‪Environment::getPublicPath();
72  $rootPath = ‪Environment::getProjectPath();
73  $checkWritable = [
74  $sitePath . '/typo3temp/' => 2,
75  $sitePath . '/typo3temp/assets/' => 2,
76  $sitePath . '/typo3temp/assets/compressed/' => 2,
77  // only needed when GraphicalFunctions is used
78  $sitePath . '/typo3temp/assets/images/' => 0,
79  // used in PageGenerator (inlineStyle2Temp) and Backend + Language JS files
80  $sitePath . '/typo3temp/assets/css/' => 2,
81  $sitePath . '/typo3temp/assets/js/' => 2,
82  // fallback storage of FAL
83  $sitePath . '/typo3temp/assets/_processed_/' => 0,
84  $varPath => 2,
85  $varPath . '/transient/' => 2,
86  $varPath . '/charset/' => 2,
87  $varPath . '/lock/' => 2,
88  $sitePath . '/typo3conf/' => 2,
90  $sitePath . '/' . ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] => -1,
91  $sitePath . '/' . ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] . '_temp_/' => 0,
92  ];
93 
94  // Check for writable extension folder files in non-composer mode only
96  $checkWritable[‪Environment::getExtensionsPath()] = 0;
97  if (‪$GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall']) {
98  $checkWritable[‪Environment::getBackendPath() . '/ext/'] = -1;
99  }
100  }
101 
102  foreach ($checkWritable as $path => $requirementLevel) {
103  $relPath = substr($path, strlen($rootPath) + 1);
104  if (!@is_dir($path)) {
105  // If the directory is missing, try to create it
106  GeneralUtility::mkdir($path);
107  }
108  if (!@is_dir($path)) {
109  if ($requirementLevel > 0) {
110  // directory is required
111  $value = $languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_missingDirectory');
112  $message .= sprintf($languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_directoryDoesNotExistCouldNotCreate'), $relPath) . '<br />';
113  $severity = ‪Status::ERROR;
114  } else {
115  $message .= sprintf($languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_directoryDoesNotExist'), $relPath);
116  if ($requirementLevel == 0) {
117  $message .= ' ' . $languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_directoryShouldAlsoBeWritable');
118  }
119  $message .= '<br />';
120  if ($severity < ‪Status::WARNING) {
121  $value = $languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_nonExistingDirectory');
122  $severity = ‪Status::WARNING;
123  }
124  }
125  } else {
126  if (!is_writable($path)) {
127  switch ($requirementLevel) {
128  case 0:
129  $message .= sprintf(
130  $languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_directoryShouldBeWritable'),
131  $path
132  ) . '<br />';
133  if ($severity < ‪Status::WARNING) {
134  $value = $languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_recommendedWritableDirectory');
135  $severity = ‪Status::WARNING;
136  }
137  break;
138  case 2:
139  $value = $languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_requiredWritableDirectory');
140  $message .= sprintf(
141  $languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_directoryMustBeWritable'),
142  $path
143  ) . '<br />';
144  $severity = ‪Status::ERROR;
145  break;
146  default:
147  }
148  }
149  }
150  }
151  return GeneralUtility::makeInstance(Status::class, $languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_fileSystem'), $value, $message, $severity);
152  }
153 
162  protected function ‪getIncompleteWizards(): array
163  {
164  $upgradeWizardsService = GeneralUtility::makeInstance(UpgradeWizardsService::class);
165  $incompleteWizards = $upgradeWizardsService->getUpgradeWizardsList();
166  $incompleteWizards = array_filter(
167  $incompleteWizards,
168  function ($wizard) {
169  return $wizard['shouldRenderWizard'];
170  }
171  );
172  return $incompleteWizards;
173  }
174 
180  protected function ‪getRemainingUpdatesStatus()
181  {
182  $languageService = $this->‪getLanguageService();
183  $value = $languageService->getLL('status_updateComplete');
184  $message = '';
185  $severity = ‪Status::OK;
187  $uriBuilder = GeneralUtility::makeInstance(\‪TYPO3\CMS\Backend\Routing\UriBuilder::class);
188  // check if there are update wizards left to perform
189  $incompleteWizards = $this->‪getIncompleteWizards();
190  if (count($incompleteWizards)) {
191  // At least one incomplete wizard was found
192  $value = $languageService->getLL('status_updateIncomplete');
193  $severity = ‪Status::WARNING;
194  $url = (string)$uriBuilder->buildUriFromRoute('tools_toolsupgrade');
195  $message = sprintf($languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:warning.install_update'), '<a href="' . htmlspecialchars($url) . '">', '</a>');
196  }
197 
198  return GeneralUtility::makeInstance(Status::class, $languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_remainingUpdates'), $value, $message, $severity);
199  }
200 
206  protected function ‪getNewVersionStatus()
207  {
208  $languageService = $this->‪getLanguageService();
210  $coreVersionService = GeneralUtility::makeInstance(\‪TYPO3\CMS\Install\Service\CoreVersionService::class);
211 
212  // No updates for development versions
213  if (!$coreVersionService->isInstalledVersionAReleasedVersion()) {
214  return GeneralUtility::makeInstance(Status::class, 'TYPO3', TYPO3_version, $languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_isDevelopmentVersion'), ‪Status::NOTICE);
215  }
216 
217  try {
218  $versionMaintenanceWindow = $coreVersionService->getMaintenanceWindow();
219  } catch (‪RemoteFetchException $remoteFetchException) {
220  return GeneralUtility::makeInstance(
221  Status::class,
222  'TYPO3',
223  TYPO3_version,
224  $languageService->sL(
225  'LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_remoteFetchException'
226  ),
228  );
229  }
230 
231  if (!$versionMaintenanceWindow->isSupportedByCommunity() && !$versionMaintenanceWindow->isSupportedByElts()) {
232  // Version is not maintained
233  $message = $languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_versionOutdated');
234  $status = ‪Status::ERROR;
235  } else {
236  $message = '';
237  $status = ‪Status::OK;
238 
239  // There is an update available
240  $availableReleases = [];
241  $latestRelease = $coreVersionService->getYoungestPatchRelease();
242  $isCurrentVersionElts = $coreVersionService->isCurrentInstalledVersionElts();
243 
244  if ($coreVersionService->isPatchReleaseSuitableForUpdate($latestRelease)) {
245  $availableReleases[] = $latestRelease;
246  }
247 
248  if (!$versionMaintenanceWindow->isSupportedByCommunity()) {
249  if ($latestRelease->isElts()) {
250  $latestCommunityDrivenRelease = $coreVersionService->getYoungestCommunityPatchRelease();
251  if ($coreVersionService->isPatchReleaseSuitableForUpdate($latestCommunityDrivenRelease)) {
252  $availableReleases[] = $latestCommunityDrivenRelease;
253  }
254  } elseif (!$isCurrentVersionElts) {
255  // Inform user about ELTS being available soon if:
256  // - regular support ran out
257  // - the current installed version is no ELTS
258  // - no ELTS update was released, yet
259  $message = sprintf(
260  $languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_elts_information'),
261  TYPO3_version,
262  '<a href="https://typo3.com/elts" target="_blank" rel="noopener">https://typo3.com/elts</a>'
263  );
264  $status = ‪Status::WARNING;
265  }
266  }
267 
268  if ($availableReleases !== []) {
269  $messages = [];
270  $status = ‪Status::WARNING;
271  foreach ($availableReleases as $availableRelease) {
272  $versionString = $availableRelease->getVersion();
273  if ($availableRelease->isElts()) {
274  $versionString .= ' ELTS';
275  }
276  if ($coreVersionService->isUpdateSecurityRelevant($availableRelease)) {
277  $status = ‪Status::ERROR;
278  $updateMessage = sprintf($languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_newVersionSecurityRelevant'), $versionString);
279  } else {
280  $updateMessage = sprintf($languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_newVersion'), $versionString);
281  }
282 
283  if ($availableRelease->isElts()) {
284  if ($isCurrentVersionElts) {
285  $updateMessage .= ' ' . sprintf(
286  $languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_elts_download'),
287  '<a href="https://my.typo3.org" target="_blank" rel="noopener">my.typo3.org</a>'
288  );
289  } else {
290  $updateMessage .= ' ' . sprintf(
291  $languageService->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_elts_subscribe'),
292  $coreVersionService->getInstalledVersion(),
293  '<a href="https://typo3.com/elts" target="_blank" rel="noopener">https://typo3.com/elts</a>'
294  );
295  }
296  }
297  $messages[] = $updateMessage;
298  }
299  $message = $this->‪wrapList($messages, count($messages) > 1 ? self::WRAP_NESTED : self::WRAP_FLAT);
300  }
301  }
302 
303  return GeneralUtility::makeInstance(Status::class, 'TYPO3', TYPO3_version, $message, $status);
304  }
305 
306  protected function ‪wrapList(array $items, int $style): string
307  {
308  if (!$this->useMarkup) {
309  return implode(', ', $items);
310  }
311  if ($style === self::WRAP_NESTED) {
312  return sprintf(
313  '<ul>%s</ul>',
314  implode('', $this->‪wrapItems($items, '<li>', '</li>'))
315  );
316  }
317  return sprintf(
318  '<p>%s</p>',
319  implode('', $this->‪wrapItems($items, '<br>', ''))
320  );
321  }
322 
323  protected function ‪wrapItems(array $items, string $before, string $after): array
324  {
325  return array_map(
326  static function (string $item) use ($before, $after): string {
327  return $before . $item . $after;
328  },
329  array_filter($items)
330  );
331  }
332 
336  protected function ‪getLanguageService()
337  {
338  return ‪$GLOBALS['LANG'];
339  }
340 }
‪TYPO3\CMS\Install\Report\InstallStatusReport\WRAP_FLAT
‪const WRAP_FLAT
Definition: InstallStatusReport.php:30
‪TYPO3\CMS\Reports\StatusProviderInterface
Definition: StatusProviderInterface.php:21
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:153
‪TYPO3\CMS\Core\Core\Environment\getLabelsPath
‪static string getLabelsPath()
Definition: Environment.php:209
‪TYPO3\CMS\Reports\Status\NOTICE
‪const NOTICE
Definition: Status.php:23
‪TYPO3
‪TYPO3\CMS\Install\Report\InstallStatusReport
Definition: InstallStatusReport.php:29
‪TYPO3\CMS\Reports\Status\ERROR
‪const ERROR
Definition: Status.php:27
‪TYPO3\CMS\Install\Report
Definition: EnvironmentStatusReport.php:2
‪TYPO3\CMS\Install\Report\InstallStatusReport\getFileSystemStatus
‪Status getFileSystemStatus()
Definition: InstallStatusReport.php:59
‪TYPO3\CMS\Install\Report\InstallStatusReport\__construct
‪__construct(bool $useMarkup=true)
Definition: InstallStatusReport.php:35
‪TYPO3\CMS\Install\Report\InstallStatusReport\getNewVersionStatus
‪Status getNewVersionStatus()
Definition: InstallStatusReport.php:206
‪TYPO3\CMS\Install\Service\UpgradeWizardsService
Definition: UpgradeWizardsService.php:42
‪TYPO3\CMS\Reports\Status\OK
‪const OK
Definition: Status.php:25
‪TYPO3\CMS\Reports\Status
Definition: Status.php:22
‪TYPO3\CMS\Install\Report\InstallStatusReport\getIncompleteWizards
‪array getIncompleteWizards()
Definition: InstallStatusReport.php:162
‪TYPO3\CMS\Core\Core\Environment\getProjectPath
‪static string getProjectPath()
Definition: Environment.php:142
‪TYPO3\CMS\Install\Report\InstallStatusReport\wrapItems
‪wrapItems(array $items, string $before, string $after)
Definition: InstallStatusReport.php:323
‪TYPO3\CMS\Core\Core\Environment\getBackendPath
‪static string getBackendPath()
Definition: Environment.php:223
‪TYPO3\CMS\Reports\Status\WARNING
‪const WARNING
Definition: Status.php:26
‪TYPO3\CMS\Install\Service\Exception\RemoteFetchException
Definition: RemoteFetchException.php:22
‪TYPO3\CMS\Install\Report\InstallStatusReport\wrapList
‪wrapList(array $items, int $style)
Definition: InstallStatusReport.php:306
‪TYPO3\CMS\Install\Report\InstallStatusReport\getStatus
‪Status[] getStatus()
Definition: InstallStatusReport.php:45
‪TYPO3\CMS\Install\Report\InstallStatusReport\getRemainingUpdatesStatus
‪Status getRemainingUpdatesStatus()
Definition: InstallStatusReport.php:180
‪TYPO3\CMS\Core\Core\Environment\isComposerMode
‪static bool isComposerMode()
Definition: Environment.php:117
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:39
‪TYPO3\CMS\Install\Report\InstallStatusReport\getLanguageService
‪LanguageService getLanguageService()
Definition: InstallStatusReport.php:336
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:29
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Install\Report\InstallStatusReport\$useMarkup
‪$useMarkup
Definition: InstallStatusReport.php:33
‪TYPO3\CMS\Install\Report\InstallStatusReport\WRAP_NESTED
‪const WRAP_NESTED
Definition: InstallStatusReport.php:31
‪TYPO3\CMS\Core\Core\Environment\getVarPath
‪static string getVarPath()
Definition: Environment.php:165
‪TYPO3\CMS\Core\Core\Environment\getExtensionsPath
‪static string getExtensionsPath()
Definition: Environment.php:245