[TASK] Call explicit render() on icon objects
[Packages/TYPO3.CMS.git] / typo3 / sysext / opendocs / Classes / Backend / ToolbarItems / OpendocsToolbarItem.php
1 <?php
2 namespace TYPO3\CMS\Opendocs\Backend\ToolbarItems;
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\Toolbar\ToolbarItemInterface;
20 use TYPO3\CMS\Core\Imaging\Icon;
21 use TYPO3\CMS\Core\Imaging\IconFactory;
22 use TYPO3\CMS\Core\Page\PageRenderer;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24
25 /**
26 * Alist of all open documents
27 */
28 class OpendocsToolbarItem implements ToolbarItemInterface {
29
30 /**
31 * @var array
32 */
33 protected $openDocs;
34
35 /**
36 * @var array
37 */
38 protected $recentDocs;
39
40 /**
41 * @var IconFactory
42 */
43 protected $iconFactory;
44
45 /**
46 * Constructor
47 */
48 public function __construct() {
49 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
50 $this->getLanguageService()->includeLLFile('EXT:opendocs/Resources/Private/Language/locallang.xlf');
51 $this->loadDocsFromUserSession();
52 $pageRenderer = $this->getPageRenderer();
53 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Opendocs/Toolbar/OpendocsMenu');
54 }
55
56 /**
57 * Checks whether the user has access to this toolbar item
58 *
59 * @return bool TRUE if user has access, FALSE if not
60 */
61 public function checkAccess() {
62 $conf = $this->getBackendUser()->getTSConfig('backendToolbarItem.tx_opendocs.disabled');
63 return $conf['value'] != 1;
64 }
65
66 /**
67 * Loads the opened and recently opened documents from the user
68 *
69 * @return void
70 */
71 public function loadDocsFromUserSession() {
72 $backendUser = $this->getBackendUser();
73 list($this->openDocs, ) = $backendUser->getModuleData('FormEngine', 'ses');
74 $this->recentDocs = $backendUser->getModuleData('opendocs::recent');
75 }
76
77 /**
78 * Render toolbar icon
79 *
80 * @return string HTML
81 */
82 public function getItem() {
83 $numDocs = count($this->openDocs);
84 $title = $this->getLanguageService()->getLL('toolbaritem', TRUE);
85
86 $opendocsMenu = array();
87 $opendocsMenu[] = '<span title="' . $title . '">' . $this->iconFactory->getIcon('apps-toolbar-menu-opendocs', Icon::SIZE_SMALL)->render() . '</span>';
88 $opendocsMenu[] = '<span class="badge" id="tx-opendocs-counter">' . $numDocs . '</span>';
89
90 return implode(LF, $opendocsMenu);
91 }
92
93 /**
94 * Render drop down
95 *
96 * @return string HTML
97 */
98 public function getDropDown() {
99 $languageService = $this->getLanguageService();
100 $openDocuments = $this->openDocs;
101 $recentDocuments = $this->recentDocs;
102 $entries = array();
103 if (!empty($openDocuments)) {
104 $entries[] = '<li class="dropdown-header">' . $languageService->getLL('open_docs', TRUE) . '</li>';
105 $i = 0;
106 foreach ($openDocuments as $md5sum => $openDocument) {
107 $i++;
108 $entries[] = $this->renderMenuEntry($openDocument, $md5sum, FALSE, $i == 1);
109 }
110 $entries[] = '<li class="divider"></li>';
111 }
112 // If there are "recent documents" in the list, add them
113 if (!empty($recentDocuments)) {
114 $entries[] = '<li class="dropdown-header">' . $languageService->getLL('recent_docs', TRUE) . '</li>';
115 $i = 0;
116 foreach ($recentDocuments as $md5sum => $recentDocument) {
117 $i++;
118 $entries[] = $this->renderMenuEntry($recentDocument, $md5sum, TRUE, $i == 1);
119 }
120 }
121 if (!empty($entries)) {
122 $content = '<ul class="dropdown-list">' . implode('', $entries) . '</ul>';
123 } else {
124 $content = '<p>' . $languageService->getLL('no_docs', TRUE) . '</p>';
125 }
126 return $content;
127 }
128
129 /**
130 * Returns the recent documents list as an array
131 *
132 * @param array $document
133 * @param string $md5sum
134 * @param bool $isRecentDoc
135 * @param bool $isFirstDoc
136 * @return array All recent documents as list-items
137 */
138 protected function renderMenuEntry($document, $md5sum, $isRecentDoc = FALSE, $isFirstDoc = FALSE) {
139 $table = $document[3]['table'];
140 $uid = $document[3]['uid'];
141 $record = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordWSOL($table, $uid);
142 if (!is_array($record)) {
143 // Record seems to be deleted
144 return '';
145 }
146 $label = htmlspecialchars(strip_tags(htmlspecialchars_decode($document[0])));
147 $icon = $this->iconFactory->getIconForRecord($table, $record, Icon::SIZE_SMALL)->render();
148 $link = \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleUrl('record_edit') . '&' . $document[2];
149 $pageId = (int)$document[3]['uid'];
150 if ($document[3]['table'] !== 'pages') {
151 $pageId = (int)$document[3]['pid'];
152 }
153 $onClickCode = 'jump(' . GeneralUtility::quoteJSvalue($link) . ', \'web_list\', \'web\', ' . $pageId . '); TYPO3.OpendocsMenu.toggleMenu(); return false;';
154 if (!$isRecentDoc) {
155 $title = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.closeDoc', TRUE);
156 // Open document
157 $closeIcon = $this->iconFactory->getIcon('actions-document-close', Icon::SIZE_SMALL)->render();
158 $entry = '
159 <li class="opendoc">
160 <a href="#" class="dropdown-list-link dropdown-link-list-add-close" onclick="' . htmlspecialchars($onClickCode) . '" target="content">' . $icon . ' ' . $label . '</a>
161 <a href="#" class="dropdown-list-link-close" data-opendocsidentifier="' . $md5sum . '" title="' . $title . '">' . $closeIcon . '</a>
162 </li>';
163 } else {
164 // Recently used document
165 $entry = '
166 <li>
167 <a href="#" class="dropdown-list-link" onclick="' . htmlspecialchars($onClickCode) . '" target="content">' . $icon . ' ' . $label . '</a>
168 </li>';
169 }
170 return $entry;
171 }
172
173 /**
174 * No additional attributes
175 *
176 * @return string List item HTML attibutes
177 */
178 public function getAdditionalAttributes() {
179 return array();
180 }
181
182 /**
183 * This item has a drop down
184 *
185 * @return bool
186 */
187 public function hasDropDown() {
188 return TRUE;
189 }
190
191
192 /*******************
193 *** HOOKS ***
194 *******************/
195 /**
196 * Called as a hook in \TYPO3\CMS\Backend\Utility\BackendUtility::setUpdateSignal, calls a JS function to change
197 * the number of opened documents
198 *
199 * @param array $params
200 * @param unknown_type $ref
201 * @return string list item HTML attributes
202 */
203 public function updateNumberOfOpenDocsHook(&$params, $ref) {
204 $params['JScode'] = '
205 if (top && top.TYPO3.OpendocsMenu) {
206 top.TYPO3.OpendocsMenu.updateMenu();
207 }
208 ';
209 }
210
211 /******************
212 *** AJAX CALLS ***
213 ******************/
214 /**
215 * Closes a document in the session and
216 *
217 * @param ServerRequestInterface $request
218 * @param ResponseInterface $response
219 * @return ResponseInterface
220 */
221 public function closeDocument(ServerRequestInterface $request, ResponseInterface $response) {
222 $backendUser = $this->getBackendUser();
223 $md5sum = isset($request->getParsedBody()['md5sum']) ? $request->getParsedBody()['md5sum'] : $request->getQueryParams()['md5sum'];
224 if ($md5sum && isset($this->openDocs[$md5sum])) {
225 // Add the document to be closed to the recent documents
226 $this->recentDocs = array_merge(array($md5sum => $this->openDocs[$md5sum]), $this->recentDocs);
227 // Allow a maximum of 8 recent documents
228 if (count($this->recentDocs) > 8) {
229 $this->recentDocs = array_slice($this->recentDocs, 0, 8);
230 }
231 // Remove it from the list of the open documents, and store the status
232 unset($this->openDocs[$md5sum]);
233 list(, $docDat) = $backendUser->getModuleData('FormEngine', 'ses');
234 $backendUser->pushModuleData('FormEngine', array($this->openDocs, $docDat));
235 $backendUser->pushModuleData('opendocs::recent', $this->recentDocs);
236 }
237 return $this->renderMenu($request, $response);
238 }
239
240 /**
241 * Renders the menu so that it can be returned as response to an AJAX call
242 *
243 * @param ServerRequestInterface $request
244 * @param ResponseInterface $response
245 * @return ResponseInterface
246 */
247 public function renderMenu(ServerRequestInterface $request, ResponseInterface $response) {
248 $response->getBody()->write($this->getDropDown());
249 $response = $response->withHeader('Content-Type', 'html');
250 return $response;
251 }
252
253 /**
254 * Position relative to others
255 *
256 * @return int
257 */
258 public function getIndex() {
259 return 30;
260 }
261
262 /**
263 * Returns the current BE user.
264 *
265 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
266 */
267 protected function getBackendUser() {
268 return $GLOBALS['BE_USER'];
269 }
270
271 /**
272 * Returns current PageRenderer
273 *
274 * @return PageRenderer
275 */
276 protected function getPageRenderer() {
277 return GeneralUtility::makeInstance(PageRenderer::class);
278 }
279
280 /**
281 * Returns LanguageService
282 *
283 * @return \TYPO3\CMS\Lang\LanguageService
284 */
285 protected function getLanguageService() {
286 return $GLOBALS['LANG'];
287 }
288
289 /**
290 * Return DatabaseConnection
291 *
292 * @return \TYPO3\CMS\Core\Database\DatabaseConnection
293 */
294 protected function getDatabaseConnection() {
295 return $GLOBALS['TYPO3_DB'];
296 }
297
298 }