first commit

This commit is contained in:
salam committed 2026-10-19 08:18:39 +02:00
commit 1218dd1517
12716 files changed
+989233

No files matched your search

@@ -0,0 +1,370 @@
<?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\Backend\View\BackendTemplateView;
use TYPO3\CMS\Belog\Domain\Model\Constraint;
use TYPO3\CMS\Belog\Domain\Model\LogEntry;
use TYPO3\CMS\Core\Messaging\AbstractMessage;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
/**
* Abstract class to show log entries from sys_log
* @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API.
*/
class BackendLogController extends ActionController
{
/**
* @var int
*/
private const TIMEFRAME_THISWEEK = 0;
/**
* @var int
*/
private const TIMEFRAME_LASTWEEK = 1;
/**
* @var int
*/
private const TIMEFRAME_LASTSEVENDAYS = 2;
/**
* @var int
*/
private const TIMEFRAME_THISMONTH = 10;
/**
* @var int
*/
private const TIMEFRAME_LASTMONTH = 11;
/**
* @var int
*/
private const TIMEFRAME_LAST31DAYS = 12;
/**
* @var int
*/
private const TIMEFRAME_CUSTOM = 30;
/**
* @var \TYPO3\CMS\Belog\Domain\Repository\LogEntryRepository
*/
protected $logEntryRepository;
/**
* @var BackendTemplateView
*/
protected $view;
/**
* @param \TYPO3\CMS\Belog\Domain\Repository\LogEntryRepository $logEntryRepository
*/
public function injectLogEntryRepository(\TYPO3\CMS\Belog\Domain\Repository\LogEntryRepository $logEntryRepository)
{
$this->logEntryRepository = $logEntryRepository;
}
/**
* Initialize list action
*/
public function initializeListAction()
{
if (!isset($this->settings['dateFormat'])) {
$this->settings['dateFormat'] = $GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? 'm-d-Y' : 'd-m-Y';
}
if (!isset($this->settings['timeFormat'])) {
$this->settings['timeFormat'] = $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'];
}
$constraintConfiguration = $this->arguments->getArgument('constraint')->getPropertyMappingConfiguration();
$constraintConfiguration->allowAllProperties();
}
/**
* Show general information and the installed modules
*
* @param Constraint $constraint
* @param int $pageId
* @param string $layout
*/
public function listAction(Constraint $constraint = null, int $pageId = null, string $layout = 'Default')
{
// Constraint object handling:
// If there is none from GET, try to get it from BE user data, else create new
if ($constraint === null) {
$constraint = $this->getConstraintFromBeUserData();
} else {
$this->persistConstraintInBeUserData($constraint);
}
$constraint->setPageId($pageId);
$this->resetConstraintsOnMemoryExhaustionError();
$this->setStartAndEndTimeFromTimeSelector($constraint);
$this->forceWorkspaceSelectionIfInWorkspace($constraint);
$logEntries = $this->logEntryRepository->findByConstraint($constraint);
$groupedLogEntries = $this->groupLogEntriesByPageAndDay($logEntries, $constraint->getGroupByPage());
$this->view->assignMultiple([
'pageId' => $pageId,
'layout' => $layout,
'groupedLogEntries' => $groupedLogEntries,
'constraint' => $constraint,
'userGroups' => $this->createUserAndGroupListForSelectOptions(),
'workspaces' => $this->createWorkspaceListForSelectOptions(),
'pageDepths' => $this->createPageDepthOptions(),
]);
}
/**
* Delete all log entries that share the same message with the log entry given
* in $errorUid
*
* @param int $errorUid
*/
public function deleteMessageAction(int $errorUid)
{
/** @var \TYPO3\CMS\Belog\Domain\Model\LogEntry $logEntry */
$logEntry = $this->logEntryRepository->findByUid($errorUid);
if (!$logEntry) {
$this->addFlashMessage(LocalizationUtility::translate('actions.delete.noRowFound', 'belog'), '', AbstractMessage::WARNING);
$this->redirect('list');
}
$numberOfDeletedRows = $this->logEntryRepository->deleteByMessageDetails($logEntry);
$this->addFlashMessage(sprintf(LocalizationUtility::translate('actions.delete.message', 'belog'), $numberOfDeletedRows));
$this->redirect('list');
}
/**
* Get module states (the constraint object) from user data
*
* @return Constraint
*/
protected function getConstraintFromBeUserData()
{
$serializedConstraint = $GLOBALS['BE_USER']->getModuleData(static::class);
$constraint = null;
if (is_string($serializedConstraint) && !empty($serializedConstraint)) {
$constraint = @unserialize($serializedConstraint, ['allowed_classes' => [Constraint::class, \DateTime::class]]);
}
return $constraint ?: $this->objectManager->get(Constraint::class);
}
/**
* Save current constraint object in be user settings (uC)
*
* @param Constraint $constraint
*/
protected function persistConstraintInBeUserData(Constraint $constraint)
{
$GLOBALS['BE_USER']->pushModuleData(static::class, serialize($constraint));
}
/**
* In case the script execution fails, because the user requested too many results
* (memory exhaustion in php), reset the constraints in be user settings, so
* the belog can be accessed again in the next call.
*/
protected function resetConstraintsOnMemoryExhaustionError()
{
$reservedMemory = new \SplFixedArray(187500); // 3M
register_shutdown_function(function () use (&$reservedMemory) {
$reservedMemory = null; // free the reserved memory
$error = error_get_last();
if (strpos($error['message'], 'Allowed memory size of') !== false) {
$constraint = $this->objectManager->get(Constraint::class);
$this->persistConstraintInBeUserData($constraint);
}
});
}
/**
* Create a sorted array for day and page view from
* the query result of the sys log repository.
*
* If group by page is FALSE, pid is always -1 (will render a flat list),
* otherwise the output is split by pages.
* '12345' is a sub array to split entries by day, number is first second of day
*
* [pid][dayTimestamp][items]
*
* @param QueryResultInterface $logEntries
* @param bool $groupByPage Whether or not log entries should be grouped by page
* @return array
*/
protected function groupLogEntriesByPageAndDay(QueryResultInterface $logEntries, $groupByPage = false)
{
$targetStructure = [];
/** @var LogEntry $entry */
foreach ($logEntries as $entry) {
// Create page split list or flat list
if ($groupByPage) {
$pid = $entry->getEventPid();
} else {
$pid = -1;
}
// Create array if it is not defined yet
if (!is_array($targetStructure[$pid])) {
$targetStructure[$pid] = [];
}
// Get day timestamp of log entry and create sub array if needed
$timestampDay = strtotime(strftime('%d.%m.%Y', $entry->getTstamp()));
if (!is_array($targetStructure[$pid][$timestampDay])) {
$targetStructure[$pid][$timestampDay] = [];
}
// Add row
$targetStructure[$pid][$timestampDay][] = $entry;
}
ksort($targetStructure);
return $targetStructure;
}
/**
* Create options for the user / group drop down.
* This is not moved to a repository by intention to not mix up this 'meta' data
* with real repository work
*
* @return array Key is the option name, value its label
*/
protected function createUserAndGroupListForSelectOptions()
{
$userGroupArray = [];
// Two meta entries: 'all' and 'self'
$userGroupArray[0] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('allUsers', 'Belog');
$userGroupArray[-1] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('self', 'Belog');
// List of groups, key is gr-'uid'
$groups = \TYPO3\CMS\Backend\Utility\BackendUtility::getGroupNames();
foreach ($groups as $group) {
$userGroupArray['gr-' . $group['uid']] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('group', 'Belog') . ' ' . $group['title'];
}
// List of users, key is us-'uid'
$users = \TYPO3\CMS\Backend\Utility\BackendUtility::getUserNames();
foreach ($users as $user) {
$userGroupArray['us-' . $user['uid']] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('user', 'Belog') . ' ' . $user['username'];
}
return $userGroupArray;
}
/**
* Create options for the workspace selector
*
* @return array Key is uid of workspace, value its label
*/
protected function createWorkspaceListForSelectOptions()
{
if (!\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('workspaces')) {
return [];
}
$workspaceArray = [];
// Two meta entries: 'all' and 'live'
$workspaceArray[-99] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('any', 'Belog');
$workspaceArray[0] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('live', 'Belog');
$workspaces = $this->objectManager->get(\TYPO3\CMS\Belog\Domain\Repository\WorkspaceRepository::class)->findAll();
/** @var \TYPO3\CMS\Belog\Domain\Model\Workspace $workspace */
foreach ($workspaces as $workspace) {
$workspaceArray[$workspace->getUid()] = $workspace->getUid() . ': ' . $workspace->getTitle();
}
return $workspaceArray;
}
/**
* If the user is in a workspace different than LIVE,
* we force to show only log entries from the selected workspace,
* and the workspace selector is not shown.
*
* @param Constraint $constraint
*/
protected function forceWorkspaceSelectionIfInWorkspace(Constraint $constraint)
{
if ($GLOBALS['BE_USER']->workspace !== 0) {
$constraint->setWorkspaceUid($GLOBALS['BE_USER']->workspace);
$this->view->assign('showWorkspaceSelector', false);
} else {
$this->view->assign('showWorkspaceSelector', true);
}
}
/**
* Create options for the 'depth of page levels' selector.
* This is shown if the module is displayed in page -> info
*
* @return array Key is depth identifier (1 = One level), value the localized select option label
*/
protected function createPageDepthOptions()
{
$options = [
0 => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0', 'lang'),
1 => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1', 'lang'),
2 => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2', 'lang'),
3 => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3', 'lang'),
4 => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4', 'lang'),
999 => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi', 'lang')
];
return $options;
}
/**
* Calculate the start- and end timestamp from the different time selector options
*
* @param Constraint $constraint
*/
protected function setStartAndEndTimeFromTimeSelector(Constraint $constraint)
{
$startTime = 0;
$endTime = $GLOBALS['EXEC_TIME'];
// @TODO: Refactor this construct
switch ($constraint->getTimeFrame()) {
case self::TIMEFRAME_THISWEEK:
// This week
$week = (date('w') ?: 7) - 1;
$startTime = mktime(0, 0, 0) - $week * 3600 * 24;
break;
case self::TIMEFRAME_LASTWEEK:
// Last week
$week = (date('w') ?: 7) - 1;
$startTime = mktime(0, 0, 0) - ($week + 7) * 3600 * 24;
$endTime = mktime(0, 0, 0) - $week * 3600 * 24;
break;
case self::TIMEFRAME_LASTSEVENDAYS:
// Last 7 days
$startTime = mktime(0, 0, 0) - 7 * 3600 * 24;
break;
case self::TIMEFRAME_THISMONTH:
// This month
$startTime = mktime(0, 0, 0, date('m'), 1);
break;
case self::TIMEFRAME_LASTMONTH:
// Last month
$startTime = mktime(0, 0, 0, date('m') - 1, 1);
$endTime = mktime(0, 0, 0, date('m'), 1);
break;
case self::TIMEFRAME_LAST31DAYS:
// Last 31 days
$startTime = mktime(0, 0, 0) - 31 * 3600 * 24;
break;
case self::TIMEFRAME_CUSTOM:
$startTime = $constraint->getManualDateStart() ? $constraint->getManualDateStart()->getTimestamp() : 0;
$endTime = $constraint->getManualDateStop() ? $constraint->getManualDateStop()->getTimestamp() : 0;
if ($endTime <= $startTime) {
$endTime = $GLOBALS['EXEC_TIME'];
}
break;
default:
}
$constraint->setStartTimestamp($startTime);
$constraint->setEndTimestamp($endTime);
}
}
@@ -0,0 +1,97 @@
<?php
declare(strict_types = 1);
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\Backend\Backend\ToolbarItems\SystemInformationToolbarItem;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Backend\Toolbar\Enumeration\InformationStatus;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
/**
* Count newest exceptions for the system information menu
* @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API.
*/
class SystemInformationController
{
/**
* @var array
*/
protected $backendUserConfiguration;
public function __construct(array $backendUserConfiguration = null)
{
$this->backendUserConfiguration = $backendUserConfiguration ?? $GLOBALS['BE_USER']->uc;
}
/**
* Modifies the SystemInformation array
*
* @param SystemInformationToolbarItem $systemInformationToolbarItem
*/
public function appendMessage(SystemInformationToolbarItem $systemInformationToolbarItem)
{
// we can't use the extbase repository here as the required TypoScript may not be parsed yet
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_log');
$count = $queryBuilder->count('error')
->from('sys_log')
->where(
$queryBuilder->expr()->gte(
'tstamp',
$queryBuilder->createNamedParameter($this->fetchLastAccessTimestamp(), \PDO::PARAM_INT)
),
$queryBuilder->expr()->in(
'error',
$queryBuilder->createNamedParameter([-1, 1, 2], Connection::PARAM_INT_ARRAY)
)
)
->execute()
->fetchColumn(0);
if ($count > 0) {
$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
$systemInformationToolbarItem->addSystemMessage(
sprintf(
LocalizationUtility::translate('systemmessage.errorsInPeriod', 'belog'),
$count,
(string)$uriBuilder->buildUriFromRoute(
'system_BelogLog',
['tx_belog_system_beloglog' => ['constraint' => ['action' => -1]]]
)
),
InformationStatus::STATUS_ERROR,
$count,
'system_BelogLog',
http_build_query(['tx_belog_system_beloglog' => ['constraint' => ['action' => -1]]])
);
}
}
protected function fetchLastAccessTimestamp(): int
{
if (!isset($this->backendUserConfiguration['systeminformation'])) {
return 0;
}
$systemInformationUc = json_decode($this->backendUserConfiguration['systeminformation'], true);
if (!isset($systemInformationUc['system_BelogLog']['lastAccess'])) {
return 0;
}
return (int)$systemInformationUc['system_BelogLog']['lastAccess'];
}
}
@@ -0,0 +1,344 @@
<?php
namespace TYPO3\CMS\Belog\Domain\Model;
/*
* 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!
*/
/**
* Constraints for log entries
* @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API.
*/
class Constraint
{
/**
* Selected user/group; possible values are "gr-<uid>" for a group, "us-<uid>" for a user or -1 for "all users"
*
* @var string
*/
protected $userOrGroup = '0';
/**
* Number of log rows to show
*
* @var int
*/
protected $number = 20;
/**
* UID of selected workspace
*
* @var int
*/
protected $workspaceUid = \TYPO3\CMS\Belog\Domain\Model\Workspace::UID_ANY_WORKSPACE;
/**
* Selected time frame
*
* @var int
*/
protected $timeFrame = 0;
/**
* Selected action
*
* @var int
*/
protected $action = 0;
/**
* Whether rows should be grouped by page
*
* @var bool
*/
protected $groupByPage = false;
/**
* Calculated start timestamp
*
* @var int
*/
protected $startTimestamp = 0;
/**
* Calculated end timestamp
*
* @var int
*/
protected $endTimestamp = 0;
/**
* Manual date start
* @var \DateTime
*/
protected $manualDateStart;
/**
* Manual date stop
* @var \DateTime
*/
protected $manualDateStop;
/**
* Selected page ID in page context
*
* @var int
*/
protected $pageId = 0;
/**
* Page level depth
*
* @var int
*/
protected $depth = 0;
/**
* Set user
*
* @param string $user
*/
public function setUserOrGroup($user)
{
$this->userOrGroup = $user;
}
/**
* Get user
*
* @return string
*/
public function getUserOrGroup()
{
return $this->userOrGroup;
}
/**
* Set number of log rows to show
*
* @param int $number
*/
public function setNumber($number)
{
$this->number = (int)$number;
}
/**
* Get number of log entries to show
*
* @return int
*/
public function getNumber()
{
return $this->number;
}
/**
* Set workspace
*
* @param string $workspace
*/
public function setWorkspaceUid($workspace)
{
$this->workspaceUid = $workspace;
}
/**
* Get workspace
*
* @return string
*/
public function getWorkspaceUid()
{
return $this->workspaceUid;
}
/**
* Set time frame
*
* @param int $timeFrame
*/
public function setTimeFrame($timeFrame)
{
$this->timeFrame = $timeFrame;
}
/**
* Get time frame
*
* @return int
*/
public function getTimeFrame()
{
return (int)$this->timeFrame;
}
/**
* Set action
*
* @param int $action
*/
public function setAction($action)
{
$this->action = $action;
}
/**
* Get action
*
* @return int
*/
public function getAction()
{
return (int)$this->action;
}
/**
* Set group by page
*
* @param bool $groupByPage
*/
public function setGroupByPage($groupByPage)
{
$this->groupByPage = $groupByPage;
}
/**
* Get group by page
*
* @return bool
*/
public function getGroupByPage()
{
return (bool)$this->groupByPage;
}
/**
* Set calculated start timestamp from query constraints
*
* @param int $timestamp
*/
public function setStartTimestamp($timestamp)
{
$this->startTimestamp = (int)$timestamp;
}
/**
* Get calculated start timestamp from query constraints
*
* @return int
*/
public function getStartTimestamp()
{
return $this->startTimestamp;
}
/**
* Set calculated end timestamp from query constraints
*
* @param int $timestamp
*/
public function setEndTimestamp($timestamp)
{
$this->endTimestamp = (int)$timestamp;
}
/**
* Get calculated end timestamp from query constraints
*
* @return int
*/
public function getEndTimestamp()
{
return $this->endTimestamp;
}
/**
* Set page id
*
* @param int $id
*/
public function setPageId($id)
{
$this->pageId = (int)$id;
}
/**
* Get page id
*
* @return int
*/
public function getPageId()
{
return $this->pageId;
}
/**
* Set page level depth
*
* @param int $depth
*/
public function setDepth($depth)
{
$this->depth = $depth;
}
/**
* Get page level depth
*
* @return int
*/
public function getDepth()
{
return (int)$this->depth;
}
/**
* Set manual date start
*
* @param \DateTime $manualDateStart
*/
public function setManualDateStart(\DateTime $manualDateStart = null)
{
$this->manualDateStart = $manualDateStart;
}
/**
* Get manual date start
*
* @return \DateTime
*/
public function getManualDateStart()
{
return $this->manualDateStart;
}
/**
* Set manual date stop
*
* @param \DateTime $manualDateStop
*/
public function setManualDateStop(\DateTime $manualDateStop = null)
{
$this->manualDateStop = $manualDateStop;
}
/**
* Get manual date stop
*
* @return \DateTime
*/
public function getManualDateStop()
{
return $this->manualDateStop;
}
}
@@ -0,0 +1,489 @@
<?php
namespace TYPO3\CMS\Belog\Domain\Model;
/*
* 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!
*/
/**
* A sys log entry
* This model is 'complete': All current database properties are in there.
*
* @todo : This should be stuffed to some more central place
* @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API.
*/
class LogEntry extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
/**
* Storage page ID of the log entry
*
* @var int
*/
protected $pid = 0;
/**
* This is not a relation to BeUser model, since the user does
* not always exist, but we want the uid in then anyway.
* This case is ugly in extbase, the best way we
* have found now is to resolve the username (if it exists) in a
* view helper and just use the uid of the be user here.
*
* @var int
*/
protected $backendUserUid = 0;
/**
* Action ID of the action that happened, for example 3 was a file action
*
* @var int
*/
protected $action = 0;
/**
* UID of the record the event happened to
*
* @var int
*/
protected $recordUid = 0;
/**
* Table name
*
* @var string
*/
protected $tableName = 0;
/**
* PID of the record the event happened to
*
* @var int
*/
protected $recordPid = 0;
/**
* Error code
*
* @var int
*/
protected $error = 0;
/**
* This is the log message itself, but possibly with %s substitutions.
*
* @var string
*/
protected $details = '';
/**
* Timestamp when the log entry was written
*
* @var int
*/
protected $tstamp = 0;
/**
* Type code
*
* @var int
*/
protected $type = 0;
/**
* Details number
*
* @var int
*/
protected $detailsNumber = 0;
/**
* IP address of client
*
* @var string
*/
protected $ip = '';
/**
* Serialized log data. This is a serialized array with substitutions for $this->details.
*
* @var string
*/
protected $logData = '';
/**
* Event PID
*
* @var int
*/
protected $eventPid = 0;
/**
* This is only the UID and not the full workspace object for the same reason as in $beUserUid.
*
* @var int
*/
protected $workspaceUid = 0;
/**
* New ID
*
* @var string
*/
protected $newId = 0;
/**
* Set pid
*
* @param int $pid
*/
public function setPid($pid)
{
$this->pid = (int)$pid;
}
/**
* Get pid
*
* @return int
*/
public function getPid()
{
return $this->pid;
}
/**
* Set backend user uid
*
* @param int $beUserUid
*/
public function setBackendUserUid($beUserUid)
{
$this->backendUserUid = $beUserUid;
}
/**
* Get backend user id
*
* @return int
*/
public function getBackendUserUid()
{
return $this->backendUserUid;
}
/**
* Set action
*
* @param int $action
*/
public function setAction($action)
{
$this->action = $action;
}
/**
* Get action
*
* @return int
*/
public function getAction()
{
return (int)$this->action;
}
/**
* Set record uid
*
* @param int $recordUid
*/
public function setRecordUid($recordUid)
{
$this->recordUid = $recordUid;
}
/**
* Get record uid
*
* @return int
*/
public function getRecordUid()
{
return (int)$this->recordUid;
}
/**
* Set table name
*
* @param string $tableName
*/
public function setTableName($tableName)
{
$this->tableName = $tableName;
}
/**
* Get table name
*
* @return string
*/
public function getTableName()
{
return $this->tableName;
}
/**
* Set record pid
*
* @param int $recordPid
*/
public function setRecordPid($recordPid)
{
$this->recordPid = $recordPid;
}
/**
* Get record pid
*
* @return int
*/
public function getRecordPid()
{
return (int)$this->recordPid;
}
/**
* Set error
*
* @param int $error
*/
public function setError($error)
{
$this->error = $error;
}
/**
* Get error
*
* @return int
*/
public function getError()
{
return (int)$this->error;
}
/**
* Get class name for the error code
*
* @return string
*/
public function getErrorIconClass(): string
{
switch ($this->getError()) {
case 1:
return 'status-dialog-warning';
case 2:
case 3:
return 'status-dialog-error';
default:
return 'empty-empty';
}
}
/**
* Set details
*
* @param string $details
*/
public function setDetails($details)
{
$this->details = $details;
}
/**
* Get details
*
* @return string
*/
public function getDetails()
{
if ($this->type === 255) {
return str_replace('###IP###', $this->ip, $this->details);
}
return $this->details;
}
/**
* Set tstamp
*
* @param int $tstamp
*/
public function setTstamp($tstamp)
{
$this->tstamp = $tstamp;
}
/**
* Get tstamp
*
* @return int
*/
public function getTstamp()
{
return (int)$this->tstamp;
}
/**
* Set type
*
* @param int $type
*/
public function setType($type)
{
$this->type = $type;
}
/**
* Get type
*
* @return int
*/
public function getType()
{
return (int)$this->type;
}
/**
* Set details number
*
* @param int $detailsNumber
*/
public function setDetailsNumber($detailsNumber)
{
$this->detailsNumber = $detailsNumber;
}
/**
* Get details number
*
* @return int
*/
public function getDetailsNumber()
{
return (int)$this->detailsNumber;
}
/**
* Set ip
*
* @param string $ip
*/
public function setIp($ip)
{
$this->ip = $ip;
}
/**
* Get ip
*
* @return string
*/
public function getIp()
{
return $this->ip;
}
/**
* Set log data
*
* @param string $logData
*/
public function setLogData($logData)
{
$this->logData = $logData;
}
/**
* Get log data
*
* @return array
*/
public function getLogData()
{
if ($this->logData === '') {
return [];
}
$logData = @unserialize($this->logData);
if (!is_array($logData)) {
$logData = [];
}
return $logData;
}
/**
* Set event pid
*
* @param int $eventPid
*/
public function setEventPid($eventPid)
{
$this->eventPid = $eventPid;
}
/**
* Get event pid
*
* @return int
*/
public function getEventPid()
{
return (int)$this->eventPid;
}
/**
* Set workspace uid
*
* @param int $workspaceUid
*/
public function setWorkspaceUid($workspaceUid)
{
$this->workspaceUid = $workspaceUid;
}
/**
* Get workspace
*
* @return int
*/
public function getWorkspaceUid()
{
return (int)$this->workspaceUid;
}
/**
* Set new id
*
* @param string $newId
*/
public function setNewId($newId)
{
$this->newId = $newId;
}
/**
* Get new id
*
* @return string
*/
public function getNewId()
{
return $this->newId;
}
}
@@ -0,0 +1,61 @@
<?php
namespace TYPO3\CMS\Belog\Domain\Model;
/*
* 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!
*/
/**
* Stub model for workspaces - only properties required for belog module are added currently
*
* @todo : This should be extended and put at some more central place
* @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API.
*/
class Workspace extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
/**
* @var int
*/
const UID_LIVE_WORKSPACE = 0;
/**
* @var int
*/
const UID_ANY_WORKSPACE = -99;
/**
* title of the workspace
*
* @var string
*/
protected $title = '';
/**
* Set workspace title
*
* @param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* Get workspace title
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
}
@@ -0,0 +1,190 @@
<?php
namespace TYPO3\CMS\Belog\Domain\Repository;
/*
* 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\LogEntry;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Sys log entry repository
* @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API.
*/
class LogEntryRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
{
/**
* Backend users, with UID as key
*
* @var array
*/
protected $beUserList = [];
/**
* Initialize some local variables to be used during creation of objects
*/
public function initializeObject()
{
$this->beUserList = $this->getBackendUsers();
/** @var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $defaultQuerySettings */
$defaultQuerySettings = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface::class);
$defaultQuerySettings->setRespectStoragePage(false);
$this->setDefaultQuerySettings($defaultQuerySettings);
}
/**
* Finds all log entries that match all given constraints.
*
* @param \TYPO3\CMS\Belog\Domain\Model\Constraint $constraint
* @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface<\TYPO3\CMS\Belog\Domain\Model\LogEntry>
*/
public function findByConstraint(\TYPO3\CMS\Belog\Domain\Model\Constraint $constraint)
{
$query = $this->createQuery();
$queryConstraints = $this->createQueryConstraints($query, $constraint);
if (!empty($queryConstraints)) {
$query->matching($query->logicalAnd($queryConstraints));
}
$query->setOrderings(['uid' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING]);
$query->setLimit($constraint->getNumber());
return $query->execute();
}
/**
* Create an array of query constraints from constraint object
*
* @param \TYPO3\CMS\Extbase\Persistence\QueryInterface $query
* @param \TYPO3\CMS\Belog\Domain\Model\Constraint $constraint
* @return array<\TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface>
*/
protected function createQueryConstraints(\TYPO3\CMS\Extbase\Persistence\QueryInterface $query, \TYPO3\CMS\Belog\Domain\Model\Constraint $constraint)
{
$queryConstraints = [];
// User / group handling
$this->addUsersAndGroupsToQueryConstraints($constraint, $query, $queryConstraints);
// Workspace
if ($constraint->getWorkspaceUid() != \TYPO3\CMS\Belog\Domain\Model\Workspace::UID_ANY_WORKSPACE) {
$queryConstraints[] = $query->equals('workspace', $constraint->getWorkspaceUid());
}
// Action (type):
if ($constraint->getAction() > 0) {
$queryConstraints[] = $query->equals('type', $constraint->getAction());
} elseif ($constraint->getAction() == -1) {
$queryConstraints[] = $query->equals('type', 5);
}
// Start / endtime handling: The timestamp calculation was already done
// in the controller, since we need those calculated values in the view as well.
$queryConstraints[] = $query->greaterThanOrEqual('tstamp', $constraint->getStartTimestamp());
$queryConstraints[] = $query->lessThan('tstamp', $constraint->getEndTimestamp());
// Page and level constraint if in page context
$this->addPageTreeConstraintsToQuery($constraint, $query, $queryConstraints);
return $queryConstraints;
}
/**
* Adds constraints for the page(s) to the query; this could be one single page or a whole subtree beneath a given
* page.
*
* @param \TYPO3\CMS\Belog\Domain\Model\Constraint $constraint
* @param \TYPO3\CMS\Extbase\Persistence\QueryInterface $query
* @param array &$queryConstraints the query constraints to add to, will be modified
*/
protected function addPageTreeConstraintsToQuery(\TYPO3\CMS\Belog\Domain\Model\Constraint $constraint, \TYPO3\CMS\Extbase\Persistence\QueryInterface $query, array &$queryConstraints)
{
$pageIds = [];
// Check if we should get a whole tree of pages and not only a single page
if ($constraint->getDepth() > 0) {
/** @var \TYPO3\CMS\Backend\Tree\View\PageTreeView $pageTree */
$pageTree = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\View\PageTreeView::class);
$pageTree->init('AND ' . $GLOBALS['BE_USER']->getPagePermsClause(Permission::PAGE_SHOW));
$pageTree->makeHTML = 0;
$pageTree->fieldArray = ['uid'];
$pageTree->getTree($constraint->getPageId(), $constraint->getDepth());
$pageIds = $pageTree->ids;
}
if (!empty($constraint->getPageId())) {
$pageIds[] = $constraint->getPageId();
}
if (!empty($pageIds)) {
$queryConstraints[] = $query->in('eventPid', $pageIds);
}
}
/**
* Adds users and groups to the query constraints.
*
* @param \TYPO3\CMS\Belog\Domain\Model\Constraint $constraint
* @param \TYPO3\CMS\Extbase\Persistence\QueryInterface $query
* @param array &$queryConstraints the query constraints to add to, will be modified
*/
protected function addUsersAndGroupsToQueryConstraints(\TYPO3\CMS\Belog\Domain\Model\Constraint $constraint, \TYPO3\CMS\Extbase\Persistence\QueryInterface $query, array &$queryConstraints)
{
$userOrGroup = $constraint->getUserOrGroup();
if ($userOrGroup === '') {
return;
}
// Constraint for a group
if (strpos($userOrGroup, 'gr-') === 0) {
$groupId = (int)substr($userOrGroup, 3);
$userIds = [];
foreach ($this->beUserList as $userId => $userData) {
if (\TYPO3\CMS\Core\Utility\GeneralUtility::inList($userData['usergroup_cached_list'], $groupId)) {
$userIds[] = $userId;
}
}
if (!empty($userIds)) {
$queryConstraints[] = $query->in('userid', $userIds);
} else {
// If there are no group members -> use -1 as constraint to not find anything
$queryConstraints[] = $query->in('userid', [-1]);
}
} elseif (strpos($userOrGroup, 'us-') === 0) {
$queryConstraints[] = $query->equals('userid', (int)substr($userOrGroup, 3));
} elseif ($userOrGroup === '-1') {
$queryConstraints[] = $query->equals('userid', (int)$GLOBALS['BE_USER']->user['uid']);
}
}
/**
* Deletes all messages which have the same message details
*
* @param LogEntry $logEntry
* @return int
*/
public function deleteByMessageDetails(LogEntry $logEntry): int
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('sys_log');
$constraints = [];
$constraints[] = $queryBuilder->expr()->eq('details', $queryBuilder->createNamedParameter($logEntry->getDetails()));
// If the detailsNo is 11 or 12 we got messages that are heavily using placeholders. In this case
// we need to compare both the message and the actual log data to not remove too many log entries.
if (GeneralUtility::inList('11,12', $logEntry->getDetailsNumber())) {
$constraints[] = $queryBuilder->expr()->eq('log_data', $queryBuilder->createNamedParameter($logEntry->getLogData()));
}
return $queryBuilder->delete('sys_log')
->where(...$constraints)
->execute();
}
/**
* Get a list of all backend users that are not deleted
*
* @return array
*/
protected function getBackendUsers()
{
return \TYPO3\CMS\Backend\Utility\BackendUtility::getUserNames();
}
}
@@ -0,0 +1,34 @@
<?php
namespace TYPO3\CMS\Belog\Domain\Repository;
/*
* 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!
*/
/**
* Repository for workspaces
* @todo This should be moved to EXT:workspaces if EXT:belog works no matter if workspaces are installed or not
* @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API.
*/
class WorkspaceRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
{
/**
* Initializes the repository.
*/
public function initializeObject()
{
/** @var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $querySettings */
$querySettings = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface::class);
$querySettings->setRespectStoragePage(false);
$this->setDefaultQuerySettings($querySettings);
}
}
@@ -0,0 +1,56 @@
<?php
namespace TYPO3\CMS\Belog\Module;
/*
* 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 Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Core\Bootstrap;
/**
* This class is a wrapper for WebInfo controller of belog.
* It is registered in ext_tables.php with \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::insertModuleFunction()
* and called by the info extension via SCbase functionality.
*
* Extbase currently provides no way to register a "TBE_MODULES_EXT" module directly,
* therefore we need to bootstrap extbase on our own here to jump to the WebInfo controller.
* @internal This class is a experimental and is not considered part of the Public TYPO3 API.
*/
class BackendLogModuleBootstrap
{
/**
* Bootstrap extbase and jump to WebInfo controller
*
* @return string
*/
public function main()
{
$_GET['tx_belog_system_beloglog']['pageId'] = GeneralUtility::_GP('id');
$_GET['tx_belog_system_beloglog']['layout'] = 'Plain';
$serverRequest = $GLOBALS['TYPO3_REQUEST'] ?? null;
if ($serverRequest instanceof ServerRequestInterface) {
$GLOBALS['TYPO3_REQUEST'] = $serverRequest->withQueryParams($_GET);
}
$options['moduleConfiguration'] = [
'extensionName' => 'Belog',
'vendorName' => 'TYPO3\\CMS',
];
$options['moduleName'] = 'system_BelogLog';
$route = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\Route::class, '/system/BelogLog/', $options);
$serverRequest = $serverRequest->withAttribute('route', $route);
$extbaseBootstrap = GeneralUtility::makeInstance(Bootstrap::class);
return $extbaseBootstrap->handleBackendRequest($serverRequest);
}
}
@@ -0,0 +1,62 @@
<?php
namespace TYPO3\CMS\Belog\ViewHelpers\Be;
/*
* 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\Utility\BackendUtility;
use TYPO3\CMS\Fluid\ViewHelpers\Be\AbstractBackendViewHelper;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
/**
* Get page path string from page id
* @internal
*/
class PagePathViewHelper extends AbstractBackendViewHelper
{
/**
* Initializes the arguments
*/
public function initializeArguments()
{
parent::initializeArguments();
$this->registerArgument('pid', 'int', 'Pid of the page', true);
$this->registerArgument('titleLimit', 'int', 'Limit of the page title', false, 20);
}
/**
* Resolve page id to page path string (with automatic cropping to maximum given length).
*
* @return string Page path string
*/
public function render()
{
return static::renderStatic(
$this->arguments,
$this->buildRenderChildrenClosure(),
$this->renderingContext
);
}
/**
* @param array $arguments
* @param \Closure $renderChildrenClosure
* @param RenderingContextInterface $renderingContext
*
* @return string
*/
public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
{
return BackendUtility::getRecordPath($arguments['pid'], '', $arguments['titleLimit']);
}
}
@@ -0,0 +1,70 @@
<?php
namespace TYPO3\CMS\Belog\ViewHelpers\Form;
/*
* 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!
*/
/**
* Extends the usual select ViewHelper, but additionally translates
* the select option labels
*
* Example:
* <belog:form.translateLabelSelect property="number" options="{settings.selectableNumberOfLogEntries}" optionLabelPrefix="numbers"
*
* Will lookup number.200 (or whatever optionValue is given) in locallang database
* @internal
*/
class TranslateLabelSelectViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\SelectViewHelper
{
/**
* Initialize arguments.
*/
public function initializeArguments()
{
parent::initializeArguments();
$this->registerArgument('optionLabelPrefix', 'string', 'Prefix for locallang lookup');
}
/**
* Render the option tags.
*
* Extend the default handling by iterating over calculated options array and
* try to translate the value
*
* @return array An associative array of options, key will be the value of the option tag
*/
protected function getOptions()
{
$options = parent::getOptions();
foreach ($options as $value => $label) {
$options[$value] = $this->translateLabel($label);
}
return $options;
}
/**
* Fetches the translation for a given label. If no translation is found, the label is returned unchanged.
*
* @param string $label The label to translate
* @return string
*/
protected function translateLabel($label)
{
if ($label === '') {
return '';
}
$labelKey = $this->hasArgument('optionLabelPrefix') ? $this->arguments['optionLabelPrefix'] . $label : $label;
$translatedLabel = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($labelKey, $this->renderingContext->getControllerContext()->getRequest()->getControllerExtensionName());
return $translatedLabel ?: $label;
}
}
@@ -0,0 +1,86 @@
<?php
namespace TYPO3\CMS\Belog\ViewHelpers;
/*
* 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\LogEntry;
use TYPO3\CMS\Core\Utility\PathUtility;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
/**
* Create detail string from log entry
* @internal
*/
class FormatDetailsViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;
/**
* Initializes the arguments
*/
public function initializeArguments()
{
$this->registerArgument('logEntry', LogEntry::class, '', true);
}
/**
* Create formatted detail string from log row.
*
* The method handles two properties of the model: details and logData
* Details is a string with possible %s placeholders, and logData an array
* with the substitutions.
* Furthermore, possible files in logData are stripped to their basename if
* the action logged was a file action
*
* @param array $arguments
* @param \Closure $renderChildrenClosure
* @param RenderingContextInterface $renderingContext
*
* @return string Formatted details
*/
public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
{
/** @var LogEntry $logEntry */
$logEntry = $arguments['logEntry'];
$detailString = $logEntry->getDetails();
$substitutes = $logEntry->getLogData();
// Strip paths from file names if the log was a file action
if ($logEntry->getType() === 2) {
$substitutes = self::stripPathFromFilenames($substitutes);
}
// Substitute
if (!empty($substitutes)) {
$detailString = vsprintf($detailString, $substitutes);
}
// Remove possible pending other %s
$detailString = str_replace('%s', '', $detailString);
return $detailString;
}
/**
* Strips path from array of file names
*
* @param array $files
* @return array
*/
protected static function stripPathFromFilenames(array $files = [])
{
foreach ($files as $key => $file) {
$files[$key] = PathUtility::basename($file);
}
return $files;
}
}
@@ -0,0 +1,71 @@
<?php
namespace TYPO3\CMS\Belog\ViewHelpers;
/*
* 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\GeneralUtility;
use TYPO3\CMS\Extbase\Domain\Repository\BackendUserRepository;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
/**
* Get username from backend user id
* @internal
*/
class UsernameViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;
/**
* First level cache of user names
*
* @var array
*/
protected static $usernameRuntimeCache = [];
/**
* Initializes the arguments
*/
public function initializeArguments()
{
$this->registerArgument('uid', 'int', 'Uid of the user', true);
}
/**
* Resolve user name from backend user id.
*
* @param array $arguments
* @param \Closure $renderChildrenClosure
* @param RenderingContextInterface $renderingContext
*
* @return string Username or an empty string if there is no user with that UID
*/
public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
{
$uid = $arguments['uid'];
if (isset(static::$usernameRuntimeCache[$uid])) {
return static::$usernameRuntimeCache[$uid];
}
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$backendUserRepository = $objectManager->get(BackendUserRepository::class);
/** @var \TYPO3\CMS\Extbase\Domain\Model\BackendUser $user */
$user = $backendUserRepository->findByUid($uid);
// $user may be NULL if user was deleted from DB, set it to empty string to always return a string
static::$usernameRuntimeCache[$uid] = $user === null ? '' : $user->getUserName();
return static::$usernameRuntimeCache[$uid];
}
}
@@ -0,0 +1,89 @@
<?php
namespace TYPO3\CMS\Belog\ViewHelpers;
/*
* 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\Repository\WorkspaceRepository;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContext;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
/**
* Get workspace title from workspace id
* @internal
*/
class WorkspaceTitleViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;
/**
* First level cache of workspace titles
*
* @var array
*/
protected static $workspaceTitleRuntimeCache = [];
/**
* Initializes the arguments
*/
public function initializeArguments()
{
$this->registerArgument('uid', 'int', 'UID of the workspace', true);
}
/**
* Resolve workspace title from UID.
*
* @param array $arguments
* @param \Closure $renderChildrenClosure
* @param RenderingContextInterface $renderingContext
*
* @return string workspace title or UID
* @throws \InvalidArgumentException
*/
public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
{
if (!$renderingContext instanceof RenderingContext) {
throw new \InvalidArgumentException('The given rendering context is not of type "TYPO3\CMS\Fluid\Core\Rendering\RenderingContext"', 1468363946);
}
$uid = $arguments['uid'];
if (isset(static::$workspaceTitleRuntimeCache[$uid])) {
return static::$workspaceTitleRuntimeCache[$uid];
}
if ($uid === 0) {
static::$workspaceTitleRuntimeCache[$uid] = LocalizationUtility::translate(
'live',
$renderingContext->getControllerContext()->getRequest()->getControllerExtensionName()
);
} elseif (!ExtensionManagementUtility::isLoaded('workspaces')) {
static::$workspaceTitleRuntimeCache[$uid] = '';
} else {
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$workspaceRepository = $objectManager->get(WorkspaceRepository::class);
/** @var \TYPO3\CMS\Belog\Domain\Model\Workspace $workspace */
$workspace = $workspaceRepository->findByUid($uid);
// $workspace may be null, force empty string in this case
static::$workspaceTitleRuntimeCache[$uid] = $workspace === null ? '' : $workspace->getTitle();
}
return static::$workspaceTitleRuntimeCache[$uid];
}
}