adb02c926f906bf3faf8c202d932844c6f9e11aa
[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\Http\JsonResponse;
21 use TYPO3\CMS\Core\Localization\LanguageService;
22 use TYPO3\CMS\Core\Messaging\FlashMessage;
23 use TYPO3\CMS\Core\Page\PageRenderer;
24 use TYPO3\CMS\Core\Utility\GeneralUtility;
25 use TYPO3\CMS\Documentation\Domain\Repository\DocumentRepository;
26 use TYPO3\CMS\Documentation\Service\DocumentationService;
27 use TYPO3\CMS\Documentation\Utility\LanguageUtility;
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 LanguageUtility
51 */
52 protected $languageUtility;
53
54 /**
55 * @var Dispatcher
56 */
57 protected $signalSlotDispatcher;
58
59 /**
60 * Backend Template Container
61 *
62 * @var BackendTemplateView
63 */
64 protected $defaultViewObjectName = BackendTemplateView::class;
65
66 /**
67 * BackendTemplateContainer
68 *
69 * @var BackendTemplateView
70 */
71 protected $view;
72
73 /**
74 * Set up the doc header properly here
75 *
76 * @param ViewInterface $view
77 */
78 protected function initializeView(ViewInterface $view)
79 {
80 if ($view instanceof BackendTemplateView) {
81 /** @var BackendTemplateView $view */
82 parent::initializeView($view);
83 $view->getModuleTemplate()->getDocHeaderComponent()->setMetaInformation([]);
84 $uriBuilder = $this->objectManager->get(UriBuilder::class);
85 $uriBuilder->setRequest($this->request);
86
87 $this->view->getModuleTemplate()->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Documentation/Main');
88 $menu = $this->view->getModuleTemplate()->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
89 $menu->setIdentifier('DocumentationModuleMenu');
90
91 $isListActive = $this->request->getControllerActionName() === 'list' ? true : false;
92 $uri = $uriBuilder->reset()->uriFor('list', [], 'Document');
93 $listMenuItem = $menu->makeMenuItem()
94 ->setTitle($this->getLanguageService()
95 ->sL('LLL:EXT:documentation/Resources/Private/Language/locallang.xlf:showDocumentation'))
96 ->setHref($uri)
97 ->setActive($isListActive);
98 $menu->addMenuItem($listMenuItem);
99
100 if ($this->getBackendUser()->isAdmin()) {
101 $isDownloadActive = $this->request->getControllerActionName() ===
102 'download' ? true : false;
103 $uri =
104 $uriBuilder->reset()->uriFor('download', [], 'Document');
105 $downloadMenuItem = $menu->makeMenuItem()
106 ->setTitle($this->getLanguageService()
107 ->sL('LLL:EXT:documentation/Resources/Private/Language/locallang.xlf:downloadDocumentation'))
108 ->setHref($uri)
109 ->setActive($isDownloadActive);
110 $menu->addMenuItem($downloadMenuItem);
111 }
112
113 $this->view->getModuleTemplate()->getDocHeaderComponent()->getMenuRegistry()->addMenu($menu);
114 $this->view->getModuleTemplate()->setFlashMessageQueue($this->controllerContext->getFlashMessageQueue());
115 }
116 }
117
118 /**
119 * @param DocumentRepository $documentRepository
120 */
121 public function injectDocumentRepository(DocumentRepository $documentRepository)
122 {
123 $this->documentRepository = $documentRepository;
124 }
125
126 /**
127 * @param DocumentationService $documentationService
128 */
129 public function injectDocumentationService(DocumentationService $documentationService)
130 {
131 $this->documentationService = $documentationService;
132 }
133
134 /**
135 * @param LanguageUtility $languageUtility
136 */
137 public function injectLanguageUtility(LanguageUtility $languageUtility)
138 {
139 $this->languageUtility = $languageUtility;
140 }
141
142 /**
143 * @param Dispatcher $signalSlotDispatcher
144 */
145 public function injectSignalSlotDispatcher(Dispatcher $signalSlotDispatcher)
146 {
147 $this->signalSlotDispatcher = $signalSlotDispatcher;
148 }
149
150 /**
151 * Lists the available documents.
152 */
153 public function listAction()
154 {
155 $this->view->getModuleTemplate()->getDocHeaderComponent()->setMetaInformation([]);
156
157 $documents = $this->getDocuments();
158
159 // Filter documents to be shown for current user
160 $hideDocuments = $this->getBackendUser()->getTSConfigVal('mod.help_DocumentationDocumentation.documents.hide');
161 $hideDocuments = GeneralUtility::trimExplode(',', $hideDocuments, true);
162 if (!empty($hideDocuments)) {
163 $documents = array_diff_key($documents, array_flip($hideDocuments));
164 }
165 $showDocuments = $this->getBackendUser()->getTSConfigVal('mod.help_DocumentationDocumentation.documents.show');
166 $showDocuments = GeneralUtility::trimExplode(',', $showDocuments, true);
167 if (!empty($showDocuments)) {
168 $documents = array_intersect_key($documents, array_flip($showDocuments));
169 }
170
171 $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
172 $pageRenderer->addInlineLanguageLabelFile('EXT:documentation/Resources/Private/Language/locallang.xlf');
173 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Documentation/Main');
174
175 $this->view->assign('documents', $documents);
176 }
177
178 /**
179 * Delete documentation with given packageKey
180 *
181 * @param ServerRequestInterface $request
182 * @return ResponseInterface
183 */
184 public function deleteAction(ServerRequestInterface $request)
185 {
186 $basePath = 'typo3conf/Documentation/';
187 $packageKey = $request->getParsedBody();
188 $isDirDeleted = GeneralUtility::rmdir(PATH_site . $basePath . $packageKey['documentationKey'], true);
189 if (!$isDirDeleted) {
190 $this->addFlashMessage(LocalizationUtility::translate('deleteFailed', 'Documentation'), '', FlashMessage::ERROR);
191 }
192
193 return GeneralUtility::makeInstance(JsonResponse::class)->setPayload([$isDirDeleted]);
194 }
195
196 /**
197 * Returns available documents.
198 *
199 * @return \TYPO3\CMS\Documentation\Domain\Model\Document[]
200 * @api
201 */
202 public function getDocuments()
203 {
204 $language = $this->languageUtility->getDocumentationLanguage();
205 $documents = $this->documentRepository->findByLanguage($language);
206
207 $documents = $this->emitAfterInitializeDocumentsSignal($language, $documents);
208
209 return $documents;
210 }
211
212 /**
213 * Emits a signal after the documents are initialized
214 *
215 * @param string $language
216 * @param \TYPO3\CMS\Documentation\Domain\Model\Document[] $documents
217 * @return \TYPO3\CMS\Documentation\Domain\Model\Document[]
218 */
219 protected function emitAfterInitializeDocumentsSignal($language, array $documents)
220 {
221 $this->signalSlotDispatcher->dispatch(
222 __CLASS__,
223 'afterInitializeDocuments',
224 [
225 $language,
226 &$documents,
227 ]
228 );
229 return $documents;
230 }
231
232 /**
233 * Shows documents to be downloaded/fetched from a remote location.
234 */
235 public function downloadAction()
236 {
237 // This action is reserved for admin users. Redirect to default view if not.
238 if (!$this->getBackendUser()->isAdmin()) {
239 $this->redirect('list');
240 }
241
242 // Retrieve the list of official documents
243 $documents = $this->documentationService->getOfficialDocuments();
244
245 // Merge with the list of local extensions
246 $extensions = $this->documentationService->getLocalExtensions();
247 $allDocuments = array_merge($documents, $extensions);
248
249 $this->view->assign('documents', $allDocuments);
250 }
251
252 /**
253 * Fetches a document from a remote URL.
254 *
255 * @param string $url
256 * @param string $key
257 * @param string $version
258 */
259 public function fetchAction($url, $key, $version = null)
260 {
261 // This action is reserved for admin users. Redirect to default view if not.
262 if (!$this->getBackendUser()->isAdmin()) {
263 $this->redirect('list');
264 }
265
266 $language = $this->languageUtility->getDocumentationLanguage();
267 try {
268 $result = $this->documentationService->fetchNearestDocument($url, $key, $version ?: 'latest', $language);
269 if ($result) {
270 $this->addFlashMessage(
271 LocalizationUtility::translate(
272 'downloadSucceeded',
273 'documentation'
274 ),
275 '',
276 FlashMessage::OK
277 );
278 } else {
279 $this->addFlashMessage(
280 LocalizationUtility::translate(
281 'downloadFailedNoArchive',
282 'documentation'
283 ),
284 LocalizationUtility::translate(
285 'downloadFailed',
286 'documentation'
287 ),
288 FlashMessage::ERROR
289 );
290 }
291 } catch (\Exception $e) {
292 $this->addFlashMessage(
293 LocalizationUtility::translate(
294 'downloadFailedDetails',
295 'documentation',
296 [
297 $key,
298 $e->getMessage(),
299 $e->getCode()
300 ]
301 ),
302 LocalizationUtility::translate(
303 'downloadFailed',
304 'documentation'
305 ),
306 FlashMessage::ERROR
307 );
308 }
309 $this->redirect('download');
310 }
311
312 /**
313 * Get backend user
314 *
315 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
316 */
317 protected function getBackendUser()
318 {
319 return $GLOBALS['BE_USER'];
320 }
321
322 /**
323 * Returns the LanguageService
324 *
325 * @return LanguageService
326 */
327 protected function getLanguageService()
328 {
329 return $GLOBALS['LANG'];
330 }
331 }