1<?php
2declare(strict_types = 1);
3namespace TYPO3\CMS\Redirects\Controller;
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
18use Psr\Http\Message\ResponseInterface;
19use Psr\Http\Message\ServerRequestInterface;
20use TYPO3\CMS\Backend\Routing\UriBuilder;
21use TYPO3\CMS\Backend\Template\Components\ButtonBar;
22use TYPO3\CMS\Backend\Template\ModuleTemplate;
23use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
24use TYPO3\CMS\Core\Configuration\Features;
25use TYPO3\CMS\Core\Http\HtmlResponse;
26use TYPO3\CMS\Core\Imaging\Icon;
27use TYPO3\CMS\Core\Imaging\IconFactory;
28use TYPO3\CMS\Core\Localization\LanguageService;
29use TYPO3\CMS\Core\Utility\GeneralUtility;
30use TYPO3\CMS\Fluid\View\StandaloneView;
31use TYPO3\CMS\Redirects\Repository\Demand;
32use TYPO3\CMS\Redirects\Repository\RedirectRepository;
33use TYPO3\CMS\Redirects\Service\UrlService;
34use TYPO3Fluid\Fluid\View\ViewInterface;
35
36/**
37 * Lists all redirects in the TYPO3 Backend as a module
38 * @internal This class is a specific TYPO3 Backend controller implementation and is not part of the Public TYPO3 API.
39 */
40class ManagementController
41{
42    /**
43     * ModuleTemplate object
44     *
45     * @var ModuleTemplate
46     */
47    protected $moduleTemplate;
48
49    /**
50     * @var ViewInterface
51     */
52    protected $view;
53
54    /**
55     * @var ServerRequestInterface
56     */
57    protected $request;
58
59    /**
60     * @var IconFactory
61     */
62    protected $iconFactory;
63
64    /**
65     * Instantiate the form protection before a simulated user is initialized.
66     */
67    public function __construct()
68    {
69        $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
70        $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Modal');
71        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
72        $this->getLanguageService()->includeLLFile('EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf');
73    }
74
75    /**
76     * Injects the request object for the current request, and renders the overview of all redirects
77     *
78     * @param ServerRequestInterface $request the current request
79     * @return ResponseInterface the response with the content
80     */
81    public function handleRequest(ServerRequestInterface $request): ResponseInterface
82    {
83        $this->request = $request;
84        $this->initializeView('overview');
85
86        $this->overviewAction($request);
87        $this->moduleTemplate->setContent($this->view->render());
88        return new HtmlResponse($this->moduleTemplate->renderContent());
89    }
90
91    /**
92     * Show all redirects, and add a button to create a new redirect
93     * @param ServerRequestInterface $request
94     */
95    protected function overviewAction(ServerRequestInterface $request)
96    {
97        $this->getButtons();
98        $demand = Demand::createFromRequest($request);
99        $redirectRepository = GeneralUtility::makeInstance(RedirectRepository::class, $demand);
100        $count = $redirectRepository->countRedirectsByByDemand();
101
102        $this->view->assignMultiple([
103            'redirects' => $redirectRepository->findRedirectsByDemand(),
104            'hosts' => $redirectRepository->findHostsOfRedirects(),
105            'statusCodes' => $redirectRepository->findStatusCodesOfRedirects(),
106            'demand' => $demand,
107            'defaultUrl' => GeneralUtility::makeInstance(UrlService::class)->getDefaultUrl(),
108            'showHitCounter' => GeneralUtility::makeInstance(Features::class)->isFeatureEnabled('redirects.hitCount'),
109            'pagination' => $this->preparePagination($demand, $count),
110        ]);
111    }
112
113    /**
114     * Prepares information for the pagination of the module
115     *
116     * @param Demand $demand
117     * @param int $count
118     * @return array
119     */
120    protected function preparePagination(Demand $demand, int $count): array
121    {
122        $numberOfPages = ceil($count / $demand->getLimit());
123        $endRecord = $demand->getOffset() + $demand->getLimit();
124        if ($endRecord > $count) {
125            $endRecord = $count;
126        }
127
128        $pagination = [
129            'current' => $demand->getPage(),
130            'numberOfPages' => $numberOfPages,
131            'hasLessPages' => $demand->getPage() > 1,
132            'hasMorePages' => $demand->getPage() < $numberOfPages,
133            'startRecord' => $demand->getOffset() + 1,
134            'endRecord' => $endRecord
135        ];
136        if ($pagination['current'] < $pagination['numberOfPages']) {
137            $pagination['nextPage'] = $pagination['current'] + 1;
138        }
139        if ($pagination['current'] > 1) {
140            $pagination['previousPage'] = $pagination['current'] - 1;
141        }
142        return $pagination;
143    }
144
145    /**
146     * @param string $templateName
147     */
148    protected function initializeView(string $templateName)
149    {
150        $this->view = GeneralUtility::makeInstance(StandaloneView::class);
151        $this->view->setTemplate($templateName);
152        $this->view->setTemplateRootPaths(['EXT:redirects/Resources/Private/Templates/Management']);
153        $this->view->setPartialRootPaths(['EXT:redirects/Resources/Private/Partials']);
154        $this->view->setLayoutRootPaths(['EXT:redirects/Resources/Private/Layouts']);
155    }
156
157    /**
158     * Create document header buttons
159     */
160    protected function getButtons()
161    {
162        /** @var UriBuilder $uriBuilder */
163        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
164
165        $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
166
167        // Create new
168        $newRecordButton = $buttonBar->makeLinkButton()
169            ->setHref((string)$uriBuilder->buildUriFromRoute(
170                'record_edit',
171                [
172                    'edit' => ['sys_redirect' => ['new'],
173                ],
174                'returnUrl' => (string)$uriBuilder->buildUriFromRoute('site_redirects'),
175            ]
176            ))
177            ->setTitle($this->getLanguageService()->getLL('redirect_add_text'))
178            ->setIcon($this->iconFactory->getIcon('actions-add', Icon::SIZE_SMALL));
179        $buttonBar->addButton($newRecordButton, ButtonBar::BUTTON_POSITION_LEFT, 10);
180
181        // Reload
182        $reloadButton = $buttonBar->makeLinkButton()
183            ->setHref(GeneralUtility::getIndpEnv('REQUEST_URI'))
184            ->setTitle($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.reload'))
185            ->setIcon($this->iconFactory->getIcon('actions-refresh', Icon::SIZE_SMALL));
186        $buttonBar->addButton($reloadButton, ButtonBar::BUTTON_POSITION_RIGHT);
187
188        // Shortcut
189        $mayMakeShortcut = $this->getBackendUserAuthentication()->mayMakeShortcut();
190        if ($mayMakeShortcut) {
191            $getVars = ['id', 'route'];
192
193            $shortcutButton = $buttonBar->makeShortcutButton()
194                ->setModuleName('site_redirects')
195                ->setGetVariables($getVars);
196            $buttonBar->addButton($shortcutButton, ButtonBar::BUTTON_POSITION_RIGHT);
197        }
198    }
199
200    /**
201     * @return LanguageService
202     */
203    protected function getLanguageService(): LanguageService
204    {
205        return $GLOBALS['LANG'];
206    }
207
208    /**
209     * @return BackendUserAuthentication
210     */
211    protected function getBackendUserAuthentication(): BackendUserAuthentication
212    {
213        return $GLOBALS['BE_USER'];
214    }
215}
216