Commit f565d0d8 authored by Andreas Fernandez's avatar Andreas Fernandez Committed by Jigal van Hemert
Browse files

[FEATURE] Introduce System Information dropdown item

This patch introduces a new System Information dropdown item that
contains several system information. By default it displays:
* PHP version
* Database version
* Application context
* git revision (if TYPO3 version has "-dev" suffix)
* Operating system

The item list is extendable by the SystemInformationHookInterface.

Resolves: #65767
Releases: master
Change-Id: I2e7489f53198d44edea9995fe4cce49696a2f888
Reviewed-on: http://review.typo3.org/37881


Reviewed-by: default avatarMarkus Klein <klein.t3@reelworx.at>
Tested-by: default avatarMarkus Klein <klein.t3@reelworx.at>
Tested-by: default avatarFrank Nägler <typo3@naegler.net>
Reviewed-by: Jigal van Hemert's avatarJigal van Hemert <jigal.van.hemert@typo3.org>
Tested-by: Jigal van Hemert's avatarJigal van Hemert <jigal.van.hemert@typo3.org>
parent a0fc38fd
<?php
namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
/**
* Render system info toolbar item
*/
abstract class AbstractToolbarItem {
/**
* @var StandaloneView
*/
protected $standaloneView = NULL;
public function __construct() {
$extPath = ExtensionManagementUtility::extPath('backend');
/* @var $view StandaloneView */
$this->standaloneView = GeneralUtility::makeInstance(StandaloneView::class);
$this->standaloneView->setTemplatePathAndFilename($extPath . 'Resources/Private/Templates/ToolbarMenu/' . static::TOOLBAR_MENU_TEMPLATE);
}
/**
* @param string $extension Set the extension context (required for shorthand locallang.xlf references)
* @return StandaloneView
*/
protected function getStandaloneView($extension = NULL) {
if (!empty($extension)) {
$request = $this->standaloneView->getRequest();
$request->setControllerExtensionName($extension);
}
return $this->standaloneView;
}
}
<?php
namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
use TYPO3\CMS\Backend\Toolbar\Enumeration\InformationStatus;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Backend\Utility\IconUtility;
use TYPO3\CMS\Core\Utility\CommandUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
/**
* Render system info toolbar item
*/
class SystemInformationToolbarItem extends AbstractToolbarItem implements ToolbarItemInterface {
/**
* Template file for the dropdown menu
*/
const TOOLBAR_MENU_TEMPLATE = 'SystemInformation.html';
/**
* Number displayed as badge on the dropdown trigger
*
* @var int
*/
protected $totalCount = 0;
/**
* Holds the highest severity
*
* @var string
*/
protected $highestSeverity = '';
/**
* @var array
*/
protected $systemInformation = array();
/**
* @var array
*/
protected $systemMessages = array();
/**
* @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
*/
protected $signalSlotDispatcher = NULL;
/**
* Constructor
*/
public function __construct() {
if (!$this->checkAccess()) {
return;
}
parent::__construct();
$pageRenderer = $this->getPageRenderer();
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Toolbar/SystemInformationMenu');
$this->getPhpVersion();
$this->getDatabase();
$this->getApplicationContext();
$this->getGitRevision();
$this->getOperatingSystem();
$this->emitGetSystemInformation();
$this->emitLoadMessages();
}
/**
* Gets the PHP version
*/
protected function getPhpVersion() {
$this->systemInformation[] = array(
'title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.sysinfo.phpversion', TRUE),
'value' => PHP_VERSION,
'icon' => '<span class="fa fa-code"></span>'
);
}
/**
* Get the database info
*/
protected function getDatabase() {
$this->systemInformation[] = array(
'title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.sysinfo.database', TRUE),
'value' => $this->getDatabaseConnection()->getServerVersion(),
'icon' => '<span class="fa fa-database"></span>'
);
}
/**
* Gets the application context
*/
protected function getApplicationContext() {
$applicationContext = GeneralUtility::getApplicationContext();
$this->systemInformation[] = array(
'title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.sysinfo.applicationcontext', TRUE),
'value' => (string)$applicationContext,
'status' => $applicationContext->isProduction() ? InformationStatus::STATUS_OK : InformationStatus::STATUS_ERROR,
'icon' => '<span class="fa fa-tasks"></span>'
);
}
/**
* Gets the current GIT revision and branch
*/
protected function getGitRevision() {
if (!StringUtility::endsWith(TYPO3_version, '-dev') || \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::isFunctionDisabled('exec')) {
return '';
}
// check if git exists
CommandUtility::exec('git --version', $_, $returnCode);
if ((int)$returnCode !== 0) {
// git is not available
return '';
}
$revision = trim(CommandUtility::exec('git rev-parse --short HEAD'));
$branch = trim(CommandUtility::exec('git rev-parse --abbrev-ref HEAD'));
if (!empty($revision) && !empty($branch)) {
$this->systemInformation[] = array(
'title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.sysinfo.gitrevision', TRUE),
'value' => sprintf('%s [%s]', $revision, $branch),
'icon' => '<span class="fa fa-git"></span>'
);
}
}
/**
* Gets the system kernel and version
*/
protected function getOperatingSystem() {
$kernelName = php_uname('s');
switch (strtolower($kernelName)) {
case 'linux':
$icon = 'linux';
break;
case 'darwin':
$icon = 'apple';
break;
default:
$icon = 'windows';
}
$this->systemInformation[] = array(
'title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.sysinfo.operatingsystem', TRUE),
'value' => $kernelName . ' ' . php_uname('r'),
'icon' => '<span class="fa fa-' . htmlspecialchars($icon) . '"></span>'
);
}
/**
* Emits the "getSystemInformation" signal
*/
protected function emitGetSystemInformation() {
list($systemInformation) = $this->getSignalSlotDispatcher()->dispatch(__CLASS__, 'getSystemInformation', array(array()));
if (!empty($systemInformation)) {
$this->systemInformation[] = $systemInformation;
}
}
/**
* Emits the "loadMessages" signal
*/
protected function emitLoadMessages() {
list($message) = $this->getSignalSlotDispatcher()->dispatch(__CLASS__, 'loadMessages', array(array()));
if (empty($message)) {
return;
}
// increase counter
if (isset($message['count'])) {
$this->totalCount += (int)$message['count'];
}
// define the severity for the badge
if (InformationStatus::mapStatusToInt($message['status']) > InformationStatus::mapStatusToInt($this->highestSeverity)) {
$this->highestSeverity = $message['status'];
}
$this->systemMessages[] = $message;
}
/**
* Checks whether the user has access to this toolbar item
*
* @return bool TRUE if user has access, FALSE if not
*/
public function checkAccess() {
return $this->getBackendUserAuthentication()->isAdmin();
}
/**
* Render system information dropdown
*
* @return string Icon HTML
*/
public function getItem() {
$title = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.sysinfo', TRUE);
$item = IconUtility::getSpriteIcon('actions-system-list-open', array('title' => $title));
if ($this->totalCount > 0) {
$severityBadge = $this->highestSeverity !== InformationStatus::STATUS_DEFAULT ? 'badge-' . $this->highestSeverity : '';
$item .= '<span id="t3js-systeminformation-counter" class="badge ' . $severityBadge . '">' . $this->totalCount . '</span>';
}
return $item;
}
/**
* Render drop down
*
* @return string Drop down HTML
*/
public function getDropDown() {
if (!$this->checkAccess()) {
return '';
}
$this->getStandaloneView('backend')->assignMultiple(array(
'installToolUrl' => BackendUtility::getModuleUrl('system_InstallInstall'),
'messages' => $this->systemMessages,
'systemInformation' => $this->systemInformation
));
return $this->getStandaloneView()->render();
}
/**
* No additional attributes needed.
*
* @return array
*/
public function getAdditionalAttributes() {
return array();
}
/**
* This item has a drop down
*
* @return bool
*/
public function hasDropDown() {
return TRUE;
}
/**
* Position relative to others
*
* @return int
*/
public function getIndex() {
return 75;
}
/**
* Returns the current BE user.
*
* @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
*/
protected function getBackendUserAuthentication() {
return $GLOBALS['BE_USER'];
}
/**
* Returns DatabaseConnection
*
* @return \TYPO3\CMS\Core\Database\DatabaseConnection
*/
protected function getDatabaseConnection() {
return $GLOBALS['TYPO3_DB'];
}
/**
* Returns current PageRenderer
*
* @return \TYPO3\CMS\Core\Page\PageRenderer
*/
protected function getPageRenderer() {
/** @var \TYPO3\CMS\Backend\Template\DocumentTemplate $documentTemplate */
$documentTemplate = $GLOBALS['TBE_TEMPLATE'];
return $documentTemplate->getPageRenderer();
}
/**
* Returns LanguageService
*
* @return \TYPO3\CMS\Lang\LanguageService
*/
protected function getLanguageService() {
return $GLOBALS['LANG'];
}
/**
* Get the SignalSlot dispatcher
*
* @return \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
*/
protected function getSignalSlotDispatcher() {
if (!isset($this->signalSlotDispatcher)) {
$this->signalSlotDispatcher = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class)
->get(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class);
}
return $this->signalSlotDispatcher;
}
}
<?php
namespace TYPO3\CMS\Backend\Toolbar\Enumeration;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
/**
* This class holds the severities of the SystemInformation toolbar menu
*/
class InformationStatus extends \TYPO3\CMS\Core\Type\Enumeration {
/**
* @var string
*/
const STATUS_DEFAULT = '';
/**
* @var string
*/
const STATUS_OK = 'success';
/**
* @var string
*/
const STATUS_WARNING = 'warning';
/**
* @var string
*/
const STATUS_ERROR = 'danger';
/**
* @var int[]
*/
static protected $statusIntegerMap = array(
self::STATUS_DEFAULT => -1,
self::STATUS_OK => 0,
self::STATUS_WARNING => 1,
self::STATUS_ERROR => 2
);
/**
* Map the status string to an integer
*
* @param string $status
* @return int
*/
static public function mapStatusToInt($status) {
if (isset(static::$statusIntegerMap[$status])) {
return static::$statusIntegerMap[$status];
}
return -1;
}
}
\ No newline at end of file
...@@ -9,6 +9,16 @@ ...@@ -9,6 +9,16 @@
<trans-unit id="show_references"> <trans-unit id="show_references">
<source>Show references</source> <source>Show references</source>
</trans-unit> </trans-unit>
<trans-unit id="systemmessage.header">
<source>Application Information</source>
</trans-unit>
<trans-unit id="systemmessage.intro">
<source><![CDATA[This is a short system overview, for advanced information please head to the <a href="%s">Install Tool</a>.]]></source>
</trans-unit>
<trans-unit id="systemmessage.allgood" xml:space="preserve">
<source>Your system is fully operational.
Have a nice day.</source>
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>
<ul class="dropdown-list">
<li class="dropdown-header"><f:translate key="systemmessage.header" /></li>
<li id="systeminformation_installtool" class="dropdown-intro typo3-module-menu-item submodule mod-system_InstallInstall" data-modulename="system_InstallInstall">
<f:translate key="systemmessage.intro" arguments="{0: '{installToolUrl}'}" />
</li>
<li>
<dl class="dl-horizontal">
<f:for each="{systemInformation}" as="info">
<dt title="{info.title}"><f:format.raw>{info.icon}</f:format.raw> {info.title}</dt>
<dd><f:if condition="{info.status}">
<f:then>
<span class="text-{info.status}">{info.value}</span>
</f:then>
<f:else>
{info.value}
</f:else>
</f:if></dd>
</f:for>
</dl>
</li>
<li class="divider"></li>
<f:if condition="{messages -> f:count()} > 0">
<f:then>
<f:for each="{messages}" as="message">
<li><span class="text-{message.status}">{message.text}</span></li>
</f:for>
</f:then>
<f:else>
<li><span class="text-success"><f:format.nl2br><f:translate key="systemmessage.allgood" /></f:format.nl2br></span></li>
</f:else>
</f:if>
</ul>
\ No newline at end of file
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
/**
* System information menu handler
*/
define('TYPO3/CMS/Backend/Toolbar/SystemInformationMenu', ['jquery'], function($) {
var SystemInformationMenu = {
elements: {
$counter: $('#t3js-systeminformation-counter')
}
};
/**
* register event handlers
*/
SystemInformationMenu.initializeEvents = function() {
var count = parseInt(SystemInformationMenu.elements.$counter.text());
SystemInformationMenu.elements.$counter.toggle(count > 0);
};
/**
* initialize and return the Opendocs object
*/
$(document).ready(function() {
SystemInformationMenu.initializeEvents();
});
TYPO3.SystemInformationMenu = SystemInformationMenu;
return SystemInformationMenu;
});
...@@ -13,6 +13,7 @@ if (TYPO3_MODE === 'BE') { ...@@ -13,6 +13,7 @@ if (TYPO3_MODE === 'BE') {
$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = \TYPO3\CMS\Backend\Backend\ToolbarItems\HelpToolbarItem::class; $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = \TYPO3\CMS\Backend\Backend\ToolbarItems\HelpToolbarItem::class;
$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = \TYPO3\CMS\Backend\Backend\ToolbarItems\LiveSearchToolbarItem::class; $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = \TYPO3\CMS\Backend\Backend\ToolbarItems\LiveSearchToolbarItem::class;
$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = \TYPO3\CMS\Backend\Backend\ToolbarItems\ShortcutToolbarItem::class; $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = \TYPO3\CMS\Backend\Backend\ToolbarItems\ShortcutToolbarItem::class;
$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = \TYPO3\CMS\Backend\Backend\ToolbarItems\SystemInformationToolbarItem::class;
$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = \TYPO3\CMS\Backend\Backend\ToolbarItems\UserToolbarItem::class; $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = \TYPO3\CMS\Backend\Backend\ToolbarItems\UserToolbarItem::class;
} }
......
<?php
namespace TYPO3\CMS\Belog\Controller;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Belog\Domain\Model\Constraint;
/**
* Count newest exceptions for the system information menu
*/
class SystemInformationController extends AbstractController {
/**
* Modifies the SystemInformation array
*
* @param array $systemMessages Array of system messages
* @return
*/
public function appendMessage() {
$constraint = $this->getConstraintFromBeUserData();
if ($constraint === NULL) {
$constraint = $this->objectManager->get(Constraint::class);