[TASK] Use Environment API in documentation extension
[Packages/TYPO3.CMS.git] / typo3 / sysext / documentation / Classes / Controller / DocumentController.php
1 <?php
2 namespace TYPO3\CMS\Documentation\Controller;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Backend\View\BackendTemplateView;
20 use TYPO3\CMS\Core\Core\Environment;
21 use TYPO3\CMS\Core\Http\JsonResponse;
22 use TYPO3\CMS\Core\Localization\LanguageService;
23 use TYPO3\CMS\Core\Messaging\FlashMessage;
24 use TYPO3\CMS\Core\Page\PageRenderer;
25 use TYPO3\CMS\Core\Utility\GeneralUtility;
26 use TYPO3\CMS\Documentation\Domain\Repository\DocumentRepository;
27 use TYPO3\CMS\Documentation\Service\DocumentationService;
28 use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
29 use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
30 use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
31 use TYPO3\CMS\Extbase\SignalSlot\Dispatcher;
32 use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
33
34 /**
35 * Main controller of the Documentation module.
36 */
37 class DocumentController extends ActionController
38 {
39 /**
40 * @var DocumentRepository
41 */
42 protected $documentRepository;
43
44 /**
45 * @var DocumentationService
46 */
47 protected $documentationService;
48
49 /**
50 * @var Dispatcher
51 */
52 protected $signalSlotDispatcher;
53
54 /**
55 * Backend Template Container
56 *
57 * @var BackendTemplateView
58 */
59 protected $defaultViewObjectName = BackendTemplateView::class;
60
61 /**
62 * BackendTemplateContainer
63 *
64 * @var BackendTemplateView
65 */
66 protected $view;
67
68 /**
69 * Set up the doc header properly here
70 *
71 * @param ViewInterface $view
72 */
73 protected function initializeView(ViewInterface $view)
74 {
75 if ($view instanceof BackendTemplateView) {
76 /** @var BackendTemplateView $view */
77 parent::initializeView($view);
78 $view->getModuleTemplate()->getDocHeaderComponent()->setMetaInformation([]);
79 $uriBuilder = $this->objectManager->get(UriBuilder::class);
80 $uriBuilder->setRequest($this->request);
81
82 $this->view->getModuleTemplate()->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Documentation/Main');
83 $menu = $this->view->getModuleTemplate()->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
84 $menu->setIdentifier('DocumentationModuleMenu');
85
86 $isListActive = $this->request->getControllerActionName() === 'list' ? true : false;
87 $uri = $uriBuilder->reset()->uriFor('list', [], 'Document');
88 $listMenuItem = $menu->makeMenuItem()
89 ->setTitle($this->getLanguageService()
90 ->sL('LLL:EXT:documentation/Resources/Private/Language/locallang.xlf:showDocumentation'))
91 ->setHref($uri)
92 ->setActive($isListActive);
93 $menu->addMenuItem($listMenuItem);
94
95 if ($this->getBackendUser()->isAdmin()) {
96 $isDownloadActive = $this->request->getControllerActionName() ===
97 'download' ? true : false;
98 $uri =
99 $uriBuilder->reset()->uriFor('download', [], 'Document');
100 $downloadMenuItem = $menu->makeMenuItem()
101 ->setTitle($this->getLanguageService()
102 ->sL('LLL:EXT:documentation/Resources/Private/Language/locallang.xlf:downloadDocumentation'))
103 ->setHref($uri)
104 ->setActive($isDownloadActive);
105 $menu->addMenuItem($downloadMenuItem);
106 }
107
108 $this->view->getModuleTemplate()->getDocHeaderComponent()->getMenuRegistry()->addMenu($menu);
109 $this->view->getModuleTemplate()->setFlashMessageQueue($this->controllerContext->getFlashMessageQueue());
110 }
111 }
112
113 /**
114 * @param DocumentRepository $documentRepository
115 */
116 public function injectDocumentRepository(DocumentRepository $documentRepository)
117 {
118 $this->documentRepository = $documentRepository;
119 }
120
121 /**
122 * @param DocumentationService $documentationService
123 */
124 public function injectDocumentationService(DocumentationService $documentationService)
125 {
126 $this->documentationService = $documentationService;
127 }
128
129 /**
130 * @param Dispatcher $signalSlotDispatcher
131 */
132 public function injectSignalSlotDispatcher(Dispatcher $signalSlotDispatcher)
133 {
134 $this->signalSlotDispatcher = $signalSlotDispatcher;
135 }
136
137 /**
138 * Lists the available documents.
139 */
140 public function listAction()
141 {
142 $this->view->getModuleTemplate()->getDocHeaderComponent()->setMetaInformation([]);
143
144 $documents = $this->getDocuments();
145
146 // Filter documents to be shown for current user
147 $userTsConfig = $this->getBackendUser()->getTSConfig();
148 $hideDocuments = GeneralUtility::trimExplode(',', $userTsConfig['mod.']['help_DocumentationDocumentation.']['documents.']['hide'] ?? '', true);
149 if (!empty($hideDocuments)) {
150 $documents = array_diff_key($documents, array_flip($hideDocuments));
151 }
152 $showDocuments = GeneralUtility::trimExplode(',', $userTsConfig['mod.']['help_DocumentationDocumentation.']['documents.']['show'] ?? '', true);
153 if (!empty($showDocuments)) {
154 $documents = array_intersect_key($documents, array_flip($showDocuments));
155 }
156
157 $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
158 $pageRenderer->addInlineLanguageLabelFile('EXT:documentation/Resources/Private/Language/locallang.xlf');
159 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Documentation/Main');
160
161 $this->view->assign('documents', $documents);
162 }
163
164 /**
165 * Delete documentation with given packageKey
166 *
167 * @param ServerRequestInterface $request
168 * @return ResponseInterface
169 */
170 public function deleteAction(ServerRequestInterface $request): ResponseInterface
171 {
172 $basePath = 'typo3conf/Documentation/';
173 $packageKey = $request->getParsedBody();
174 $isDirDeleted = GeneralUtility::rmdir(Environment::getPublicPath() . '/' . $basePath . $packageKey['documentationKey'], true);
175 if (!$isDirDeleted) {
176 $this->addFlashMessage(LocalizationUtility::translate('deleteFailed', 'Documentation'), '', FlashMessage::ERROR);
177 }
178 return new JsonResponse([$isDirDeleted]);
179 }
180
181 /**
182 * Returns available documents.
183 *
184 * @return \TYPO3\CMS\Documentation\Domain\Model\Document[]
185 * @api
186 */
187 public function getDocuments()
188 {
189 $language = $this->getBackendUser()->uc['lang'] ?: 'default';
190 $documents = $this->documentRepository->findByLanguage($language);
191
192 $documents = $this->emitAfterInitializeDocumentsSignal($language, $documents);
193
194 return $documents;
195 }
196
197 /**
198 * Emits a signal after the documents are initialized
199 *
200 * @param string $language
201 * @param \TYPO3\CMS\Documentation\Domain\Model\Document[] $documents
202 * @return \TYPO3\CMS\Documentation\Domain\Model\Document[]
203 */
204 protected function emitAfterInitializeDocumentsSignal($language, array $documents)
205 {
206 $this->signalSlotDispatcher->dispatch(
207 __CLASS__,
208 'afterInitializeDocuments',
209 [
210 $language,
211 &$documents,
212 ]
213 );
214 return $documents;
215 }
216
217 /**
218 * Shows documents to be downloaded/fetched from a remote location.
219 */
220 public function downloadAction()
221 {
222 // This action is reserved for admin users. Redirect to default view if not.
223 if (!$this->getBackendUser()->isAdmin()) {
224 $this->redirect('list');
225 }
226
227 // Retrieve the list of official documents
228 $documents = $this->documentationService->getOfficialDocuments();
229
230 // Merge with the list of local extensions
231 $extensions = $this->documentationService->getLocalExtensions();
232 $allDocuments = array_merge($documents, $extensions);
233
234 $this->view->assign('documents', $allDocuments);
235 }
236
237 /**
238 * Fetches a document from a remote URL.
239 *
240 * @param string $url
241 * @param string $key
242 * @param string $version
243 */
244 public function fetchAction($url, $key, $version = null)
245 {
246 // This action is reserved for admin users. Redirect to default view if not.
247 if (!$this->getBackendUser()->isAdmin()) {
248 $this->redirect('list');
249 }
250
251 $language = $this->getBackendUser()->uc['lang'] ?: 'default';
252 try {
253 $result = $this->documentationService->fetchNearestDocument($url, $key, $version ?: 'latest', $language);
254 if ($result) {
255 $this->addFlashMessage(
256 LocalizationUtility::translate(
257 'downloadSucceeded',
258 'documentation'
259 ),
260 '',
261 FlashMessage::OK
262 );
263 } else {
264 $this->addFlashMessage(
265 LocalizationUtility::translate(
266 'downloadFailedNoArchive',
267 'documentation'
268 ),
269 LocalizationUtility::translate(
270 'downloadFailed',
271 'documentation'
272 ),
273 FlashMessage::ERROR
274 );
275 }
276 } catch (\Exception $e) {
277 $this->addFlashMessage(
278 LocalizationUtility::translate(
279 'downloadFailedDetails',
280 'documentation',
281 [
282 $key,
283 $e->getMessage(),
284 $e->getCode()
285 ]
286 ),
287 LocalizationUtility::translate(
288 'downloadFailed',
289 'documentation'
290 ),
291 FlashMessage::ERROR
292 );
293 }
294 $this->redirect('download');
295 }
296
297 /**
298 * Get backend user
299 *
300 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
301 */
302 protected function getBackendUser()
303 {
304 return $GLOBALS['BE_USER'];
305 }
306
307 /**
308 * Returns the LanguageService
309 *
310 * @return LanguageService
311 */
312 protected function getLanguageService()
313 {
314 return $GLOBALS['LANG'];
315 }
316 }