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