[TASK] Use IconFactory in System Information Panel
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Backend / ToolbarItems / SystemInformationToolbarItem.php
1 <?php
2 namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
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
17 use Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Backend\Toolbar\Enumeration\InformationStatus;
20 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
21 use TYPO3\CMS\Backend\Utility\BackendUtility;
22 use TYPO3\CMS\Core\Core\Bootstrap;
23 use TYPO3\CMS\Core\Imaging\Icon;
24 use TYPO3\CMS\Core\Imaging\IconFactory;
25 use TYPO3\CMS\Core\Page\PageRenderer;
26 use TYPO3\CMS\Core\Utility\CommandUtility;
27 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
28 use TYPO3\CMS\Core\Utility\GeneralUtility;
29 use TYPO3\CMS\Core\Utility\StringUtility;
30 use TYPO3\CMS\Fluid\View\StandaloneView;
31
32 /**
33 * Render system info toolbar item
34 */
35 class SystemInformationToolbarItem implements ToolbarItemInterface
36 {
37 /**
38 * @var StandaloneView
39 */
40 protected $standaloneView = null;
41
42 /**
43 * Template file for the dropdown menu
44 */
45 const TOOLBAR_MENU_TEMPLATE = 'SystemInformation.html';
46
47 /**
48 * Number displayed as badge on the dropdown trigger
49 *
50 * @var int
51 */
52 protected $totalCount = 0;
53
54 /**
55 * Holds the highest severity
56 *
57 * @var InformationStatus
58 */
59 protected $highestSeverity;
60
61 /**
62 * The CSS class for the badge
63 *
64 * @var string
65 */
66 protected $severityBadgeClass = '';
67
68 /**
69 * @var array
70 */
71 protected $systemInformation = array();
72
73 /**
74 * @var array
75 */
76 protected $systemMessages = array();
77
78 /**
79 * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
80 */
81 protected $signalSlotDispatcher = null;
82
83 /**
84 * @var IconFactory
85 */
86 protected $iconFactory;
87
88 /**
89 * Constructor
90 */
91 public function __construct()
92 {
93 if (!$this->checkAccess()) {
94 return;
95 }
96 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
97
98 $extPath = ExtensionManagementUtility::extPath('backend');
99 /* @var $view StandaloneView */
100 $this->standaloneView = GeneralUtility::makeInstance(StandaloneView::class);
101 $this->standaloneView->setTemplatePathAndFilename($extPath . 'Resources/Private/Templates/ToolbarMenu/' . static::TOOLBAR_MENU_TEMPLATE);
102
103 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Toolbar/SystemInformationMenu');
104
105 $this->highestSeverity = InformationStatus::cast(InformationStatus::STATUS_INFO);
106 }
107
108 /**
109 * Collect the information for the menu
110 */
111 protected function collectInformation()
112 {
113 $this->getWebServer();
114 $this->getPhpVersion();
115 $this->getDatabase();
116 $this->getApplicationContext();
117 $this->getComposerMode();
118 $this->getGitRevision();
119 $this->getOperatingSystem();
120
121 $this->emitGetSystemInformation();
122 $this->emitLoadMessages();
123
124 $this->severityBadgeClass = !$this->highestSeverity->equals(InformationStatus::STATUS_NOTICE) ? 'badge-' . (string)$this->highestSeverity : '';
125 }
126
127 /**
128 * Renders the menu for AJAX calls
129 *
130 * @param ServerRequestInterface $request
131 * @param ResponseInterface $response
132 * @return ResponseInterface
133 */
134 public function renderMenuAction(ServerRequestInterface $request, ResponseInterface $response)
135 {
136 $this->collectInformation();
137
138 $response->getBody()->write($this->getDropDown());
139 $response = $response->withHeader('Content-Type', 'text/html; charset=utf-8');
140 return $response;
141 }
142
143 /**
144 * Gets the PHP version
145 *
146 * @return void
147 */
148 protected function getPhpVersion()
149 {
150 $this->systemInformation[] = array(
151 'title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.sysinfo.phpversion', true),
152 'value' => PHP_VERSION,
153 'icon' => $this->iconFactory->getIcon('sysinfo-php-version', Icon::SIZE_SMALL)->render()
154 );
155 }
156
157 /**
158 * Get the database info
159 *
160 * @return void
161 */
162 protected function getDatabase()
163 {
164 $this->systemInformation[] = array(
165 'title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.sysinfo.database', true),
166 'value' => $this->getDatabaseConnection()->getServerVersion(),
167 'icon' => $this->iconFactory->getIcon('sysinfo-database', Icon::SIZE_SMALL)->render()
168 );
169 }
170
171 /**
172 * Gets the application context
173 *
174 * @return void
175 */
176 protected function getApplicationContext()
177 {
178 $applicationContext = GeneralUtility::getApplicationContext();
179 $this->systemInformation[] = array(
180 'title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.sysinfo.applicationcontext', true),
181 'value' => (string)$applicationContext,
182 'status' => $applicationContext->isProduction() ? InformationStatus::STATUS_OK : InformationStatus::STATUS_WARNING,
183 'icon' => $this->iconFactory->getIcon('sysinfo-application-context', Icon::SIZE_SMALL)->render()
184 );
185 }
186
187 /**
188 * Adds the information if the Composer mode is enabled or disabled to the displayed system information
189 */
190 protected function getComposerMode()
191 {
192 if (!Bootstrap::usesComposerClassLoading()) {
193 return;
194 }
195
196 $languageService = $this->getLanguageService();
197 $this->systemInformation[] = array(
198 'title' => $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.sysinfo.composerMode', true),
199 'value' => $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.enabled', true),
200 'icon' => $this->iconFactory->getIcon('sysinfo-composer-mode', Icon::SIZE_SMALL)->render()
201 );
202 }
203
204 /**
205 * Gets the current GIT revision and branch
206 *
207 * @return void
208 */
209 protected function getGitRevision()
210 {
211 if (!StringUtility::endsWith(TYPO3_version, '-dev') || \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::isFunctionDisabled('exec')) {
212 return;
213 }
214 // check if git exists
215 CommandUtility::exec('git --version', $_, $returnCode);
216 if ((int)$returnCode !== 0) {
217 // git is not available
218 return;
219 }
220
221 $revision = trim(CommandUtility::exec('git rev-parse --short HEAD'));
222 $branch = trim(CommandUtility::exec('git rev-parse --abbrev-ref HEAD'));
223 if (!empty($revision) && !empty($branch)) {
224 $this->systemInformation[] = array(
225 'title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.sysinfo.gitrevision', true),
226 'value' => sprintf('%s [%s]', $revision, $branch),
227 'icon' => $this->iconFactory->getIcon('sysinfo-git', Icon::SIZE_SMALL)->render()
228 );
229 }
230 }
231
232 /**
233 * Gets the system kernel and version
234 *
235 * @return void
236 */
237 protected function getOperatingSystem()
238 {
239 $kernelName = php_uname('s');
240 switch (strtolower($kernelName)) {
241 case 'linux':
242 $icon = 'linux';
243 break;
244 case 'darwin':
245 $icon = 'apple';
246 break;
247 default:
248 $icon = 'windows';
249 }
250 $this->systemInformation[] = array(
251 'title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.sysinfo.operatingsystem', true),
252 'value' => $kernelName . ' ' . php_uname('r'),
253 'icon' => $this->iconFactory->getIcon('sysinfo-os-' . $icon, Icon::SIZE_SMALL)->render()
254 );
255 }
256
257 /**
258 * Gets the webserver software
259 */
260 protected function getWebServer()
261 {
262 $this->systemInformation[] = array(
263 'title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.sysinfo.webserver', true),
264 'value' => htmlspecialchars($_SERVER['SERVER_SOFTWARE']),
265 'icon' => $this->iconFactory->getIcon('sysinfo-webserver', Icon::SIZE_SMALL)->render()
266 );
267 }
268
269 /**
270 * Emits the "getSystemInformation" signal
271 *
272 * @return void
273 */
274 protected function emitGetSystemInformation()
275 {
276 // @internal This API is subject to be rebuilt from scratch anytime. Do not use in extensions!
277 list($systemInformation) = $this->getSignalSlotDispatcher()->dispatch(__CLASS__, 'getSystemInformation', array(array()));
278 if (!empty($systemInformation)) {
279 $this->systemInformation[] = $systemInformation;
280 }
281 }
282
283 /**
284 * Emits the "loadMessages" signal
285 *
286 * @return void
287 */
288 protected function emitLoadMessages()
289 {
290 // @internal This API is subject to be rebuilt from scratch anytime. Do not use in extensions!
291 list($message) = $this->getSignalSlotDispatcher()->dispatch(__CLASS__, 'loadMessages', array(array()));
292 if (empty($message)) {
293 return;
294 }
295
296 // increase counter
297 if (isset($message['count'])) {
298 $this->totalCount += (int)$message['count'];
299 }
300
301 /** @var InformationStatus $messageSeverity */
302 $messageSeverity = InformationStatus::cast($message['status']);
303 // define the severity for the badge
304 if ($messageSeverity->isGreaterThan($this->highestSeverity)) {
305 $this->highestSeverity = $messageSeverity;
306 }
307
308 $this->systemMessages[] = $message;
309 }
310
311 /**
312 * Checks whether the user has access to this toolbar item
313 *
314 * @return bool TRUE if user has access, FALSE if not
315 */
316 public function checkAccess()
317 {
318 return $this->getBackendUserAuthentication()->isAdmin();
319 }
320
321 /**
322 * Render system information dropdown
323 *
324 * @return string Icon HTML
325 */
326 public function getItem()
327 {
328 $title = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.sysinfo', true);
329 $icon = $this->iconFactory->getIcon('actions-system-list-open', Icon::SIZE_SMALL)->render('inline');
330 return '<span title="' . $title . '">' . $icon . '<span id="t3js-systeminformation-counter" class="badge"></span></span>';
331 }
332
333 /**
334 * Render drop down
335 *
336 * @return string Drop down HTML
337 */
338 public function getDropDown()
339 {
340 if (!$this->checkAccess()) {
341 return '';
342 }
343
344 $request = $this->standaloneView->getRequest();
345 $request->setControllerExtensionName('backend');
346 $this->standaloneView->assignMultiple(array(
347 'installToolUrl' => BackendUtility::getModuleUrl('system_InstallInstall'),
348 'messages' => $this->systemMessages,
349 'count' => $this->totalCount,
350 'severityBadgeClass' => $this->severityBadgeClass,
351 'systemInformation' => $this->systemInformation
352 ));
353 return $this->standaloneView->render();
354 }
355
356 /**
357 * No additional attributes needed.
358 *
359 * @return array
360 */
361 public function getAdditionalAttributes()
362 {
363 return array();
364 }
365
366 /**
367 * This item has a drop down
368 *
369 * @return bool
370 */
371 public function hasDropDown()
372 {
373 return true;
374 }
375
376 /**
377 * Position relative to others
378 *
379 * @return int
380 */
381 public function getIndex()
382 {
383 return 75;
384 }
385
386 /**
387 * Returns the current BE user.
388 *
389 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
390 */
391 protected function getBackendUserAuthentication()
392 {
393 return $GLOBALS['BE_USER'];
394 }
395
396 /**
397 * Returns DatabaseConnection
398 *
399 * @return \TYPO3\CMS\Core\Database\DatabaseConnection
400 */
401 protected function getDatabaseConnection()
402 {
403 return $GLOBALS['TYPO3_DB'];
404 }
405
406 /**
407 * Returns current PageRenderer
408 *
409 * @return PageRenderer
410 */
411 protected function getPageRenderer()
412 {
413 return GeneralUtility::makeInstance(PageRenderer::class);
414 }
415
416 /**
417 * Returns LanguageService
418 *
419 * @return \TYPO3\CMS\Lang\LanguageService
420 */
421 protected function getLanguageService()
422 {
423 return $GLOBALS['LANG'];
424 }
425
426 /**
427 * Get the SignalSlot dispatcher
428 *
429 * @return \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
430 */
431 protected function getSignalSlotDispatcher()
432 {
433 if (!isset($this->signalSlotDispatcher)) {
434 $this->signalSlotDispatcher = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class)
435 ->get(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class);
436 }
437 return $this->signalSlotDispatcher;
438 }
439 }