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