[TASK] Move Backend Module calls to index.php
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Backend / ToolbarItems / ShortcutToolbarItem.php
1 <?php
2 namespace TYPO3\CMS\Backend\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 TYPO3\CMS\Backend\Module\ModuleLoader;
18 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
19 use TYPO3\CMS\Backend\Utility\BackendUtility;
20 use TYPO3\CMS\Backend\Utility\IconUtility;
21 use TYPO3\CMS\Core\Http\AjaxRequestHandler;
22 use TYPO3\CMS\Core\Page\PageRenderer;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24 use TYPO3\CMS\Core\Utility\MathUtility;
25 use TYPO3\CMS\Core\Utility\PathUtility;
26
27 /**
28 * Class to render the shortcut menu
29 */
30 class ShortcutToolbarItem implements ToolbarItemInterface {
31
32 /**
33 * @const integer Number of super global group
34 */
35 const SUPERGLOBAL_GROUP = -100;
36
37 /**
38 * @var string
39 */
40 public $perms_clause;
41
42 /**
43 * @var array
44 */
45 public $fieldArray;
46
47 /**
48 * All available shortcuts
49 *
50 * @var array
51 */
52 protected $shortcuts;
53
54 /**
55 * @var array
56 */
57 protected $shortcutGroups;
58
59 /**
60 * Labels of all groups.
61 * If value is 1, the system will try to find a label in the locallang array.
62 *
63 * @var array
64 */
65 protected $groupLabels;
66
67 /**
68 * Constructor
69 */
70 public function __construct() {
71 if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX) {
72 $this->getLanguageService()->includeLLFile('EXT:lang/locallang_misc.xlf');
73 // Needed to get the correct icons when reloading the menu after saving it
74 $loadModules = GeneralUtility::makeInstance(ModuleLoader::class);
75 $loadModules->load($GLOBALS['TBE_MODULES']);
76 }
77
78 // By default, 5 groups are set
79 $this->shortcutGroups = array(
80 1 => '1',
81 2 => '1',
82 3 => '1',
83 4 => '1',
84 5 => '1'
85 );
86 $this->shortcutGroups = $this->initShortcutGroups();
87 $this->shortcuts = $this->initShortcuts();
88
89 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Toolbar/ShortcutMenu');
90 }
91
92 /**
93 * Checks whether the user has access to this toolbar item
94 *
95 * @return bool TRUE if user has access, FALSE if not
96 */
97 public function checkAccess() {
98 return (bool)$this->getBackendUser()->getTSConfigVal('options.enableBookmarks');
99 }
100
101 /**
102 * Render shortcut icon
103 *
104 * @return string HTML
105 */
106 public function getItem() {
107 return IconUtility::getSpriteIcon(
108 'apps-toolbar-menu-shortcut',
109 array(
110 'title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarks', TRUE),
111 )
112 );
113 }
114
115 /**
116 * Render drop down content
117 *
118 * @return string HTML
119 */
120 public function getDropDown() {
121 $languageService = $this->getLanguageService();
122 $shortcutGroup = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarksGroup', TRUE);
123 $shortcutEdit = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarksEdit', TRUE);
124 $shortcutDelete = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarksDelete', TRUE);
125 $editIcon = '<a href="#" class="dropdown-list-link-edit shortcut-edit">' . IconUtility::getSpriteIcon('actions-document-open', array('title' => $shortcutEdit)) . '</a>';
126 $deleteIcon = '<a href="#" class="dropdown-list-link-delete shortcut-delete">' . IconUtility::getSpriteIcon('actions-edit-delete', array('title' => $shortcutDelete)) . '</a>';
127
128 $shortcutMenu[] = '<ul class="dropdown-list">';
129
130 // Render shortcuts with no group (group id = 0) first
131 $noGroupShortcuts = $this->getShortcutsByGroup(0);
132 foreach ($noGroupShortcuts as $shortcut) {
133
134 $shortcutMenu[] = '
135 <li class="shortcut" data-shortcutid="' . (int)$shortcut['raw']['uid'] . '">
136 <a class="dropdown-list-link dropdown-link-list-add-editdelete" href="#" onclick="' . htmlspecialchars($shortcut['action']) . ' return false;">' .
137 $shortcut['icon'] . ' ' .
138 htmlspecialchars($shortcut['label']) .
139 '</a>
140 ' . $editIcon . $deleteIcon . '
141 </li>';
142 }
143 // Now render groups and the contained shortcuts
144 $groups = $this->getGroupsFromShortcuts();
145 krsort($groups, SORT_NUMERIC);
146 foreach ($groups as $groupId => $groupLabel) {
147 if ($groupId != 0) {
148 $shortcutGroup = '';
149 if (count($shortcutMenu) > 1) {
150 $shortcutGroup .= '<li class="divider"></li>';
151 }
152 $shortcutGroup .= '
153 <li class="dropdown-header" id="shortcut-group-' . (int)$groupId . '">
154 ' . $groupLabel . '
155 </li>';
156 $shortcuts = $this->getShortcutsByGroup($groupId);
157 $i = 0;
158 foreach ($shortcuts as $shortcut) {
159 $i++;
160 $shortcutGroup .= '
161 <li class="shortcut" data-shortcutid="' . (int)$shortcut['raw']['uid'] . '" data-shortcutgroup="' . (int)$groupId . '">
162 <a class="dropdown-list-link dropdown-link-list-add-editdelete" href="#" onclick="' . htmlspecialchars($shortcut['action']) . ' return false;">' .
163 $shortcut['icon'] . ' ' .
164 htmlspecialchars($shortcut['label']) .
165 '</a>
166 ' . $editIcon . $deleteIcon . '
167 </li>';
168 }
169 $shortcutMenu[] = $shortcutGroup;
170 }
171 }
172 $shortcutMenu[] = '</ul>';
173
174 if (count($shortcutMenu) === 2) {
175 // No shortcuts added yet, show a small help message how to add shortcuts
176 $title = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarks', TRUE);
177 $icon = IconUtility::getSpriteIcon('actions-system-shortcut-new', array(
178 'title' => $title
179 ));
180 $label = str_replace('%icon%', $icon, $languageService->sL('LLL:EXT:lang/locallang_misc.xlf:bookmarkDescription'));
181 $compiledShortcutMenu = '<p>' . $label . '</p>';
182 } else {
183 $compiledShortcutMenu = implode(LF, $shortcutMenu);
184 }
185
186 return $compiledShortcutMenu;
187 }
188
189 /**
190 * Renders the menu so that it can be returned as response to an AJAX call
191 *
192 * @param array $params Array of parameters from the AJAX interface, currently unused
193 * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj Object of type AjaxRequestHandler
194 * @return void
195 */
196 public function renderAjaxMenu($params = array(), AjaxRequestHandler $ajaxObj = NULL) {
197 $menuContent = $this->getDropDown();
198 $ajaxObj->addContent('shortcutMenu', $menuContent);
199 }
200
201 /**
202 * This toolbar item needs no additional attributes
203 *
204 * @return array
205 */
206 public function getAdditionalAttributes() {
207 return array();
208 }
209
210 /**
211 * This item has a drop down
212 *
213 * @return bool
214 */
215 public function hasDropDown() {
216 return TRUE;
217 }
218
219 /**
220 * Retrieves the shortcuts for the current user
221 *
222 * @return array Array of shortcuts
223 */
224 protected function initShortcuts() {
225 $databaseConnection = $this->getDatabaseConnection();
226 $globalGroupIdList = implode(',', array_keys($this->getGlobalShortcutGroups()));
227 $backendUser = $this->getBackendUser();
228 $res = $databaseConnection->exec_SELECTquery(
229 '*',
230 'sys_be_shortcuts',
231 '(userid = ' . (int)$backendUser->user['uid'] . ' AND sc_group>=0) OR sc_group IN (' . $globalGroupIdList . ')',
232 '',
233 'sc_group,sorting'
234 );
235 // Traverse shortcuts
236 $lastGroup = 0;
237 $shortcuts = array();
238 while ($row = $databaseConnection->sql_fetch_assoc($res)) {
239 $shortcut = array('raw' => $row);
240
241 list($row['module_name'], $row['M_module_name']) = explode('|', $row['module_name']);
242
243 $queryParts = parse_url($row['url']);
244 $queryParameters = GeneralUtility::explodeUrl2Array($queryParts['query'], 1);
245 if ($row['module_name'] === 'xMOD_alt_doc.php' && is_array($queryParameters['edit'])) {
246 $shortcut['table'] = key($queryParameters['edit']);
247 $shortcut['recordid'] = key($queryParameters['edit'][$shortcut['table']]);
248 if ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] === 'edit') {
249 $shortcut['type'] = 'edit';
250 } elseif ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] === 'new') {
251 $shortcut['type'] = 'new';
252 }
253 if (substr($shortcut['recordid'], -1) === ',') {
254 $shortcut['recordid'] = substr($shortcut['recordid'], 0, -1);
255 }
256 } else {
257 $shortcut['type'] = 'other';
258 }
259 // Check for module access
260 $moduleName = $row['M_module_name'] ?: $row['module_name'];
261 $pageId = $this->getLinkedPageId($row['url']);
262 if (!$backendUser->isAdmin()) {
263 if (!isset($this->getLanguageService()->moduleLabels['tabs_images'][$moduleName . '_tab'])) {
264 // Nice hack to check if the user has access to this module
265 // - otherwise the translation label would not have been loaded :-)
266 continue;
267 }
268 if (MathUtility::canBeInterpretedAsInteger($pageId)) {
269 // Check for webmount access
270 if (!$backendUser->isInWebMount($pageId)) {
271 continue;
272 }
273 // Check for record access
274 $pageRow = BackendUtility::getRecord('pages', $pageId);
275 if (!$backendUser->doesUserHaveAccess($pageRow, ($perms = 1))) {
276 continue;
277 }
278 }
279 }
280 $moduleParts = explode('_', $moduleName);
281 $shortcutGroup = (int)$row['sc_group'];
282 if ($shortcutGroup && $lastGroup !== $shortcutGroup && $shortcutGroup !== self::SUPERGLOBAL_GROUP) {
283 $shortcut['groupLabel'] = $this->getShortcutGroupLabel($shortcutGroup);
284 }
285 $lastGroup = $shortcutGroup;
286
287 if ($row['description']) {
288 $shortcut['label'] = $row['description'];
289 } else {
290 $shortcut['label'] = GeneralUtility::fixed_lgd_cs(rawurldecode($queryParts['query']), 150);
291 }
292 $shortcut['group'] = $shortcutGroup;
293 $shortcut['icon'] = $this->getShortcutIcon($row, $shortcut);
294 $shortcut['iconTitle'] = $this->getShortcutIconTitle($shortcut['label'], $row['module_name'], $row['M_module_name']);
295 $shortcut['action'] = 'jump(' . GeneralUtility::quoteJSvalue($this->getTokenUrl($row['url'])) . ',' . GeneralUtility::quoteJSvalue($moduleName) . ',' . GeneralUtility::quoteJSvalue($moduleParts[0]) . ', ' . (int)$pageId . ');';
296
297 $shortcuts[] = $shortcut;
298 }
299 return $shortcuts;
300 }
301
302 /**
303 * Adds the correct token, if the url is a index.php script
304 *
305 * @param string $url
306 * @return string
307 */
308 protected function getTokenUrl($url) {
309 $parsedUrl = parse_url($url);
310 parse_str($parsedUrl['query'], $parameters);
311
312 // parse the returnUrl and replace the module token of it
313 if (isset($parameters['returnUrl'])) {
314 $parsedReturnUrl = parse_url($parameters['returnUrl']);
315 parse_str($parsedReturnUrl['query'], $returnUrlParameters);
316 if (strpos($parsedReturnUrl['path'], 'index.php') !== FALSE && isset($returnUrlParameters['M'])) {
317 $module = $returnUrlParameters['M'];
318 $returnUrl = BackendUtility::getModuleUrl($module, $returnUrlParameters);
319 $parameters['returnUrl'] = $returnUrl;
320 $url = $parsedUrl['path'] . '?' . http_build_query($parameters);
321 }
322 }
323
324 if (strpos($parsedUrl['path'], 'index.php') !== FALSE && isset($parameters['M'])) {
325 $module = $parameters['M'];
326 $url = BackendUtility::getModuleUrl($module, $parameters);
327 }
328 return $url;
329 }
330
331 /**
332 * Gets shortcuts for a specific group
333 *
334 * @param int $groupId Group Id
335 * @return array Array of shortcuts that matched the group
336 */
337 protected function getShortcutsByGroup($groupId) {
338 $shortcuts = array();
339 foreach ($this->shortcuts as $shortcut) {
340 if ($shortcut['group'] == $groupId) {
341 $shortcuts[] = $shortcut;
342 }
343 }
344 return $shortcuts;
345 }
346
347 /**
348 * Gets a shortcut by its uid
349 *
350 * @param int $shortcutId Shortcut id to get the complete shortcut for
351 * @return mixed An array containing the shortcut's data on success or FALSE on failure
352 */
353 protected function getShortcutById($shortcutId) {
354 $returnShortcut = FALSE;
355 foreach ($this->shortcuts as $shortcut) {
356 if ($shortcut['raw']['uid'] == (int)$shortcutId) {
357 $returnShortcut = $shortcut;
358 continue;
359 }
360 }
361 return $returnShortcut;
362 }
363
364 /**
365 * Gets the available shortcut groups from default groups, user TSConfig, and global groups
366 *
367 * @return array
368 */
369 protected function initShortcutGroups() {
370 $languageService = $this->getLanguageService();
371 $backendUser = $this->getBackendUser();
372 // Groups from TSConfig
373 $bookmarkGroups = $backendUser->getTSConfigProp('options.bookmarkGroups');
374 if (is_array($bookmarkGroups) && !empty($bookmarkGroups)) {
375 foreach ($bookmarkGroups as $groupId => $label) {
376 if (!empty($label)) {
377 $this->shortcutGroups[$groupId] = (string)$label;
378 } elseif ($backendUser->isAdmin()) {
379 unset($this->shortcutGroups[$groupId]);
380 }
381 }
382 }
383 // Generate global groups, all global groups have negative IDs.
384 if (!empty($this->shortcutGroups)) {
385 $groups = $this->shortcutGroups;
386 foreach ($groups as $groupId => $groupLabel) {
387 $this->shortcutGroups[$groupId * -1] = $groupLabel;
388 }
389 }
390 // Group -100 is kind of superglobal and can't be changed.
391 $this->shortcutGroups[self::SUPERGLOBAL_GROUP] = 1;
392 // Add labels
393 foreach ($this->shortcutGroups as $groupId => $groupLabel) {
394 $groupId = (int)$groupId;
395 $label = $groupLabel;
396 if ($groupLabel == '1') {
397 $label = $languageService->sL('LLL:EXT:lang/locallang_misc.xlf:bookmark_group_' . abs($groupId), TRUE);
398 if (empty($label)) {
399 // Fallback label
400 $label = $languageService->getLL('bookmark_group', TRUE) . ' ' . abs($groupId);
401 }
402 }
403 if ($groupId < 0) {
404 // Global group
405 $label = $languageService->sL('LLL:EXT:lang/locallang_misc.xlf:bookmark_global', TRUE) . ': ' . (!empty($label) ? $label : abs($groupId));
406 if ($groupId === self::SUPERGLOBAL_GROUP) {
407 $label = $languageService->getLL('bookmark_global', TRUE) . ': ' . $languageService->getLL('bookmark_all', TRUE);
408 }
409 }
410 $this->shortcutGroups[$groupId] = $label;
411 }
412 return $this->shortcutGroups;
413 }
414
415 /**
416 * gets the available shortcut groups, renders a form so it can be saved lateron
417 *
418 * @param array $params Array of parameters from the AJAX interface, currently unused
419 * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj Object of type AjaxRequestHandler
420 * @return void
421 */
422 public function getAjaxShortcutEditForm($params = array(), AjaxRequestHandler $ajaxObj = NULL) {
423 $selectedShortcutId = (int)GeneralUtility::_GP('shortcutId');
424 $selectedShortcutGroupId = (int)GeneralUtility::_GP('shortcutGroup');
425 $selectedShortcut = $this->getShortcutById($selectedShortcutId);
426
427 $shortcutGroups = $this->shortcutGroups;
428 if (!$this->getBackendUser()->isAdmin()) {
429 foreach ($shortcutGroups as $groupId => $groupName) {
430 if ((int)$groupId < 0) {
431 unset($shortcutGroups[$groupId]);
432 }
433 }
434 }
435
436 // build the form
437 $content = '
438 <form class="shortcut-form" role="form">
439 <div class="form-group">
440 <input type="text" class="form-control" name="shortcut-title" value="' . htmlspecialchars($selectedShortcut['label']) . '">
441 </div>';
442
443 $content .= '
444 <div class="form-group">
445 <select class="form-control" name="shortcut-group">';
446 foreach ($shortcutGroups as $shortcutGroupId => $shortcutGroupTitle) {
447 $content .= '<option value="' . (int)$shortcutGroupId . '"' . ($selectedShortcutGroupId == $shortcutGroupId ? ' selected="selected"' : '') . '>' . htmlspecialchars($shortcutGroupTitle) . '</option>';
448 }
449 $content .= '
450 </select>
451 </div>
452 <input type="button" class="btn btn-default shortcut-form-cancel" value="Cancel">
453 <input type="button" class="btn btn-success shortcut-form-save" value="Save">
454 </form>';
455
456 $ajaxObj->addContent('data', $content);
457 }
458
459 /**
460 * Deletes a shortcut through an AJAX call
461 *
462 * @param array $params Array of parameters from the AJAX interface, currently unused
463 * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj Object of type AjaxRequestHandler
464 * @return void
465 */
466 public function deleteAjaxShortcut($params = array(), AjaxRequestHandler $ajaxObj = NULL) {
467 $databaseConnection = $this->getDatabaseConnection();
468 $shortcutId = (int)GeneralUtility::_POST('shortcutId');
469 $fullShortcut = $this->getShortcutById($shortcutId);
470 $ajaxReturn = 'failed';
471 if ($fullShortcut['raw']['userid'] == $this->getBackendUser()->user['uid']) {
472 $databaseConnection->exec_DELETEquery('sys_be_shortcuts', 'uid = ' . $shortcutId);
473 if ($databaseConnection->sql_affected_rows() == 1) {
474 $ajaxReturn = 'deleted';
475 }
476 }
477 $ajaxObj->addContent('delete', $ajaxReturn);
478 }
479
480 /**
481 * Creates a shortcut through an AJAX call
482 *
483 * @param array $params Array of parameters from the AJAX interface, currently unused
484 * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj Oject of type AjaxRequestHandler
485 * @return void
486 */
487 public function createAjaxShortcut($params = array(), AjaxRequestHandler $ajaxObj = NULL) {
488 $databaseConnection = $this->getDatabaseConnection();
489 $languageService = $this->getLanguageService();
490 $shortcutCreated = 'failed';
491 // Default name
492 $shortcutName = 'Shortcut';
493 $shortcutNamePrepend = '';
494 $url = GeneralUtility::_POST('url');
495 $module = GeneralUtility::_POST('module');
496 $motherModule = GeneralUtility::_POST('motherModName');
497 // Determine shortcut type
498 $url = rawurldecode($url);
499 $queryParts = parse_url($url);
500 $queryParameters = GeneralUtility::explodeUrl2Array($queryParts['query'], TRUE);
501 // Proceed only if no scheme is defined, as URL is expected to be relative
502 if (empty($queryParts['scheme'])) {
503 if (is_array($queryParameters['edit'])) {
504 $shortcut['table'] = key($queryParameters['edit']);
505 $shortcut['recordid'] = key($queryParameters['edit'][$shortcut['table']]);
506 if ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] == 'edit') {
507 $shortcut['type'] = 'edit';
508 $shortcutNamePrepend = $languageService->getLL('shortcut_edit', TRUE);
509 } elseif ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] == 'new') {
510 $shortcut['type'] = 'new';
511 $shortcutNamePrepend = $languageService->getLL('shortcut_create', TRUE);
512 }
513 } else {
514 $shortcut['type'] = 'other';
515 }
516 // Lookup the title of this page and use it as default description
517 $pageId = $shortcut['recordid'] ? $shortcut['recordid'] : $this->getLinkedPageId($url);
518 if (MathUtility::canBeInterpretedAsInteger($pageId)) {
519 $page = BackendUtility::getRecord('pages', $pageId);
520 if (!empty($page)) {
521 // Set the name to the title of the page
522 if ($shortcut['type'] == 'other') {
523 $shortcutName = $page['title'];
524 } else {
525 $shortcutName = $shortcutNamePrepend . ' ' . $languageService->sL($GLOBALS['TCA'][$shortcut['table']]['ctrl']['title']) . ' (' . $page['title'] . ')';
526 }
527 }
528 } else {
529 $dirName = urldecode($pageId);
530 if (preg_match('/\\/$/', $dirName)) {
531 // If $pageId is a string and ends with a slash,
532 // assume it is a fileadmin reference and set
533 // the description to the basename of that path
534 $shortcutName .= ' ' . basename($dirName);
535 }
536 }
537 // adding the shortcut
538 if ($module && $url) {
539 $fieldValues = array(
540 'userid' => $this->getBackendUser()->user['uid'],
541 'module_name' => $module . '|' . $motherModule,
542 'url' => $url,
543 'description' => $shortcutName,
544 'sorting' => $GLOBALS['EXEC_TIME']
545 );
546 $databaseConnection->exec_INSERTquery('sys_be_shortcuts', $fieldValues);
547 if ($databaseConnection->sql_affected_rows() == 1) {
548 $shortcutCreated = 'success';
549 }
550 }
551 $ajaxObj->addContent('create', $shortcutCreated);
552 }
553 }
554
555 /**
556 * Gets called when a shortcut is changed, checks whether the user has
557 * permissions to do so and saves the changes if everything is ok
558 *
559 * @param array $params Array of parameters from the AJAX interface, currently unused
560 * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj Object of type AjaxRequestHandler
561 * @return void
562 */
563 public function setAjaxShortcut($params = array(), AjaxRequestHandler $ajaxObj = NULL) {
564 $databaseConnection = $this->getDatabaseConnection();
565 $backendUser = $this->getBackendUser();
566 $shortcutId = (int)GeneralUtility::_POST('shortcutId');
567 $shortcutName = strip_tags(GeneralUtility::_POST('shortcutTitle'));
568 $shortcutGroupId = (int)GeneralUtility::_POST('shortcutGroup');
569 if ($shortcutGroupId > 0 || $backendUser->isAdmin()) {
570 // Users can delete only their own shortcuts (except admins)
571 $addUserWhere = !$backendUser->isAdmin() ? ' AND userid=' . (int)$backendUser->user['uid'] : '';
572 $fieldValues = array(
573 'description' => $shortcutName,
574 'sc_group' => $shortcutGroupId
575 );
576 if ($fieldValues['sc_group'] < 0 && !$backendUser->isAdmin()) {
577 $fieldValues['sc_group'] = 0;
578 }
579 $databaseConnection->exec_UPDATEquery('sys_be_shortcuts', 'uid=' . $shortcutId . $addUserWhere, $fieldValues);
580 $affectedRows = $databaseConnection->sql_affected_rows();
581 if ($affectedRows == 1) {
582 $ajaxObj->addContent('shortcut', $shortcutName);
583 } else {
584 $ajaxObj->addContent('shortcut', 'failed');
585 }
586 }
587 $ajaxObj->setContentFormat('plain');
588 }
589
590 /**
591 * Gets the label for a shortcut group
592 *
593 * @param int $groupId A shortcut group id
594 * @return string The shortcut group label, can be an empty string if no group was found for the id
595 */
596 protected function getShortcutGroupLabel($groupId) {
597 return isset($this->shortcutGroups[$groupId]) ? $this->shortcutGroups[$groupId] : '';
598 }
599
600 /**
601 * Gets a list of global groups, shortcuts in these groups are available to all users
602 *
603 * @return array Array of global groups
604 */
605 protected function getGlobalShortcutGroups() {
606 $globalGroups = array();
607 foreach ($this->shortcutGroups as $groupId => $groupLabel) {
608 if ($groupId < 0) {
609 $globalGroups[$groupId] = $groupLabel;
610 }
611 }
612 return $globalGroups;
613 }
614
615 /**
616 * runs through the available shortcuts an collects their groups
617 *
618 * @return array Array of groups which have shortcuts
619 */
620 protected function getGroupsFromShortcuts() {
621 $groups = array();
622 foreach ($this->shortcuts as $shortcut) {
623 $groups[$shortcut['group']] = $this->shortcutGroups[$shortcut['group']];
624 }
625 return array_unique($groups);
626 }
627
628 /**
629 * Gets the icon for the shortcut
630 *
631 * @param array $row
632 * @param array $shortcut
633 * @return string Shortcut icon as img tag
634 */
635 protected function getShortcutIcon($row, $shortcut) {
636 $databaseConnection = $this->getDatabaseConnection();
637 $languageService = $this->getLanguageService();
638 $titleAttribute = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.shortcut', TRUE);
639 switch ($row['module_name']) {
640 case 'xMOD_alt_doc.php':
641 $table = $shortcut['table'];
642 $recordid = $shortcut['recordid'];
643 $icon = '';
644 if ($shortcut['type'] == 'edit') {
645 // Creating the list of fields to include in the SQL query:
646 $selectFields = $this->fieldArray;
647 $selectFields[] = 'uid';
648 $selectFields[] = 'pid';
649 if ($table == 'pages') {
650 $selectFields[] = 'module';
651 $selectFields[] = 'extendToSubpages';
652 $selectFields[] = 'doktype';
653 }
654 if (is_array($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) {
655 $selectFields = array_merge($selectFields, $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']);
656 }
657 if ($GLOBALS['TCA'][$table]['ctrl']['type']) {
658 $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['type'];
659 }
660 if ($GLOBALS['TCA'][$table]['ctrl']['typeicon_column']) {
661 $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_column'];
662 }
663 if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
664 $selectFields[] = 't3ver_state';
665 }
666 // Unique list!
667 $selectFields = array_unique($selectFields);
668 $permissionClause = $table === 'pages' && $this->perms_clause ? ' AND ' . $this->perms_clause : '';
669 $sqlQueryParts = array(
670 'SELECT' => implode(',', $selectFields),
671 'FROM' => $table,
672 'WHERE' => 'uid IN (' . $recordid . ') ' . $permissionClause . BackendUtility::deleteClause($table) . BackendUtility::versioningPlaceholderClause($table)
673 );
674 $result = $databaseConnection->exec_SELECT_queryArray($sqlQueryParts);
675 $row = $databaseConnection->sql_fetch_assoc($result);
676 $icon = IconUtility::getSpriteIconForRecord($table, (array)$row, array('title' => $titleAttribute));
677 } elseif ($shortcut['type'] == 'new') {
678 $icon = IconUtility::getSpriteIconForRecord($table, array(), array('title' => $titleAttribute));
679 }
680 break;
681 case 'file_edit':
682 $icon = IconUtility::getSpriteIcon('mimetypes-text-html', array('title' => $titleAttribute));
683 break;
684 case 'wizard_rte':
685 $icon = IconUtility::getSpriteIcon('mimetypes-word', array('title' => $titleAttribute));
686 break;
687 default:
688 if ($languageService->moduleLabels['tabs_images'][$row['module_name'] . '_tab']) {
689 $icon = $languageService->moduleLabels['tabs_images'][$row['module_name'] . '_tab'];
690 // Change icon of fileadmin references - otherwise it doesn't differ with Web->List
691 $icon = str_replace('mod/file/list/list.gif', 'mod/file/file.gif', $icon);
692 if (GeneralUtility::isAbsPath($icon)) {
693 $icon = '../' . PathUtility::stripPathSitePrefix($icon);
694 }
695 // @todo: hardcoded width as we don't have a way to address module icons with an API yet.
696 $icon = '<img src="' . htmlspecialchars($icon) . '" alt="' . $titleAttribute . '" width="16">';
697 } else {
698 $icon = IconUtility::getSpriteIcon('empty-empty', array('title' => $titleAttribute));
699 }
700 }
701 return $icon;
702 }
703
704 /**
705 * Returns title for the shortcut icon
706 *
707 * @param string $shortcutLabel Shortcut label
708 * @param string $moduleName Backend module name (key)
709 * @param string $parentModuleName Parent module label
710 * @return string Title for the shortcut icon
711 */
712 protected function getShortcutIconTitle($shortcutLabel, $moduleName, $parentModuleName = '') {
713 $languageService = $this->getLanguageService();
714 if (substr($moduleName, 0, 5) == 'xMOD_') {
715 $title = substr($moduleName, 5);
716 } else {
717 $splitModuleName = explode('_', $moduleName);
718 $title = $languageService->moduleLabels['tabs'][$splitModuleName[0] . '_tab'];
719 if (count($splitModuleName) > 1) {
720 $title .= '>' . $languageService->moduleLabels['tabs'][($moduleName . '_tab')];
721 }
722 }
723 if ($parentModuleName) {
724 $title .= ' (' . $parentModuleName . ')';
725 }
726 $title .= ': ' . $shortcutLabel;
727 return $title;
728 }
729
730 /**
731 * Return the ID of the page in the URL if found.
732 *
733 * @param string $url The URL of the current shortcut link
734 * @return string If a page ID was found, it is returned. Otherwise: 0
735 */
736 protected function getLinkedPageId($url) {
737 return preg_replace('/.*[\\?&]id=([^&]+).*/', '$1', $url);
738 }
739
740 /**
741 * Position relative to others, live search should be very right
742 *
743 * @return int
744 */
745 public function getIndex() {
746 return 20;
747 }
748
749 /**
750 * Returns the current BE user.
751 *
752 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
753 */
754 protected function getBackendUser() {
755 return $GLOBALS['BE_USER'];
756 }
757
758 /**
759 * Returns current PageRenderer
760 *
761 * @return PageRenderer
762 */
763 protected function getPageRenderer() {
764 return GeneralUtility::makeInstance(PageRenderer::class);
765 }
766
767 /**
768 * Returns LanguageService
769 *
770 * @return \TYPO3\CMS\Lang\LanguageService
771 */
772 protected function getLanguageService() {
773 return $GLOBALS['LANG'];
774 }
775
776 /**
777 * Return DatabaseConnection
778 *
779 * @return \TYPO3\CMS\Core\Database\DatabaseConnection
780 */
781 protected function getDatabaseConnection() {
782 return $GLOBALS['TYPO3_DB'];
783 }
784
785 }