1<?php
2
3declare(strict_types=1);
4
5/*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18namespace TYPO3\CMS\SysNote\Hook;
19
20use Psr\Http\Message\ServerRequestInterface;
21use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException;
22use TYPO3\CMS\Backend\Routing\UriBuilder;
23use TYPO3\CMS\Backend\Template\Components\ButtonBar;
24use TYPO3\CMS\Backend\Utility\BackendUtility;
25use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
26use TYPO3\CMS\Core\Imaging\Icon;
27use TYPO3\CMS\Core\Imaging\IconFactory;
28use TYPO3\CMS\Core\Localization\LanguageService;
29use TYPO3\CMS\Core\Type\Bitmask\Permission;
30use TYPO3\CMS\Core\Utility\GeneralUtility;
31
32/**
33 * Hook for the button bar
34 *
35 * @internal This is a specific hook implementation and is not considered part of the Public TYPO3 API.
36 */
37class ButtonBarHook
38{
39    private const TABLE_NAME = 'sys_note';
40    private const ALLOWED_MODULES = ['web_layout', 'web_list', 'web_info'];
41
42    /**
43     * Add a sys_note creation button to the button bar of defined modules
44     *
45     * @param array $params
46     * @param ButtonBar $buttonBar
47     *
48     * @return array
49     * @throws RouteNotFoundException
50     */
51    public function getButtons(array $params, ButtonBar $buttonBar): array
52    {
53        $buttons = $params['buttons'];
54        $request = $this->getRequest();
55
56        $id = (int)($request->getParsedBody()['id'] ?? $request->getQueryParams()['id'] ?? 0);
57        $route = $request->getAttribute('route');
58        $normalizedParams = $request->getAttribute('normalizedParams');
59        $pageTSconfig = BackendUtility::getPagesTSconfig($id);
60
61        if (!$id
62            || $route === null
63            || $normalizedParams === null
64            || !empty($pageTSconfig['mod.']['SHARED.']['disableSysNoteButton'])
65            || !$this->canCreateNewRecord($id)
66            || !in_array($route->getOption('moduleName'), self::ALLOWED_MODULES, true)
67            || ($route->getOption('moduleName') === 'web_list' && !$this->isCreationAllowed($pageTSconfig['mod.']['web_list.'] ?? []))
68        ) {
69            return $buttons;
70        }
71
72        $uri = (string)GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute(
73            'record_edit',
74            [
75                'edit' => [
76                    self::TABLE_NAME => [
77                        $id => 'new',
78                    ],
79                ],
80                'returnUrl' => $normalizedParams->getRequestUri(),
81            ]
82        );
83
84        $buttons[ButtonBar::BUTTON_POSITION_RIGHT][2][] = $buttonBar
85            ->makeLinkButton()
86            ->setTitle(htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:sys_note/Resources/Private/Language/locallang.xlf:new_internal_note')))
87            ->setIcon(GeneralUtility::makeInstance(IconFactory::class)->getIcon('sysnote-type-0', Icon::SIZE_SMALL))
88            ->setHref($uri);
89
90        ksort($buttons[ButtonBar::BUTTON_POSITION_RIGHT]);
91
92        return $buttons;
93    }
94
95    /**
96     * Check if the user is allowed to create a sys_note record
97     *
98     * @param int $id
99     * @return bool
100     */
101    protected function canCreateNewRecord(int $id): bool
102    {
103        $tableConfiguration = $GLOBALS['TCA'][self::TABLE_NAME]['ctrl'];
104        $pageRow = BackendUtility::getRecord('pages', $id);
105        $backendUser = $this->getBackendUserAuthentication();
106
107        return !($pageRow === null
108            || ($tableConfiguration['readOnly'] ?? false)
109            || ($tableConfiguration['hideTable'] ?? false)
110            || ($tableConfiguration['is_static'] ?? false)
111            || (($tableConfiguration['adminOnly'] ?? false) && !$backendUser->isAdmin())
112            || !$backendUser->doesUserHaveAccess($pageRow, Permission::CONTENT_EDIT)
113            || !$backendUser->check('tables_modify', self::TABLE_NAME)
114            || !$backendUser->workspaceCanCreateNewRecord(self::TABLE_NAME));
115    }
116
117    /**
118     * Check if creation is allowed / denied in web_list via mod TSconfig
119     *
120     * @param array $modTSconfig
121     * @return bool
122     */
123    protected function isCreationAllowed(array $modTSconfig): bool
124    {
125        $allowedNewTables = GeneralUtility::trimExplode(',', $modTSconfig['allowedNewTables'] ?? '', true);
126        $deniedNewTables = GeneralUtility::trimExplode(',', $modTSconfig['deniedNewTables'] ?? '', true);
127
128        return ($allowedNewTables === [] && $deniedNewTables === [])
129            || (!in_array(self::TABLE_NAME, $deniedNewTables)
130                && ($allowedNewTables === [] || in_array(self::TABLE_NAME, $allowedNewTables)));
131    }
132
133    protected function getRequest(): ServerRequestInterface
134    {
135        return $GLOBALS['TYPO3_REQUEST'];
136    }
137
138    protected function getBackendUserAuthentication(): BackendUserAuthentication
139    {
140        return $GLOBALS['BE_USER'];
141    }
142
143    protected function getLanguageService(): LanguageService
144    {
145        return $GLOBALS['LANG'];
146    }
147}
148