TYPO3 v15 dev-main snapshot ()
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
/vendor/
|
||||||
@@ -0,0 +1,346 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace TYPO3\CMS\Belog\Controller;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
|
||||||
|
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||||
|
use TYPO3\CMS\Belog\Domain\Model\Constraint;
|
||||||
|
use TYPO3\CMS\Belog\Domain\Model\LogEntry;
|
||||||
|
use TYPO3\CMS\Belog\Domain\Repository\LogEntryRepository;
|
||||||
|
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
|
||||||
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||||
|
use TYPO3\CMS\Core\Domain\DateTimeFormat;
|
||||||
|
use TYPO3\CMS\Core\Http\AllowedMethodsTrait;
|
||||||
|
use TYPO3\CMS\Core\Localization\LanguageService;
|
||||||
|
use TYPO3\CMS\Core\Type\Bitmask\Permission;
|
||||||
|
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
|
||||||
|
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
|
||||||
|
use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter;
|
||||||
|
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
use AllowedMethodsTrait;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
protected readonly ModuleTemplateFactory $moduleTemplateFactory,
|
||||||
|
protected readonly LogEntryRepository $logEntryRepository,
|
||||||
|
protected readonly ConnectionPool $connectionPool,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize list action
|
||||||
|
*/
|
||||||
|
public function initializeListAction(): void
|
||||||
|
{
|
||||||
|
if (!isset($this->settings['dateFormat'])) {
|
||||||
|
$this->settings['dateFormat'] = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] ?: 'd-m-Y';
|
||||||
|
}
|
||||||
|
if (!isset($this->settings['timeFormat'])) {
|
||||||
|
$this->settings['timeFormat'] = $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'];
|
||||||
|
}
|
||||||
|
// Static format needed for date picker (flatpickr), see BackendController::generateJavascript() and #91606
|
||||||
|
$this->settings['dateTimeFormat'] = 'H:i d-m-Y';
|
||||||
|
$constraintConfiguration = $this->arguments->getArgument('constraint')->getPropertyMappingConfiguration();
|
||||||
|
$constraintConfiguration->allowAllProperties();
|
||||||
|
$constraintConfiguration->forProperty('manualDateStart')->setTypeConverterOption(DateTimeConverter::class, DateTimeConverter::CONFIGURATION_DATE_FORMAT, DateTimeFormat::ISO8601_LOCALTIME);
|
||||||
|
$constraintConfiguration->forProperty('manualDateStop')->setTypeConverterOption(DateTimeConverter::class, DateTimeConverter::CONFIGURATION_DATE_FORMAT, DateTimeFormat::ISO8601_LOCALTIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show general information and the installed modules
|
||||||
|
*/
|
||||||
|
public function listAction(?Constraint $constraint = null, string $operation = ''): ResponseInterface
|
||||||
|
{
|
||||||
|
if ($operation === 'reset-filters') {
|
||||||
|
$constraint = new Constraint();
|
||||||
|
} elseif ($constraint === null) {
|
||||||
|
$constraint = $this->getConstraintFromBeUserData();
|
||||||
|
}
|
||||||
|
|
||||||
|
$access = true;
|
||||||
|
$pageId = $constraint->getPageId();
|
||||||
|
$permsClause = $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW);
|
||||||
|
if ($pageId === 0 || (BackendUtility::readPageAccess($pageId, $permsClause) ?: []) === []) {
|
||||||
|
if (!$this->getBackendUser()->isAdmin()) {
|
||||||
|
// User does not have access to selected site
|
||||||
|
$access = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($pageId === 0) {
|
||||||
|
// In case no page is selected, set depth to 0 to display only "global" logs
|
||||||
|
$constraint->setDepth(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->persistConstraintInBeUserData($constraint);
|
||||||
|
$this->resetConstraintsOnMemoryExhaustionError();
|
||||||
|
$this->setStartAndEndTimeFromTimeSelector($constraint);
|
||||||
|
$showWorkspaceSelector = $this->forceWorkspaceSelectionIfInWorkspace($constraint);
|
||||||
|
|
||||||
|
$viewVariables = [
|
||||||
|
'access' => $access,
|
||||||
|
'settings' => $this->settings,
|
||||||
|
'pageId' => $pageId,
|
||||||
|
'constraint' => $constraint,
|
||||||
|
'userGroups' => $this->createUserAndGroupListForSelectOptions(),
|
||||||
|
'selectableNumberOfLogEntries' => $this->createSelectableNumberOfLogEntriesOptions(),
|
||||||
|
'workspaces' => $this->createWorkspaceListForSelectOptions(),
|
||||||
|
'pageDepths' => $this->createPageDepthOptions(),
|
||||||
|
'channels' => $this->logEntryRepository->getUsedChannels(),
|
||||||
|
'channel' => $constraint->getChannel(),
|
||||||
|
'levels' => $this->logEntryRepository->getUsedLevels(),
|
||||||
|
'level' => $constraint->getLevel(),
|
||||||
|
'showWorkspaceSelector' => $showWorkspaceSelector,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($access) {
|
||||||
|
// Only fetch log entries if user has access
|
||||||
|
$logEntries = $this->logEntryRepository->findByConstraint($constraint);
|
||||||
|
$groupedLogEntries = $this->groupLogEntriesDay($logEntries);
|
||||||
|
$viewVariables['groupedLogEntries'] = $groupedLogEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
$view = $this->moduleTemplateFactory->create($this->request);
|
||||||
|
$view->getDocHeaderComponent()->setShortcutContext(
|
||||||
|
'system_log',
|
||||||
|
$this->getLanguageService()->translate('title', 'belog.module')
|
||||||
|
);
|
||||||
|
return $view->setFlashMessageQueue($this->getFlashMessageQueue())
|
||||||
|
->setTitle(LocalizationUtility::translate('title', 'belog.module'))
|
||||||
|
->assignMultiple($viewVariables)
|
||||||
|
->renderResponse('BackendLog/List');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function initializeDeleteMessageAction(): void
|
||||||
|
{
|
||||||
|
$this->assertAllowedHttpMethod($this->request, 'POST');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all log entries that share the same message with the log entry given
|
||||||
|
* in $errorUid
|
||||||
|
*/
|
||||||
|
public function deleteMessageAction(int $errorUid): ResponseInterface
|
||||||
|
{
|
||||||
|
$logEntry = $this->logEntryRepository->findByUid($errorUid);
|
||||||
|
if (!$logEntry) {
|
||||||
|
$this->addFlashMessage(LocalizationUtility::translate('actions.delete.noRowFound', 'belog') ?? '', '', ContextualFeedbackSeverity::WARNING);
|
||||||
|
return $this->redirect('list');
|
||||||
|
}
|
||||||
|
$numberOfDeletedRows = $this->logEntryRepository->deleteByMessageDetails($logEntry);
|
||||||
|
$this->addFlashMessage(sprintf(LocalizationUtility::translate('actions.delete.message', 'belog') ?? '', $numberOfDeletedRows));
|
||||||
|
BackendUtility::setUpdateSignal('updateSystemInformationMenu');
|
||||||
|
return $this->redirect('list');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get module states (the constraint object) from user data
|
||||||
|
*/
|
||||||
|
protected function getConstraintFromBeUserData(): Constraint
|
||||||
|
{
|
||||||
|
$serializedConstraint = $this->request->getAttribute('moduleData')->get('constraint');
|
||||||
|
$constraint = null;
|
||||||
|
if (is_string($serializedConstraint) && !empty($serializedConstraint)) {
|
||||||
|
$constraint = @unserialize($serializedConstraint, ['allowed_classes' => [Constraint::class, \DateTime::class]]);
|
||||||
|
}
|
||||||
|
return $constraint ?: GeneralUtility::makeInstance(Constraint::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save current constraint object in be user settings (uC)
|
||||||
|
*/
|
||||||
|
protected function persistConstraintInBeUserData(Constraint $constraint): void
|
||||||
|
{
|
||||||
|
$moduleData = $this->request->getAttribute('moduleData');
|
||||||
|
$moduleData->set('constraint', serialize($constraint));
|
||||||
|
$this->getBackendUser()->pushModuleData($moduleData->getModuleIdentifier(), $moduleData->toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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(): void
|
||||||
|
{
|
||||||
|
$reservedMemory = new \SplFixedArray(187500); // 3M
|
||||||
|
register_shutdown_function(function () use (&$reservedMemory): void {
|
||||||
|
$reservedMemory = null; // free the reserved memory
|
||||||
|
$error = error_get_last();
|
||||||
|
if (str_contains($error['message'] ?? '', 'Allowed memory size of')) {
|
||||||
|
$constraint = GeneralUtility::makeInstance(Constraint::class);
|
||||||
|
$this->persistConstraintInBeUserData($constraint);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a sorted array for day from the query result of the sys log repository.
|
||||||
|
*
|
||||||
|
* pid is always -1 to render a flat list.
|
||||||
|
* '12345' is a sub array to split entries by day, number is first second of day
|
||||||
|
*
|
||||||
|
* [pid][dayTimestamp][items]
|
||||||
|
*
|
||||||
|
* @param array<LogEntry> $logEntries
|
||||||
|
*/
|
||||||
|
protected function groupLogEntriesDay(array $logEntries): array
|
||||||
|
{
|
||||||
|
$targetStructure = [];
|
||||||
|
foreach ($logEntries as $entry) {
|
||||||
|
$pid = -1;
|
||||||
|
// Create array if it is not defined yet
|
||||||
|
if (!is_array($targetStructure[$pid] ?? false)) {
|
||||||
|
$targetStructure[-1] = [];
|
||||||
|
}
|
||||||
|
// Get day timestamp of log entry and create sub array if needed
|
||||||
|
$timestampDay = strtotime($entry->getTstamp()->format('Y-m-d'));
|
||||||
|
if (!is_array($targetStructure[$pid][$timestampDay] ?? false)) {
|
||||||
|
$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.
|
||||||
|
*/
|
||||||
|
protected function createUserAndGroupListForSelectOptions(): array
|
||||||
|
{
|
||||||
|
$items = [];
|
||||||
|
foreach (BackendUtility::getGroupNames() as $group) {
|
||||||
|
$items['groups']['gr-' . $group['uid']] = BackendUtility::getRecordTitle('be_groups', $group);
|
||||||
|
}
|
||||||
|
foreach (BackendUtility::getUserNames() as $user) {
|
||||||
|
$items['users']['us-' . $user['uid']] = BackendUtility::getRecordTitle('be_users', $user);
|
||||||
|
}
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for the "max" drop down
|
||||||
|
*/
|
||||||
|
protected function createSelectableNumberOfLogEntriesOptions(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
50 => 50,
|
||||||
|
100 => 100,
|
||||||
|
200 => 200,
|
||||||
|
500 => 500,
|
||||||
|
1000 => 1000,
|
||||||
|
1000000 => LocalizationUtility::translate('any', 'Belog'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create options for the workspace selector
|
||||||
|
*
|
||||||
|
* @return array Key is uid of workspace, value its label
|
||||||
|
*/
|
||||||
|
protected function createWorkspaceListForSelectOptions(): array
|
||||||
|
{
|
||||||
|
if (!ExtensionManagementUtility::isLoaded('workspaces')) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$workspaceArray = [];
|
||||||
|
// Two meta entries: 'all' and 'live'
|
||||||
|
$workspaceArray[-99] = LocalizationUtility::translate('any', 'Belog');
|
||||||
|
$workspaceArray[0] = LocalizationUtility::translate('live', 'Belog');
|
||||||
|
$resultSet = $this->connectionPool->getQueryBuilderForTable('sys_workspace')
|
||||||
|
->select('uid', 'title')
|
||||||
|
->from('sys_workspace')
|
||||||
|
->executeQuery();
|
||||||
|
while ($row = $resultSet->fetchAssociative()) {
|
||||||
|
$workspaceArray[$row['uid']] = $row['uid'] . ': ' . $row['title'];
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
protected function forceWorkspaceSelectionIfInWorkspace(Constraint $constraint): bool
|
||||||
|
{
|
||||||
|
if (!ExtensionManagementUtility::isLoaded('workspaces')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->getBackendUser()->workspace !== 0) {
|
||||||
|
$constraint->setWorkspaceUid($this->getBackendUser()->workspace);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create options for the 'depth of page levels' selector.
|
||||||
|
*
|
||||||
|
* @return array Key is depth identifier (1 = One level), value the localized select option label
|
||||||
|
*/
|
||||||
|
protected function createPageDepthOptions(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
0 => LocalizationUtility::translate('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
|
||||||
|
1 => LocalizationUtility::translate('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
|
||||||
|
2 => LocalizationUtility::translate('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
|
||||||
|
3 => LocalizationUtility::translate('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
|
||||||
|
4 => LocalizationUtility::translate('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
|
||||||
|
999 => LocalizationUtility::translate('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the start- and end timestamp
|
||||||
|
*/
|
||||||
|
protected function setStartAndEndTimeFromTimeSelector(Constraint $constraint): void
|
||||||
|
{
|
||||||
|
$startTime = $constraint->getManualDateStart() ? $constraint->getManualDateStart()->getTimestamp() : 0;
|
||||||
|
$endTime = $constraint->getManualDateStop() ? $constraint->getManualDateStop()->getTimestamp() : 0;
|
||||||
|
if ($endTime <= $startTime) {
|
||||||
|
$endTime = $GLOBALS['EXEC_TIME'];
|
||||||
|
}
|
||||||
|
$constraint->setStartTimestamp($startTime);
|
||||||
|
$constraint->setEndTimestamp($endTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getBackendUser(): BackendUserAuthentication
|
||||||
|
{
|
||||||
|
return $GLOBALS['BE_USER'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getLanguageService(): LanguageService
|
||||||
|
{
|
||||||
|
return $GLOBALS['LANG'];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace TYPO3\CMS\Belog\Domain\Model;
|
||||||
|
|
||||||
|
use Psr\Log\LogLevel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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"
|
||||||
|
*/
|
||||||
|
protected string $userOrGroup = '0';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of log rows to show
|
||||||
|
*/
|
||||||
|
protected int $number = 20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UID of selected workspace
|
||||||
|
*/
|
||||||
|
protected int $workspaceUid = -99;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selected channel
|
||||||
|
*/
|
||||||
|
protected string $channel = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selected level
|
||||||
|
*/
|
||||||
|
protected string $level = LogLevel::DEBUG;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculated start timestamp
|
||||||
|
*/
|
||||||
|
protected int $startTimestamp = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculated end timestamp
|
||||||
|
*/
|
||||||
|
protected int $endTimestamp = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manual date start
|
||||||
|
*/
|
||||||
|
protected ?\DateTime $manualDateStart = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manual date stop
|
||||||
|
*/
|
||||||
|
protected ?\DateTime $manualDateStop = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selected page ID in page context
|
||||||
|
*/
|
||||||
|
protected int $pageId = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page level depth
|
||||||
|
*/
|
||||||
|
protected int $depth = 0;
|
||||||
|
|
||||||
|
public function setUserOrGroup(string $user): void
|
||||||
|
{
|
||||||
|
$this->userOrGroup = $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUserOrGroup(): string
|
||||||
|
{
|
||||||
|
return $this->userOrGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setNumber(int $number): void
|
||||||
|
{
|
||||||
|
$this->number = $number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNumber(): int
|
||||||
|
{
|
||||||
|
return $this->number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setWorkspaceUid(int $workspace): void
|
||||||
|
{
|
||||||
|
$this->workspaceUid = $workspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getWorkspaceUid(): int
|
||||||
|
{
|
||||||
|
return $this->workspaceUid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setChannel(string $channel): void
|
||||||
|
{
|
||||||
|
$this->channel = $channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getChannel(): string
|
||||||
|
{
|
||||||
|
return $this->channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setLevel(string $level): void
|
||||||
|
{
|
||||||
|
$this->level = $level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLevel(): string
|
||||||
|
{
|
||||||
|
return $this->level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setStartTimestamp(int $timestamp): void
|
||||||
|
{
|
||||||
|
$this->startTimestamp = $timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStartTimestamp(): int
|
||||||
|
{
|
||||||
|
return $this->startTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setEndTimestamp(int $timestamp): void
|
||||||
|
{
|
||||||
|
$this->endTimestamp = $timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEndTimestamp(): int
|
||||||
|
{
|
||||||
|
return $this->endTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPageId(?int $id): void
|
||||||
|
{
|
||||||
|
$this->pageId = $id ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPageId(): int
|
||||||
|
{
|
||||||
|
return $this->pageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDepth(int $depth): void
|
||||||
|
{
|
||||||
|
$this->depth = $depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDepth(): int
|
||||||
|
{
|
||||||
|
return $this->depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setManualDateStart(?\DateTime $manualDateStart = null): void
|
||||||
|
{
|
||||||
|
$this->manualDateStart = $manualDateStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getManualDateStart(): ?\DateTime
|
||||||
|
{
|
||||||
|
return $this->manualDateStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setManualDateStop(?\DateTime $manualDateStop = null): void
|
||||||
|
{
|
||||||
|
$this->manualDateStop = $manualDateStop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getManualDateStop(): ?\DateTime
|
||||||
|
{
|
||||||
|
return $this->manualDateStop;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace TYPO3\CMS\Belog\Domain\Model;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\Log\LogDataTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sys log entry
|
||||||
|
* This model is 'complete': All current database properties are in there.
|
||||||
|
*
|
||||||
|
* @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API.
|
||||||
|
*/
|
||||||
|
class LogEntry
|
||||||
|
{
|
||||||
|
use LogDataTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int<0, max>
|
||||||
|
*/
|
||||||
|
protected int $uid = 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.
|
||||||
|
*/
|
||||||
|
protected int $backendUserUid = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action ID of the action that happened, for example 3 was a file action
|
||||||
|
*/
|
||||||
|
protected int $action = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UID of the record the event happened to
|
||||||
|
*/
|
||||||
|
protected int $recordUid = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table name
|
||||||
|
*/
|
||||||
|
protected string $tableName = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PID of the record the event happened to
|
||||||
|
*/
|
||||||
|
protected int $recordPid = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error code
|
||||||
|
*/
|
||||||
|
protected int $error = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the log message itself, but possibly with %s substitutions.
|
||||||
|
*/
|
||||||
|
protected string $details = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timestamp when the log entry was written
|
||||||
|
*/
|
||||||
|
protected \DateTimeInterface $tstamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type code
|
||||||
|
*/
|
||||||
|
protected int $type = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Channel name.
|
||||||
|
*/
|
||||||
|
protected string $channel = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Level.
|
||||||
|
*/
|
||||||
|
protected string $level = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IP address of client
|
||||||
|
*/
|
||||||
|
protected string $ip = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialized log data. This is a serialized array with substitutions for $this->details.
|
||||||
|
*/
|
||||||
|
protected string $logData = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event PID
|
||||||
|
*/
|
||||||
|
protected int $eventPid = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is only the UID and not the full workspace object for the same reason as in $beUserUid.
|
||||||
|
*/
|
||||||
|
protected int $workspaceUid = 0;
|
||||||
|
|
||||||
|
public function getUid(): int
|
||||||
|
{
|
||||||
|
return $this->uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBackendUserUid(): int
|
||||||
|
{
|
||||||
|
return $this->backendUserUid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAction(): int
|
||||||
|
{
|
||||||
|
return $this->action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRecordUid(): int
|
||||||
|
{
|
||||||
|
return $this->recordUid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTableName(): string
|
||||||
|
{
|
||||||
|
return $this->tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRecordPid(): int
|
||||||
|
{
|
||||||
|
return $this->recordPid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setError(int $error): void
|
||||||
|
{
|
||||||
|
$this->error = $error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getError(): int
|
||||||
|
{
|
||||||
|
return $this->error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getErrorIconClass(): string
|
||||||
|
{
|
||||||
|
return match ($this->getError()) {
|
||||||
|
1 => 'status-dialog-warning',
|
||||||
|
2, 3 => 'status-dialog-error',
|
||||||
|
default => 'empty-empty',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDetails(): string
|
||||||
|
{
|
||||||
|
if ($this->type === 255) {
|
||||||
|
return str_replace('###IP###', $this->ip, $this->details);
|
||||||
|
}
|
||||||
|
return $this->details;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTstamp(): \DateTimeInterface
|
||||||
|
{
|
||||||
|
return $this->tstamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getType(): int
|
||||||
|
{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getChannel(): string
|
||||||
|
{
|
||||||
|
return $this->channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLevel(): string
|
||||||
|
{
|
||||||
|
return $this->level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIp(): string
|
||||||
|
{
|
||||||
|
return $this->ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setLogData(string $logData): void
|
||||||
|
{
|
||||||
|
$this->logData = $logData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLogData(): array
|
||||||
|
{
|
||||||
|
if ($this->logData === '') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$logData = $this->unserializeLogData($this->logData);
|
||||||
|
return $logData ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLogDataRaw(): string
|
||||||
|
{
|
||||||
|
return $this->logData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEventPid(): int
|
||||||
|
{
|
||||||
|
return $this->eventPid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getWorkspaceUid(): int
|
||||||
|
{
|
||||||
|
return $this->workspaceUid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function createFromDatabaseRecord(array $row): self
|
||||||
|
{
|
||||||
|
$obj = new self();
|
||||||
|
$obj->uid = $row['uid'] ?? $obj->uid;
|
||||||
|
$obj->tstamp = new \DateTimeImmutable(date('Y-m-d\TH:i:s', $row['tstamp'] ?? 0));
|
||||||
|
$obj->backendUserUid = $row['userid'] ?? $obj->backendUserUid;
|
||||||
|
$obj->action = $row['action'] ?? $obj->action;
|
||||||
|
$obj->recordUid = $row['recuid'] ?? $obj->recordUid;
|
||||||
|
$obj->tableName = $row['tablename'] ?? $obj->tableName;
|
||||||
|
$obj->recordPid = $row['recpid'] ?? $obj->recordPid;
|
||||||
|
$obj->error = $row['error'] ?? $obj->error;
|
||||||
|
$obj->type = $row['type'] ?? $obj->type;
|
||||||
|
$obj->details = $row['details'] ?? $obj->details;
|
||||||
|
$obj->ip = $row['IP'] ?? $obj->ip;
|
||||||
|
$obj->logData = $row['log_data'] ?? $obj->logData;
|
||||||
|
$obj->eventPid = $row['event_pid'] ?? $obj->eventPid;
|
||||||
|
$obj->workspaceUid = $row['workspace'] ?? $obj->workspaceUid;
|
||||||
|
$obj->channel = $row['channel'] ?? $obj->channel;
|
||||||
|
$obj->level = $row['level'] ?? $obj->level;
|
||||||
|
return $obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace TYPO3\CMS\Belog\Domain\Repository;
|
||||||
|
|
||||||
|
use Psr\Log\LogLevel;
|
||||||
|
use TYPO3\CMS\Backend\Tree\Repository\PageTreeRepository;
|
||||||
|
use TYPO3\CMS\Belog\Domain\Model\Constraint;
|
||||||
|
use TYPO3\CMS\Belog\Domain\Model\LogEntry;
|
||||||
|
use TYPO3\CMS\Core\Authentication\GroupResolver;
|
||||||
|
use TYPO3\CMS\Core\Database\Connection;
|
||||||
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||||
|
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
||||||
|
use TYPO3\CMS\Core\Log\LogLevel as Typo3LogLevel;
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
readonly class LogEntryRepository
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private GroupResolver $groupResolver,
|
||||||
|
private ConnectionPool $connectionPool,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function findByUid($uid): ?LogEntry
|
||||||
|
{
|
||||||
|
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_log');
|
||||||
|
$row = $queryBuilder
|
||||||
|
->select('*')
|
||||||
|
->from('sys_log')
|
||||||
|
->where(
|
||||||
|
$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, Connection::PARAM_INT))
|
||||||
|
)
|
||||||
|
->fetchAssociative();
|
||||||
|
return $row ? LogEntry::createFromDatabaseRecord($row) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds all log entries that match all given constraints.
|
||||||
|
*
|
||||||
|
* @return array<LogEntry>
|
||||||
|
*/
|
||||||
|
public function findByConstraint(Constraint $constraint): array
|
||||||
|
{
|
||||||
|
$query = $this->connectionPool->getQueryBuilderForTable('sys_log');
|
||||||
|
$query->select('*')
|
||||||
|
->from('sys_log')
|
||||||
|
->orderBy('uid', 'DESC');
|
||||||
|
$queryConstraints = $this->createQueryConstraints($query, $constraint);
|
||||||
|
$stmt = $query
|
||||||
|
->where(...$queryConstraints)
|
||||||
|
->setMaxResults($constraint->getNumber())
|
||||||
|
->executeQuery();
|
||||||
|
$result = [];
|
||||||
|
while ($row = $stmt->fetchAssociative()) {
|
||||||
|
$result[] = LogEntry::createFromDatabaseRecord($row);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an array of query constraints from constraint object
|
||||||
|
*/
|
||||||
|
protected function createQueryConstraints(QueryBuilder $query, Constraint $constraint): array
|
||||||
|
{
|
||||||
|
// User / group handling
|
||||||
|
$queryConstraints = $this->addUsersAndGroupsToQueryConstraints($constraint, $query);
|
||||||
|
// Workspace
|
||||||
|
if ($constraint->getWorkspaceUid() !== -99) {
|
||||||
|
$queryConstraints[] = $query->expr()->eq('workspace', $query->createNamedParameter($constraint->getWorkspaceUid(), Connection::PARAM_INT));
|
||||||
|
}
|
||||||
|
// Channel
|
||||||
|
if ($channel = $constraint->getChannel()) {
|
||||||
|
$queryConstraints[] = $query->expr()->eq('channel', $query->createNamedParameter($channel));
|
||||||
|
}
|
||||||
|
// Level
|
||||||
|
if ($level = $constraint->getLevel()) {
|
||||||
|
$queryConstraints[] = $query->expr()->in('level', $query->createNamedParameter(Typo3LogLevel::atLeast($level), Connection::PARAM_STR_ARRAY));
|
||||||
|
}
|
||||||
|
// 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->expr()->gte('tstamp', $query->createNamedParameter($constraint->getStartTimestamp(), Connection::PARAM_INT));
|
||||||
|
$queryConstraints[] = $query->expr()->lt('tstamp', $query->createNamedParameter($constraint->getEndTimestamp(), Connection::PARAM_INT));
|
||||||
|
// Page and level constraint if in page context
|
||||||
|
$constraint = $this->addPageTreeConstraintsToQuery($constraint, $query);
|
||||||
|
if ($constraint) {
|
||||||
|
$queryConstraints[] = $constraint;
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
protected function addPageTreeConstraintsToQuery(Constraint $constraint, QueryBuilder $query): ?string
|
||||||
|
{
|
||||||
|
$pageIds = [];
|
||||||
|
// Check if we should get a whole tree of pages and not only a single page
|
||||||
|
if ($constraint->getDepth() > 0) {
|
||||||
|
$repository = GeneralUtility::makeInstance(PageTreeRepository::class);
|
||||||
|
$repository->setAdditionalWhereClause($GLOBALS['BE_USER']->getPagePermsClause(Permission::PAGE_SHOW));
|
||||||
|
$pages = $repository->getFlattenedPages([$constraint->getPageId()], $constraint->getDepth());
|
||||||
|
foreach ($pages as $page) {
|
||||||
|
$pageIds[] = (int)$page['uid'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($constraint->getPageId())) {
|
||||||
|
$pageIds[] = $constraint->getPageId();
|
||||||
|
}
|
||||||
|
if (!empty($pageIds)) {
|
||||||
|
return $query->expr()->in('event_pid', $query->createNamedParameter($pageIds, Connection::PARAM_INT_ARRAY));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds users and groups to the query constraints.
|
||||||
|
*/
|
||||||
|
protected function addUsersAndGroupsToQueryConstraints(Constraint $constraint, QueryBuilder $query): array
|
||||||
|
{
|
||||||
|
$userOrGroup = $constraint->getUserOrGroup();
|
||||||
|
if ($userOrGroup === '') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$queryConstraints = [];
|
||||||
|
// Constraint for a group
|
||||||
|
if (str_starts_with($userOrGroup, 'gr-')) {
|
||||||
|
$groupId = (int)substr($userOrGroup, 3);
|
||||||
|
$userIds = $this->groupResolver->findAllUsersInGroups([$groupId], 'be_groups', 'be_users');
|
||||||
|
if (!empty($userIds)) {
|
||||||
|
$userIds = array_column($userIds, 'uid');
|
||||||
|
$userIds = array_map(intval(...), $userIds);
|
||||||
|
$queryConstraints[] = $query->expr()->in('userid', $query->createNamedParameter($userIds, Connection::PARAM_INT_ARRAY));
|
||||||
|
} else {
|
||||||
|
// If there are no group members -> use -1 as constraint to not find anything
|
||||||
|
$queryConstraints[] = $query->expr()->eq('userid', $query->createNamedParameter(-1, Connection::PARAM_INT));
|
||||||
|
}
|
||||||
|
} elseif (str_starts_with($userOrGroup, 'us-')) {
|
||||||
|
$queryConstraints[] = $query->expr()->in('userid', $query->createNamedParameter((int)substr($userOrGroup, 3), Connection::PARAM_INT));
|
||||||
|
} elseif ($userOrGroup === '-1') {
|
||||||
|
$queryConstraints[] = $query->expr()->in('userid', $query->createNamedParameter((int)$GLOBALS['BE_USER']->user['uid'], Connection::PARAM_INT));
|
||||||
|
}
|
||||||
|
return $queryConstraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all messages which have the same message details
|
||||||
|
*/
|
||||||
|
public function deleteByMessageDetails(LogEntry $logEntry): int
|
||||||
|
{
|
||||||
|
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_log');
|
||||||
|
return $queryBuilder->delete('sys_log')
|
||||||
|
->where($queryBuilder->expr()->eq('details', $queryBuilder->createNamedParameter($logEntry->getDetails())))
|
||||||
|
->executeStatement();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUsedChannels(): array
|
||||||
|
{
|
||||||
|
$channels = $this->connectionPool->getQueryBuilderForTable('sys_log')
|
||||||
|
->select('channel')
|
||||||
|
->distinct()
|
||||||
|
->from('sys_log')
|
||||||
|
->orderBy('channel')
|
||||||
|
->executeQuery()
|
||||||
|
->fetchFirstColumn();
|
||||||
|
return array_combine($channels, $channels);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUsedLevels(): array
|
||||||
|
{
|
||||||
|
static $allLevels = [
|
||||||
|
LogLevel::EMERGENCY,
|
||||||
|
LogLevel::ALERT,
|
||||||
|
LogLevel::CRITICAL,
|
||||||
|
LogLevel::ERROR,
|
||||||
|
LogLevel::WARNING,
|
||||||
|
LogLevel::NOTICE,
|
||||||
|
LogLevel::INFO,
|
||||||
|
LogLevel::DEBUG,
|
||||||
|
];
|
||||||
|
$levels = $this->connectionPool->getQueryBuilderForTable('sys_log')
|
||||||
|
->select('level')
|
||||||
|
->distinct()
|
||||||
|
->from('sys_log')
|
||||||
|
->executeQuery()
|
||||||
|
->fetchFirstColumn();
|
||||||
|
$levelsUsed = array_intersect($allLevels, $levels);
|
||||||
|
return array_combine($levelsUsed, $levelsUsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace TYPO3\CMS\Belog\EventListener;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Backend\Backend\Event\SystemInformationToolbarCollectorEvent;
|
||||||
|
use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException;
|
||||||
|
use TYPO3\CMS\Backend\Routing\UriBuilder;
|
||||||
|
use TYPO3\CMS\Backend\Toolbar\InformationStatus;
|
||||||
|
use TYPO3\CMS\Core\Attribute\AsEventListener;
|
||||||
|
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
|
||||||
|
use TYPO3\CMS\Core\Database\Connection;
|
||||||
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||||
|
use TYPO3\CMS\Core\Localization\LanguageService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count latest exceptions for the system information menu.
|
||||||
|
*
|
||||||
|
* @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API.
|
||||||
|
*/
|
||||||
|
final readonly class SystemInformationEventListener
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private ConnectionPool $connectionPool,
|
||||||
|
private UriBuilder $uriBuilder
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifies the SystemInformation toolbar to inject a new message
|
||||||
|
* @throws RouteNotFoundException
|
||||||
|
*/
|
||||||
|
#[AsEventListener('belog/show-latest-errors')]
|
||||||
|
public function appendMessage(SystemInformationToolbarCollectorEvent $event): void
|
||||||
|
{
|
||||||
|
// we can't use the extbase repository here as the required TypoScript may not be parsed yet
|
||||||
|
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_log');
|
||||||
|
$count = $queryBuilder->count('error')
|
||||||
|
->from('sys_log')
|
||||||
|
->where(
|
||||||
|
$queryBuilder->expr()->gte(
|
||||||
|
'tstamp',
|
||||||
|
$queryBuilder->createNamedParameter($this->fetchLastAccessTimestamp(), Connection::PARAM_INT)
|
||||||
|
),
|
||||||
|
$queryBuilder->expr()->in(
|
||||||
|
'error',
|
||||||
|
$queryBuilder->createNamedParameter([-1, 1, 2], Connection::PARAM_INT_ARRAY)
|
||||||
|
),
|
||||||
|
$queryBuilder->expr()->eq(
|
||||||
|
'channel',
|
||||||
|
$queryBuilder->createNamedParameter('php', Connection::PARAM_STR)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->executeQuery()
|
||||||
|
->fetchOne();
|
||||||
|
|
||||||
|
if ($count > 0) {
|
||||||
|
$moduleIdentifier = 'system_log';
|
||||||
|
$moduleParams = ['constraint' => ['channel' => 'php']];
|
||||||
|
$text = $this->getLanguageService()->translate(
|
||||||
|
'systemmessage.errorsInPeriod',
|
||||||
|
'belog.messages',
|
||||||
|
[
|
||||||
|
$count,
|
||||||
|
(string)$this->uriBuilder->buildUriFromRoute($moduleIdentifier, $moduleParams),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$systemInformationToolbarItem = $event->getToolbarItem();
|
||||||
|
$systemInformationToolbarItem->addSystemMessage(
|
||||||
|
$text,
|
||||||
|
InformationStatus::ERROR,
|
||||||
|
$count,
|
||||||
|
$moduleIdentifier,
|
||||||
|
http_build_query($moduleParams)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function fetchLastAccessTimestamp(): int
|
||||||
|
{
|
||||||
|
if (!isset($this->getBackendUser()->uc['systeminformation'])) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
$systemInformationUc = json_decode($this->getBackendUser()->uc['systeminformation'], true, 512, JSON_THROW_ON_ERROR);
|
||||||
|
return (int)($systemInformationUc['system_log']['lastAccess'] ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getLanguageService(): LanguageService
|
||||||
|
{
|
||||||
|
return $GLOBALS['LANG'];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getBackendUser(): BackendUserAuthentication
|
||||||
|
{
|
||||||
|
return $GLOBALS['BE_USER'];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace TYPO3\CMS\Belog\ViewHelpers;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Belog\Domain\Model\LogEntry;
|
||||||
|
use TYPO3\CMS\Core\Log\LogDataTrait;
|
||||||
|
use TYPO3\CMS\Core\Utility\PathUtility;
|
||||||
|
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ViewHelper to create detail string from a log entry.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <belog:formatDetails logEntry="{logItem}" />
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class FormatDetailsViewHelper extends AbstractViewHelper
|
||||||
|
{
|
||||||
|
use LogDataTrait;
|
||||||
|
|
||||||
|
public function initializeArguments(): void
|
||||||
|
{
|
||||||
|
$this->registerArgument('logEntry', LogEntry::class, 'Log entry instance to be rendered', 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
|
||||||
|
*/
|
||||||
|
public function render(): string
|
||||||
|
{
|
||||||
|
/** @var LogEntry $logEntry */
|
||||||
|
$logEntry = $this->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);
|
||||||
|
}
|
||||||
|
return self::formatLogDetailsStatic($detailString, $substitutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strips path from array of file names
|
||||||
|
*/
|
||||||
|
private static function stripPathFromFilenames(array $files = []): array
|
||||||
|
{
|
||||||
|
foreach ($files as $key => $file) {
|
||||||
|
$files[$key] = PathUtility::basename((string)$file);
|
||||||
|
}
|
||||||
|
return $files;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace TYPO3\CMS\Belog\ViewHelpers;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||||
|
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||||
|
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
|
||||||
|
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ViewHelper to get a username from a backend user id.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <belog:username uid="{logItem.backendUserUid}" />
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class UsernameViewHelper extends AbstractViewHelper
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
#[Autowire(service: 'cache.runtime')]
|
||||||
|
private readonly FrontendInterface $usernameRuntimeCache
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function initializeArguments(): void
|
||||||
|
{
|
||||||
|
$this->registerArgument('uid', 'int', 'Uid of the user', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve username from backend user id. Can return empty string if there is no user with that UID.
|
||||||
|
*/
|
||||||
|
public function render(): string
|
||||||
|
{
|
||||||
|
$uid = $this->arguments['uid'];
|
||||||
|
$cacheIdentifier = 'belog-viewhelper-username_' . $uid;
|
||||||
|
if ($this->usernameRuntimeCache->has($cacheIdentifier)) {
|
||||||
|
return $this->usernameRuntimeCache->get($cacheIdentifier);
|
||||||
|
}
|
||||||
|
$username = BackendUtility::getRecord('be_users', $uid)['username'] ?? '';
|
||||||
|
$this->usernameRuntimeCache->set($cacheIdentifier, $username);
|
||||||
|
return $username;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace TYPO3\CMS\Belog\ViewHelpers;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||||
|
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||||
|
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
|
||||||
|
use TYPO3\CMS\Core\Localization\LanguageService;
|
||||||
|
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
|
||||||
|
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ViewHelper to get workspace title from a workspace id.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* belog:workspaceTitle uid="{logItem.workspaceUid}" />
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class WorkspaceTitleViewHelper extends AbstractViewHelper
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
#[Autowire(service: 'cache.runtime')]
|
||||||
|
private readonly FrontendInterface $workspaceTitleRuntimeCache
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function initializeArguments(): void
|
||||||
|
{
|
||||||
|
$this->registerArgument('uid', 'int', 'UID of the workspace', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return resolved workspace title or empty string if it can not be resolved.
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function render(): string
|
||||||
|
{
|
||||||
|
$uid = $this->arguments['uid'];
|
||||||
|
$cacheIdentifier = 'belog-viewhelper-workspace-title_' . $uid;
|
||||||
|
if ($this->workspaceTitleRuntimeCache->has($cacheIdentifier)) {
|
||||||
|
return $this->workspaceTitleRuntimeCache->get($cacheIdentifier);
|
||||||
|
}
|
||||||
|
if ($uid === 0) {
|
||||||
|
$this->workspaceTitleRuntimeCache->set($cacheIdentifier, htmlspecialchars(self::getLanguageService()->sL(
|
||||||
|
'LLL:EXT:belog/Resources/Private/Language/locallang.xlf:live'
|
||||||
|
)));
|
||||||
|
} elseif (!ExtensionManagementUtility::isLoaded('workspaces')) {
|
||||||
|
$this->workspaceTitleRuntimeCache->set($cacheIdentifier, '');
|
||||||
|
} else {
|
||||||
|
$workspace = BackendUtility::getRecord('sys_workspace', $uid);
|
||||||
|
$this->workspaceTitleRuntimeCache->set($cacheIdentifier, $workspace['title'] ?? '');
|
||||||
|
}
|
||||||
|
return $this->workspaceTitleRuntimeCache->get($cacheIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getLanguageService(): LanguageService
|
||||||
|
{
|
||||||
|
return $GLOBALS['LANG'];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use TYPO3\CMS\Belog\Controller\BackendLogController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Definitions for modules provided by EXT:belog
|
||||||
|
*/
|
||||||
|
return [
|
||||||
|
'system_log' => [
|
||||||
|
'parent' => 'admin',
|
||||||
|
'position' => ['after' => 'integrations'],
|
||||||
|
'access' => 'user',
|
||||||
|
'iconIdentifier' => 'module-belog',
|
||||||
|
'labels' => 'belog.module',
|
||||||
|
'path' => '/module/system/log',
|
||||||
|
'aliases' => ['system_BelogLog'],
|
||||||
|
'extensionName' => 'Belog',
|
||||||
|
'controllerActions' => [
|
||||||
|
BackendLogController::class => [
|
||||||
|
'list', 'deleteMessage',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'dependencies' => [
|
||||||
|
'backend',
|
||||||
|
'core',
|
||||||
|
],
|
||||||
|
'imports' => [
|
||||||
|
'@typo3/belog/' => 'EXT:belog/Resources/Public/JavaScript/',
|
||||||
|
],
|
||||||
|
];
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
services:
|
||||||
|
_defaults:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
public: false
|
||||||
|
|
||||||
|
TYPO3\CMS\Belog\:
|
||||||
|
resource: '../Classes/*'
|
||||||
+339
@@ -0,0 +1,339 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
=========================
|
||||||
|
TYPO3 extension ``belog``
|
||||||
|
=========================
|
||||||
|
|
||||||
|
View logs from the sys_log table in the TYPO3 backend modules System>Log and
|
||||||
|
Web>Info>Log.
|
||||||
|
|
||||||
|
The TYPO3 backend module System>Log provides a system wide overview and
|
||||||
|
Web>Info>Log shows logs related to specific pages.
|
||||||
|
|
||||||
|
:Repository: https://github.com/typo3/typo3
|
||||||
|
:Issues: https://forge.typo3.org/
|
||||||
|
:Read online: https://docs.typo3.org/
|
||||||
|
:Packagist: https://packagist.org/packages/typo3/cms-belog
|
||||||
@@ -0,0 +1,359 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||||
|
<file source-language="en" datatype="plaintext" original="EXT:belog/Resources/Private/Language/locallang.xlf" date="2011-10-17T20:22:32Z" product-name="belog">
|
||||||
|
<header/>
|
||||||
|
<body>
|
||||||
|
<trans-unit id="adminLog">
|
||||||
|
<source>Administration log</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="allUsers">
|
||||||
|
<source>[All users]</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="any">
|
||||||
|
<source>[Any]</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="viaUser">
|
||||||
|
<source>via</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="live">
|
||||||
|
<source>LIVE</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="draft">
|
||||||
|
<source>Draft</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="self">
|
||||||
|
<source>Self</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="userGroup">
|
||||||
|
<source>Group</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="set">
|
||||||
|
<source>Filter</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="reset">
|
||||||
|
<source>Reset</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="all">
|
||||||
|
<source>[all]</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="actionAll">
|
||||||
|
<source>All</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="actionDatabase">
|
||||||
|
<source>Database</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="actionFile">
|
||||||
|
<source>File</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="actionCache">
|
||||||
|
<source>Cache</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="actionSettings">
|
||||||
|
<source>Settings</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="actionLogin">
|
||||||
|
<source>Login</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="actionErrors">
|
||||||
|
<source>Errors</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="group">
|
||||||
|
<source>Group</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="user">
|
||||||
|
<source>User</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="users">
|
||||||
|
<source>Users</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="time">
|
||||||
|
<source>Time</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="max">
|
||||||
|
<source>Max</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="showHistory">
|
||||||
|
<source>Show History</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action">
|
||||||
|
<source>Action</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="channel">
|
||||||
|
<source>Channel</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="levels">
|
||||||
|
<source>Levels</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="workspace">
|
||||||
|
<source>Workspace</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="overview">
|
||||||
|
<source>Overview</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="type_1">
|
||||||
|
<source>DB</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_1_1">
|
||||||
|
<source>Insert</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_1_2">
|
||||||
|
<source>Update</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_1_3">
|
||||||
|
<source>Delete</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_1_4">
|
||||||
|
<source>Move</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_1_5">
|
||||||
|
<source>Check</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_0_1">
|
||||||
|
<source>Referer host '%s' and server host '%s' did not match!</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_1_11">
|
||||||
|
<source>Attempt to insert record on page '%s' (%s) where this table, %s, is not allowed</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_1_12">
|
||||||
|
<source>Attempt to insert a record on page '%s' (%s) from table '%s' without permissions. Or non-existing page.</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_2_1">
|
||||||
|
<source>Attempt to modify table '%s' without permission</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_2_2">
|
||||||
|
<source>Attempt to modify record '%s' (%s) without permission. Or non-existing page.</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_2_10">
|
||||||
|
<source>Record '%s' (%s) was updated.</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_2_12">
|
||||||
|
<source>MySQL error: '%s' (%s)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_4_1">
|
||||||
|
<source>Attempt to move record '%s' (%s) to after a non-existing record (uid=%s)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_4_2">
|
||||||
|
<source>Moved record '%s' (%s) to page '%s' (%s)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_4_3">
|
||||||
|
<source>Moved record '%s' (%s) from page '%s' (%s)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_4_4">
|
||||||
|
<source>Moved record '%s' (%s) on page '%s' (%s)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_4_10">
|
||||||
|
<source>Attempt to move page '%s' (%s) to inside of its own rootline (at page '%s' (%s))</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_4_11">
|
||||||
|
<source>Attempt to insert record on page '%s' (%s) where this table, %s, is not allowed</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_4_12">
|
||||||
|
<source>Attempt to insert a record on page '%s' (%s) from table '%s' without permissions. Or non-existing page.</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_4_13">
|
||||||
|
<source>Attempt to move record '%s' (%s) to after another record, although the table has no sorting row.</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_4_14">
|
||||||
|
<source>Attempt to move record '%s' (%s) without having permissions to do so</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_5_1">
|
||||||
|
<source>You cannot change the 'doktype' of page '%s' to the desired value.</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_5_2">
|
||||||
|
<source>'doktype' of page '%s' could not be changed because the page contains records from disallowed tables; %s</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_5_3">
|
||||||
|
<source>Too few items in the list of values. (%s)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_5_10">
|
||||||
|
<source>Could not delete file '%s' (does not exist). (%s)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_5_11">
|
||||||
|
<source>Copying file '%s' failed!: No destination file (%s) possible!. (%s)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_5_12">
|
||||||
|
<source>File extension '%s' is not allowed. (%s)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_5_13">
|
||||||
|
<source>File size (%s) of file '%s' exceeds limit (%s). (%s)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_5_14">
|
||||||
|
<source>The destination (%s) or the source file (%s) does not exist. (%s)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_5_15">
|
||||||
|
<source>Copying to file '%s' failed! (%s)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_5_16">
|
||||||
|
<source>Copying file '%s' failed!: The destination path (%s) may be write protected. Please make it write enabled!. (%s)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_1_5_4">
|
||||||
|
<source>The value of the field "%s" has been changed from "%s" to "%s" as it is required to be unique.</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="type_2">
|
||||||
|
<source>FILE</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_2_1">
|
||||||
|
<source>Upload</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_2_2">
|
||||||
|
<source>Copy</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_2_3">
|
||||||
|
<source>Move</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_2_4">
|
||||||
|
<source>Delete</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_2_5">
|
||||||
|
<source>Rename</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_2_6">
|
||||||
|
<source>New</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_2_7">
|
||||||
|
<source>Unzip</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_2_8">
|
||||||
|
<source>New file</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_2_9">
|
||||||
|
<source>Edit</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="msg_2_9_1">
|
||||||
|
<source>File saved to '%s', bytes: %s, MD5: %s </source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="type_3">
|
||||||
|
<source>CACHE</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_3_1">
|
||||||
|
<source>Clear Cache</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="type_4">
|
||||||
|
<source>EXTENSION</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="type_5">
|
||||||
|
<source>ERROR</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_5_0">
|
||||||
|
<source>Error handler</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="type_254">
|
||||||
|
<source>SETTING</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_254_1">
|
||||||
|
<source>Change</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="type_255">
|
||||||
|
<source>LOGIN</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_255_1">
|
||||||
|
<source>LOGIN</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_255_2">
|
||||||
|
<source>LOGOUT</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="action_255_3">
|
||||||
|
<source>ATTEMPT</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_title">
|
||||||
|
<source>Admin Changelog</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_users_0">
|
||||||
|
<source>All users</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_users_-1">
|
||||||
|
<source>Self</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_time_0">
|
||||||
|
<source>This week</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_time_1">
|
||||||
|
<source>Last week</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_time_2">
|
||||||
|
<source>Last 7 days</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_time_10">
|
||||||
|
<source>This month</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_time_11">
|
||||||
|
<source>Last month</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_time_12">
|
||||||
|
<source>Last 31 days</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_time_20">
|
||||||
|
<source>No limit</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_l_time">
|
||||||
|
<source>Time</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_l_user">
|
||||||
|
<source>User</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_l_action">
|
||||||
|
<source>Action</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_l_channel">
|
||||||
|
<source>Channel</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_l_types">
|
||||||
|
<source>Type</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_l_level">
|
||||||
|
<source>Level</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_l_table">
|
||||||
|
<source>Table</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_l_details">
|
||||||
|
<source>Details</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_menuUsers">
|
||||||
|
<source>Users</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_menuPageId">
|
||||||
|
<source>Page</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_menuDepth">
|
||||||
|
<source>Depth</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="chLog_menuTime">
|
||||||
|
<source>Time</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="systemmessage.errorsInPeriod">
|
||||||
|
<source><![CDATA[We have found %1$d error(s). Please check your <a href="%2$s">system log</a>.]]></source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="actions">
|
||||||
|
<source>Actions</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="actions.delete">
|
||||||
|
<source>Delete similar errors</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="actions.deleteWarnings">
|
||||||
|
<source>Delete similar warnings</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="actions.delete.message">
|
||||||
|
<source>Total entries deleted: %1$d</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="actions.delete.noRowFound">
|
||||||
|
<source>Log entry could not be found.</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="info.noRecords.message">
|
||||||
|
<source>No records found.</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="info.selectPage.title">
|
||||||
|
<source>No page selected</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="info.selectPage.message">
|
||||||
|
<source>Select a page to display logs for.</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="error.noAccess.title">
|
||||||
|
<source>No access!</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="error.noAccess.message">
|
||||||
|
<source>You don't have access to the selected page.</source>
|
||||||
|
</trans-unit>
|
||||||
|
</body>
|
||||||
|
</file>
|
||||||
|
</xliff>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||||
|
<file source-language="en" datatype="plaintext" original="EXT:belog/Resources/Private/Language/module.xlf" date="2025-11-10T13:37:37Z" product-name="belog">
|
||||||
|
<header/>
|
||||||
|
<body>
|
||||||
|
<trans-unit id="title">
|
||||||
|
<source>Log</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="short_description">
|
||||||
|
<source>Viewing log</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="description">
|
||||||
|
<source>Allows you access to the full backend changelog in TYPO3.</source>
|
||||||
|
</trans-unit>
|
||||||
|
</body>
|
||||||
|
</file>
|
||||||
|
</xliff>
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
<html
|
||||||
|
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||||
|
xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers"
|
||||||
|
xmlns:belog="http://typo3.org/ns/TYPO3/CMS/Belog/ViewHelpers"
|
||||||
|
data-namespace-typo3-fluid="true">
|
||||||
|
|
||||||
|
<f:form object="{constraint}" action="list" name="constraint">
|
||||||
|
<f:variable name="dateFormat" value="{f:constant(name: '\TYPO3\CMS\Core\Domain\DateTimeFormat::ISO8601_LOCALTIME')}" />
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="belog-users" class="form-label"><f:translate key="users" /></label>
|
||||||
|
<f:form.select
|
||||||
|
property="userOrGroup"
|
||||||
|
class="form-select"
|
||||||
|
id="belog-users"
|
||||||
|
>
|
||||||
|
<f:form.select.option value="0">{f:translate(key:'allUsers')}</f:form.select.option>
|
||||||
|
<f:form.select.option value="-1">{f:translate(key:'self')}</f:form.select.option>
|
||||||
|
<f:form.select.optgroup label="{f:translate(key:'group')}">
|
||||||
|
<f:for each="{userGroups.groups}" as="label" key="key">
|
||||||
|
<f:form.select.option value="{key}">{label}</f:form.select.option>
|
||||||
|
</f:for>
|
||||||
|
</f:form.select.optgroup>
|
||||||
|
<f:form.select.optgroup label="{f:translate(key:'user')}">
|
||||||
|
<f:for each="{userGroups.users}" as="label" key="key">
|
||||||
|
<f:form.select.option value="{key}">{label}</f:form.select.option>
|
||||||
|
</f:for>
|
||||||
|
</f:form.select.optgroup>
|
||||||
|
</f:form.select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="belog-max" class="form-label"><f:translate key="max" /></label>
|
||||||
|
<f:form.select
|
||||||
|
property="number"
|
||||||
|
options="{selectableNumberOfLogEntries}"
|
||||||
|
class="form-select"
|
||||||
|
id="belog-max"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<f:if condition="{showWorkspaceSelector}">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="belog-workspaces" class="form-label"><f:translate key="workspace" /></label>
|
||||||
|
<f:form.select
|
||||||
|
property="workspaceUid"
|
||||||
|
options="{workspaces}"
|
||||||
|
class="form-select"
|
||||||
|
id="belog-workspaces"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</f:if>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="belog-pageId" class="form-label"><f:translate key="chLog_menuPageId" /></label>
|
||||||
|
<div class="input-group">
|
||||||
|
<f:form.textfield
|
||||||
|
type="number"
|
||||||
|
property="pageId"
|
||||||
|
value="{pageId}"
|
||||||
|
id="belog-pageId"
|
||||||
|
class="form-control"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
class="btn btn-default t3js-element-browser"
|
||||||
|
data-target="{f:be.uri(route: 'wizard_element_browser')}"
|
||||||
|
data-trigger-for="belog-pageId"
|
||||||
|
data-mode="db"
|
||||||
|
title="{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.browse_db')}"
|
||||||
|
>
|
||||||
|
<core:icon identifier="actions-insert-record" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<f:if condition="{pageId}">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="belog-depth" class="form-label"><f:translate key="chLog_menuDepth" /></label>
|
||||||
|
<f:form.select
|
||||||
|
property="depth"
|
||||||
|
options="{pageDepths}"
|
||||||
|
class="form-select"
|
||||||
|
id="belog-depth"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</f:if>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="belog-channel" class="form-label"><f:translate key="channel" /></label>
|
||||||
|
<f:form.select
|
||||||
|
property="channel"
|
||||||
|
options="{channels}"
|
||||||
|
prependOptionLabel="{f:translate(key='all')}"
|
||||||
|
prependOptionValue=""
|
||||||
|
class="form-select"
|
||||||
|
id="belog-channel"
|
||||||
|
value="{channel}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="belog-level" class="form-label"><f:translate key="levels" /></label>
|
||||||
|
<f:form.select
|
||||||
|
property="level"
|
||||||
|
options="{levels}"
|
||||||
|
prependOptionLabel="{f:translate(key='all')}"
|
||||||
|
prependOptionValue=""
|
||||||
|
class="form-select"
|
||||||
|
id="belog-level"
|
||||||
|
value="{level}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="manualDateStart" class="form-label"><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:from" /></label>
|
||||||
|
<div class="input-group">
|
||||||
|
<f:form.textfield
|
||||||
|
property="manualDateStart"
|
||||||
|
value="{f:if(condition: constraint.manualDateStart, then: \"{f:format.date(format: dateFormat, date: '{constraint.manualDateStart}')}\")}"
|
||||||
|
id="manualDateStart"
|
||||||
|
additionalAttributes="{'autocomplete': 'off'}"
|
||||||
|
class="form-control form-control-clearable t3js-datetimepicker"
|
||||||
|
data="{date-type: 'datetime'}"
|
||||||
|
/>
|
||||||
|
<label class="btn btn-default" for="manualDateStart">
|
||||||
|
<core:icon identifier="actions-calendar" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="manualDateStop" class="form-label"><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:to" /></label>
|
||||||
|
<div class="input-group">
|
||||||
|
<f:form.textfield
|
||||||
|
property="manualDateStop"
|
||||||
|
value="{f:format.date(format: dateFormat, date: '{constraint.manualDateStop}')}"
|
||||||
|
additionalAttributes="{'autocomplete': 'off'}"
|
||||||
|
id="manualDateStop"
|
||||||
|
class="form-control form-control-clearable t3js-datetimepicker"
|
||||||
|
data="{date-type: 'datetime'}"
|
||||||
|
/>
|
||||||
|
<label class="btn btn-default" for="manualDateStop">
|
||||||
|
<core:icon identifier="actions-calendar" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group align-self-end">
|
||||||
|
<f:form.button type="submit" name="operation" value="filter" class="btn btn-default">{f:translate(key: 'set')}</f:form.button>
|
||||||
|
<f:form.button type="submit" name="operation" value="reset-filters" class="btn btn-link">{f:translate(key: 'reset')}</f:form.button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</f:form>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
<html
|
||||||
|
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||||
|
xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers"
|
||||||
|
xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers"
|
||||||
|
xmlns:belog="http://typo3.org/ns/TYPO3/CMS/Belog/ViewHelpers"
|
||||||
|
data-namespace-typo3-fluid="true">
|
||||||
|
|
||||||
|
<f:if condition="{groupedLogEntries -> f:count()} > 0">
|
||||||
|
<f:then>
|
||||||
|
<f:for each="{groupedLogEntries}" as="pidEntry" key="pid">
|
||||||
|
<f:for each="{pidEntry}" as="day" key="dayTimestamp">
|
||||||
|
<h3>
|
||||||
|
<f:format.date format="{settings.dateFormat}">@{dayTimestamp}</f:format.date>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div class="table-fit">
|
||||||
|
<table class="table table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th><f:translate key="chLog_l_time"/></th>
|
||||||
|
<th colspan="2"><f:translate key="chLog_l_user"/></th>
|
||||||
|
<th>
|
||||||
|
<f:if condition="{pageId}">
|
||||||
|
<f:then>
|
||||||
|
<f:translate key="chLog_l_table"/>
|
||||||
|
</f:then>
|
||||||
|
<f:else>
|
||||||
|
<f:translate key="chLog_l_level"/>
|
||||||
|
</f:else>
|
||||||
|
</f:if>
|
||||||
|
</th>
|
||||||
|
<th><f:translate key="chLog_l_channel"/></th>
|
||||||
|
<th><f:translate key="chLog_l_details"/></th>
|
||||||
|
<th class="col-control"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<f:for each="{day}" as="logItem">
|
||||||
|
<tr>
|
||||||
|
<td class="col-icon">
|
||||||
|
<f:if condition="{logItem.errorIconClass}">
|
||||||
|
<core:icon identifier="{logItem.errorIconClass}" />
|
||||||
|
</f:if>
|
||||||
|
</td>
|
||||||
|
<td class="col-time">
|
||||||
|
<f:format.date format="H:i:s">{logItem.tstamp}</f:format.date>
|
||||||
|
</td>
|
||||||
|
<td class="col-avatar">
|
||||||
|
<f:if condition="{belog:username(uid:logItem.backendUserUid)}">
|
||||||
|
<be:avatar backendUser="{logItem.backendUserUid}" showIcon="true"/>
|
||||||
|
</f:if>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<f:if condition="{belog:username(uid:logItem.backendUserUid)}">
|
||||||
|
<f:then>
|
||||||
|
<belog:username uid="{logItem.backendUserUid}"/>
|
||||||
|
</f:then>
|
||||||
|
<f:else>[{logItem.backendUserUid}]</f:else>
|
||||||
|
</f:if>
|
||||||
|
<f:if condition="{logItem.logData.originalUser}">
|
||||||
|
({f:translate(key:'viaUser')}
|
||||||
|
<f:if condition="{belog:username(uid:logItem.logData.originalUser)}">
|
||||||
|
<f:then>
|
||||||
|
<belog:username uid="{logItem.logData.originalUser}"/>
|
||||||
|
</f:then>
|
||||||
|
<f:else>[{logItem.logData.originalUser}]</f:else>
|
||||||
|
</f:if>
|
||||||
|
)
|
||||||
|
</f:if>
|
||||||
|
<f:if condition="{workspaces}">
|
||||||
|
<br>
|
||||||
|
<span class="text-variant">
|
||||||
|
<f:if condition="{belog:workspaceTitle(uid:logItem.workspaceUid)}">
|
||||||
|
<f:then><belog:workspaceTitle uid="{logItem.workspaceUid}"/></f:then>
|
||||||
|
<f:else>[{logItem.workspaceUid}]</f:else>
|
||||||
|
</f:if>
|
||||||
|
</span>
|
||||||
|
</f:if>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<f:if condition="{pageId}">
|
||||||
|
<f:then>
|
||||||
|
{logItem.tableName}
|
||||||
|
</f:then>
|
||||||
|
<f:else>
|
||||||
|
{logItem.level}
|
||||||
|
</f:else>
|
||||||
|
</f:if>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{logItem.channel}
|
||||||
|
</td>
|
||||||
|
<td class="col-word-break" lang="en">
|
||||||
|
<belog:formatDetails logEntry="{logItem}"/>
|
||||||
|
</td>
|
||||||
|
<td class="col-control">
|
||||||
|
<f:if condition="{logItem.error} == 1">
|
||||||
|
<f:form.button class="btn btn-sm btn-warning" form="form-delete-message" type="submit" name="errorUid" value="{logItem.uid}">
|
||||||
|
<core:icon identifier="actions-delete" size="small"/>
|
||||||
|
<f:translate key="actions.deleteWarnings"/>
|
||||||
|
</f:form.button>
|
||||||
|
</f:if>
|
||||||
|
<f:if condition="{logItem.error} == 2">
|
||||||
|
<f:form.button class="btn btn-sm btn-danger" form="form-delete-message" type="submit" name="errorUid" value="{logItem.uid}">
|
||||||
|
<core:icon identifier="actions-delete" size="small"/>
|
||||||
|
<f:translate key="actions.delete"/>
|
||||||
|
</f:form.button>
|
||||||
|
</f:if>
|
||||||
|
<f:if condition="{logItem.logData.history}">
|
||||||
|
<a class="btn btn-sm btn-default" href="{be:moduleLink(route: 'record_history', arguments: '{historyEntry: logItem.logData.history}')}" title="{f:translate(key: 'showHistory')}">
|
||||||
|
<core:icon identifier="actions-document-history-open" />
|
||||||
|
<f:translate id="showHistory" />
|
||||||
|
</a>
|
||||||
|
</f:if>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</f:for>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</f:for>
|
||||||
|
</f:for>
|
||||||
|
|
||||||
|
<f:form action="deleteMessage" id="form-delete-message" method="post" class="hidden"/>
|
||||||
|
</f:then>
|
||||||
|
<f:else>
|
||||||
|
<f:be.infobox
|
||||||
|
message="{f:translate(key: 'LLL:EXT:belog/Resources/Private/Language/locallang.xlf:info.noRecords.message')}"
|
||||||
|
state="{f:constant(name: 'TYPO3\CMS\Core\Type\ContextualFeedbackSeverity::NOTICE')}"
|
||||||
|
/>
|
||||||
|
</f:else>
|
||||||
|
</f:if>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<html
|
||||||
|
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||||
|
data-namespace-typo3-fluid="true">
|
||||||
|
|
||||||
|
<f:layout name="Module"/>
|
||||||
|
<f:section name="Content">
|
||||||
|
|
||||||
|
<f:asset.module identifier="@typo3/backend/global-event-handler.js"/>
|
||||||
|
<f:asset.module identifier="@typo3/belog/backend-log.js"/>
|
||||||
|
|
||||||
|
<h1>
|
||||||
|
<f:translate key="adminLog" />
|
||||||
|
</h1>
|
||||||
|
<f:render partial="Content/Filter" arguments="{_all}" />
|
||||||
|
|
||||||
|
<f:if condition="{access}">
|
||||||
|
<f:then>
|
||||||
|
<f:render partial="Content/LogEntries" arguments="{_all}" />
|
||||||
|
</f:then>
|
||||||
|
<f:else if="!{pageId}">
|
||||||
|
<f:be.infobox state="{f:constant(name: 'TYPO3\CMS\Core\Type\ContextualFeedbackSeverity::INFO')}" title="{f:translate(key: 'LLL:EXT:belog/Resources/Private/Language/locallang.xlf:info.selectPage.title')}">
|
||||||
|
<p><f:translate key="LLL:EXT:belog/Resources/Private/Language/locallang.xlf:info.selectPage.message" /></p>
|
||||||
|
</f:be.infobox>
|
||||||
|
</f:else>
|
||||||
|
<f:else>
|
||||||
|
<f:be.infobox state="{f:constant(name: 'TYPO3\CMS\Core\Type\ContextualFeedbackSeverity::ERROR')}" title="{f:translate(key: 'LLL:EXT:belog/Resources/Private/Language/locallang.xlf:error.noAccess.title')}">
|
||||||
|
<p><f:translate key="LLL:EXT:belog/Resources/Private/Language/locallang.xlf:error.noAccess.message" /></p>
|
||||||
|
</f:be.infobox>
|
||||||
|
</f:else>
|
||||||
|
</f:if>
|
||||||
|
|
||||||
|
</f:section>
|
||||||
|
|
||||||
|
</html>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 360 B |
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* 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!
|
||||||
|
*/
|
||||||
|
import a from"@typo3/backend/modal.js";import n from"@typo3/core/document-service.js";import s from"@typo3/backend/date-time-picker.js";import"@typo3/backend/input/clearable.js";import{MessageUtility as m}from"@typo3/backend/utility/message-utility.js";class o{constructor(){this.clearableElements=null,this.dateTimePickerElements=null,this.elementBrowserElements=null,n.ready().then(()=>{this.clearableElements=document.querySelectorAll(".t3js-clearable"),this.dateTimePickerElements=document.querySelectorAll(".t3js-datetimepicker"),this.elementBrowserElements=document.querySelectorAll(".t3js-element-browser"),this.initializeClearableElements(),this.initializeDateTimePickerElements(),this.initializeElementBrowserElements(),this.initializeElementBrowserEventListener()})}initializeClearableElements(){this.clearableElements.forEach(e=>e.clearable())}initializeDateTimePickerElements(){this.dateTimePickerElements.forEach(e=>s.initialize(e))}initializeElementBrowserElements(){this.elementBrowserElements.forEach(e=>{const t=document.getElementById(e.dataset.triggerFor);e.dataset.fieldReference=t.name,e.dataset.allowedTypes="pages",e.addEventListener("click",r=>{r.preventDefault();const i=r.currentTarget,l=new URLSearchParams({mode:i.dataset.mode,fieldReference:i.dataset.fieldReference,allowedTypes:i.dataset.allowedTypes});a.advanced({type:a.types.iframe,content:i.dataset.target+"&"+l.toString(),size:a.sizes.large})})})}initializeElementBrowserEventListener(){window.addEventListener("message",e=>{if(!m.verifyOrigin(e.origin)||e.data.actionName!=="typo3:elementBrowser:elementAdded"||typeof e.data.fieldName!="string"||typeof e.data.value!="string")return;const t=document.querySelector('input[name="'+e.data.fieldName+'"]');t&&(t.value=e.data.value.split("_").pop())})}}var d=new o;export{d as default};
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"name": "typo3/cms-belog",
|
||||||
|
"type": "typo3-cms-framework",
|
||||||
|
"description": "TYPO3 CMS Log - View logs from the sys_log table in the TYPO3 backend modules System>Log",
|
||||||
|
"homepage": "https://typo3.community/",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "membership",
|
||||||
|
"url": "https://typo3.org/membership"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": [
|
||||||
|
"GPL-2.0-or-later"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "TYPO3 Core Team",
|
||||||
|
"email": "typo3cms@typo3.org",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://forge.typo3.org/issues/",
|
||||||
|
"forum": "https://talk.typo3.org/",
|
||||||
|
"source": "https://github.com/TYPO3/typo3/",
|
||||||
|
"docs": "https://docs.typo3.org/",
|
||||||
|
"rss": "https://news.typo3.com/rss/",
|
||||||
|
"chat": "https://typo3.community/meet/slack/",
|
||||||
|
"security": "https://typo3.org/security/"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"sort-packages": true
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"typo3/cms-core": "15.0.*@dev"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"typo3/cms": "*"
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "15.0.x-dev"
|
||||||
|
},
|
||||||
|
"typo3/cms": {
|
||||||
|
"Package": {
|
||||||
|
"partOfFactoryDefault": true
|
||||||
|
},
|
||||||
|
"extension-key": "belog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"TYPO3\\CMS\\Belog\\": "Classes/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user