[TASK] Add tool-function to strip PATH_site-part of paths
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / ShortcutFrameController.php
1 <?php
2 namespace TYPO3\CMS\Backend\Controller;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 1999-2013 Kasper Skårhøj (kasperYYYY@typo3.com)
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29
30 use TYPO3\CMS\Backend\Utility\BackendUtility;
31 use TYPO3\CMS\Backend\Utility\IconUtility;
32 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
33 use TYPO3\CMS\Core\Utility\GeneralUtility;
34 use TYPO3\CMS\Core\Utility\MathUtility;
35
36 /**
37 * Script Class for the shortcut frame, bottom frame of the backend frameset
38 *
39 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
40 */
41 class ShortcutFrameController {
42
43 // Internal, static: GPvar
44 /**
45 * @todo Define visibility
46 */
47 public $modName;
48
49 /**
50 * @todo Define visibility
51 */
52 public $M_modName;
53
54 /**
55 * @todo Define visibility
56 */
57 public $URL;
58
59 /**
60 * @todo Define visibility
61 */
62 public $editSC;
63
64 /**
65 * @todo Define visibility
66 */
67 public $deleteCategory;
68
69 /**
70 * @todo Define visibility
71 */
72 public $editName;
73
74 /**
75 * @todo Define visibility
76 */
77 public $editGroup;
78
79 /**
80 * @todo Define visibility
81 */
82 public $whichItem;
83
84 // Internal, static:
85 /**
86 * Object for backend modules, load modules-object
87 *
88 * @var \TYPO3\CMS\Backend\Module\ModuleLoader
89 * @todo Define visibility
90 */
91 public $loadModules;
92
93 protected $isAjaxCall;
94
95 /**
96 * Document template object
97 *
98 * @var \TYPO3\CMS\Backend\Template\DocumentTemplate
99 * @todo Define visibility
100 */
101 public $doc;
102
103 // Internal, dynamic:
104 // Accumulation of output HTML (string)
105 /**
106 * @todo Define visibility
107 */
108 public $content;
109
110 // Accumulation of table cells (array)
111 /**
112 * @todo Define visibility
113 */
114 public $lines;
115
116 // Flag for defining whether we are editing
117 /**
118 * @todo Define visibility
119 */
120 public $editLoaded;
121
122 // Can contain edit error message
123 /**
124 * @todo Define visibility
125 */
126 public $editError;
127
128 // Set to the record path of the record being edited.
129 /**
130 * @todo Define visibility
131 */
132 public $editPath;
133
134 // Holds the shortcut record when editing
135 /**
136 * @todo Define visibility
137 */
138 public $editSC_rec;
139
140 // Page record to be edited
141 /**
142 * @todo Define visibility
143 */
144 public $theEditRec;
145
146 // Page alias or id to be edited
147 /**
148 * @todo Define visibility
149 */
150 public $editPage;
151
152 // Select options.
153 /**
154 * @todo Define visibility
155 */
156 public $selOpt;
157
158 // Text to search for...
159 /**
160 * @todo Define visibility
161 */
162 public $searchFor;
163
164 // Labels of all groups. If value is 1, the system will try to find a label in the locallang array.
165 /**
166 * @todo Define visibility
167 */
168 public $groupLabels = array();
169
170 // Array with key 0/1 being table/uid of record to edit. Internally set.
171 /**
172 * @todo Define visibility
173 */
174 public $alternativeTableUid = array();
175
176 /**
177 * Constructor
178 */
179 public function __construct() {
180 $GLOBALS['SOBE'] = $this;
181 $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_misc.xlf');
182
183 $this->preinit();
184 }
185
186 /**
187 * Pre-initialization - setting input variables for storing shortcuts etc.
188 *
189 * @return void
190 */
191 protected function preinit() {
192 // Setting GPvars:
193 $this->isAjaxCall = (bool) GeneralUtility::_GP('ajax');
194 $this->modName = GeneralUtility::_GP('modName');
195 $this->M_modName = GeneralUtility::_GP('motherModName');
196 $this->URL = GeneralUtility::_GP('URL');
197 $this->editSC = GeneralUtility::_GP('editShortcut');
198 $this->deleteCategory = GeneralUtility::_GP('deleteCategory');
199 $this->editPage = GeneralUtility::_GP('editPage');
200 $this->changeWorkspace = GeneralUtility::_GP('changeWorkspace');
201 $this->changeWorkspacePreview = GeneralUtility::_GP('changeWorkspacePreview');
202 $this->editName = GeneralUtility::_GP('editName');
203 $this->editGroup = GeneralUtility::_GP('editGroup');
204 $this->whichItem = GeneralUtility::_GP('whichItem');
205 // Creating modules object
206 $this->loadModules = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Module\\ModuleLoader');
207 $this->loadModules->load($GLOBALS['TBE_MODULES']);
208 }
209
210 /**
211 * Adding shortcuts, editing shortcuts etc.
212 *
213 * @return void
214 */
215 public function preprocess() {
216 // Default description
217 $description = '';
218 $url = urldecode($this->URL);
219 $queryParts = parse_url($url);
220 // Lookup the title of this page and use it as default description
221 $page_id = $this->getLinkedPageId($url);
222 if (MathUtility::canBeInterpretedAsInteger($page_id)) {
223 if (preg_match('/\\&edit\\[(.*)\\]\\[(.*)\\]=edit/', $url, $matches)) {
224 // Edit record
225 // TODO: Set something useful
226 $description = '';
227 } else {
228 // Page listing
229 $pageRow = BackendUtility::getRecord('pages', $page_id);
230 if (count($pageRow)) {
231 // If $page_id is an integer, set the description to the title of that page
232 $description = $pageRow['title'];
233 }
234 }
235 } else {
236 if (preg_match('/\\/$/', $page_id)) {
237 // If $page_id is a string and ends with a slash, assume it is a fileadmin reference and set the description to the basename of that path
238 $description = basename($page_id);
239 }
240 }
241 // Adding a shortcut being set from another frame,
242 // but only if it's a relative URL (i.e. scheme part is not defined)
243 if ($this->modName && $this->URL && empty($queryParts['scheme'])) {
244 $fields_values = array(
245 'userid' => $GLOBALS['BE_USER']->user['uid'],
246 'module_name' => $this->modName . '|' . $this->M_modName,
247 'url' => $this->URL,
248 'description' => $description,
249 'sorting' => $GLOBALS['EXEC_TIME']
250 );
251 $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_be_shortcuts', $fields_values);
252 }
253 // Selection-clause for users - so users can deleted only their own shortcuts (except admins)
254 $addUSERWhere = !$GLOBALS['BE_USER']->isAdmin() ? ' AND userid=' . intval($GLOBALS['BE_USER']->user['uid']) : '';
255 // Deleting shortcuts:
256 if (strcmp($this->deleteCategory, '')) {
257 if (MathUtility::canBeInterpretedAsInteger($this->deleteCategory)) {
258 $GLOBALS['TYPO3_DB']->exec_DELETEquery('sys_be_shortcuts', 'sc_group=' . intval($this->deleteCategory) . $addUSERWhere);
259 }
260 }
261 // If other changes in post-vars:
262 if (is_array($_POST)) {
263 // Saving:
264 if (isset($_POST['_savedok_x']) || isset($_POST['_saveclosedok_x'])) {
265 $fields_values = array(
266 'description' => $this->editName,
267 'sc_group' => intval($this->editGroup)
268 );
269 if ($fields_values['sc_group'] < 0 && !$GLOBALS['BE_USER']->isAdmin()) {
270 $fields_values['sc_group'] = 0;
271 }
272 $GLOBALS['TYPO3_DB']->exec_UPDATEquery('sys_be_shortcuts', 'uid=' . intval($this->whichItem) . $addUSERWhere, $fields_values);
273 }
274 // If save without close, keep the session going...
275 if (isset($_POST['_savedok_x'])) {
276 $this->editSC = $this->whichItem;
277 }
278 // Deleting a single shortcut ?
279 if (isset($_POST['_deletedok_x'])) {
280 $GLOBALS['TYPO3_DB']->exec_DELETEquery('sys_be_shortcuts', 'uid=' . intval($this->whichItem) . $addUSERWhere);
281 // Just to have the checkbox set...
282 if (!$this->editSC) {
283 $this->editSC = -1;
284 }
285 }
286 }
287 }
288
289 /**
290 * Initialize (page output)
291 *
292 * @return void
293 */
294 public function init() {
295 $this->doc = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Template\\DocumentTemplate');
296 $this->doc->backPath = $GLOBALS['BACK_PATH'];
297 $this->doc->form = '<form action="alt_shortcut.php" name="shForm" method="post">';
298 $this->doc->divClass = 'typo3-shortcut';
299 $this->doc->JScode .= $this->doc->wrapScriptTags('
300 function jump(url,modName,mainModName) { //
301 // Clear information about which entry in nav. tree that might have been highlighted.
302 top.fsMod.navFrameHighlightedID = new Array();
303 if (top.content && top.content.nav_frame && top.content.nav_frame.refresh_nav) {
304 top.content.nav_frame.refresh_nav();
305 }
306
307 top.nextLoadModuleUrl = url;
308 top.goToModule(modName);
309 }
310 function editSh(uid) { //
311 window.location.href="alt_shortcut.php?editShortcut="+uid;
312 }
313 function submitEditPage(id) { //
314 window.location.href="alt_shortcut.php?editPage="+top.rawurlencodeAndRemoveSiteUrl(id);
315 }
316 function changeWorkspace(workspaceId) { //
317 window.location.href="alt_shortcut.php?changeWorkspace="+top.rawurlencodeAndRemoveSiteUrl(workspaceId);
318 }
319 function changeWorkspacePreview(newstate) { //
320 window.location.href="alt_shortcut.php?changeWorkspacePreview="+newstate;
321 }
322 function refreshShortcuts() {
323 window.location.href = document.URL;
324 }
325
326 ');
327 $this->content .= $this->doc->startPage('Shortcut frame');
328 }
329
330 /**
331 * Main function, creating content in the frame
332 *
333 * @return void
334 */
335 public function main() {
336 // By default, 5 groups are set
337 $this->groupLabels = array(
338 1 => 1,
339 2 => 1,
340 3 => 1,
341 4 => 1,
342 5 => 1
343 );
344 $bookmarkGroups = $GLOBALS['BE_USER']->getTSConfigProp('options.bookmarkGroups');
345 if (is_array($bookmarkGroups) && count($bookmarkGroups)) {
346 foreach ($bookmarkGroups as $k => $v) {
347 if (strcmp('', $v) && strcmp('0', $v)) {
348 $this->groupLabels[$k] = (string) $v;
349 } elseif ($GLOBALS['BE_USER']->isAdmin()) {
350 unset($this->groupLabels[$k]);
351 }
352 }
353 }
354 // List of global groups that will be loaded. All global groups have negative IDs.
355 $globalGroups = -100;
356 // Group -100 is kind of superglobal and can't be changed.
357 if (count($this->groupLabels)) {
358 $globalGroups .= ',' . implode(',', array_keys($this->groupLabels));
359 $globalGroups = str_replace(',', ',-', $globalGroups);
360 }
361 // Fetching shortcuts to display for this user:
362 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_be_shortcuts', '((userid=' . $GLOBALS['BE_USER']->user['uid'] . ' AND sc_group>=0) OR sc_group IN (' . $globalGroups . '))', '', 'sc_group,sorting');
363 // Init vars:
364 $this->lines = array();
365 $this->linesPre = array();
366 $this->editSC_rec = '';
367 $this->selOpt = array();
368 $formerGr = '';
369 // Traverse shortcuts
370 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
371 $mParts = explode('|', $row['module_name']);
372 $row['module_name'] = $mParts[0];
373 $row['M_module_name'] = $mParts[1];
374 $mParts = explode('_', $row['M_module_name'] ? $row['M_module_name'] : $row['module_name']);
375 $qParts = parse_url($row['url']);
376 if (!$GLOBALS['BE_USER']->isAdmin()) {
377 // Check for module access
378 if (!isset($GLOBALS['LANG']->moduleLabels['tabs_images'][(implode('_', $mParts) . '_tab')])) {
379 // Nice hack to check if the user has access to this module - otherwise the translation label would not have been loaded :-)
380 continue;
381 }
382 $page_id = $this->getLinkedPageId($row['url']);
383 if (MathUtility::canBeInterpretedAsInteger($page_id)) {
384 // Check for webmount access
385 if (!$GLOBALS['BE_USER']->isInWebMount($page_id)) {
386 continue;
387 }
388 // Check for record access
389 $pageRow = BackendUtility::getRecord('pages', $page_id);
390 if (!$GLOBALS['BE_USER']->doesUserHaveAccess($pageRow, ($perms = 1))) {
391 continue;
392 }
393 }
394 }
395 if ($this->editSC && $row['uid'] == $this->editSC) {
396 $this->editSC_rec = $row;
397 }
398 $sc_group = $row['sc_group'];
399 if ($sc_group && strcmp($formerGr, $sc_group)) {
400 if ($sc_group != -100) {
401 if ($this->groupLabels[abs($sc_group)] && strcmp('1', $this->groupLabels[abs($sc_group)])) {
402 $label = $this->groupLabels[abs($sc_group)];
403 } else {
404 $label = $GLOBALS['LANG']->getLL('shortcut_group_' . abs($sc_group), TRUE);
405 // Fallback label
406 if (!$label) {
407 $label = $GLOBALS['LANG']->getLL('shortcut_group', TRUE) . ' ' . abs($sc_group);
408 }
409 }
410 if ($sc_group >= 0) {
411 $onC = 'if (confirm(' . $GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->getLL('bookmark_delAllInCat')) . ')){window.location.href=\'alt_shortcut.php?deleteCategory=' . $sc_group . '\';}return false;';
412 $this->linesPre[] = '<td>&nbsp;</td><td class="bgColor5"><a href="#" onclick="' . htmlspecialchars($onC) . '" title="' . $GLOBALS['LANG']->getLL('bookmark_delAllInCat', TRUE) . '">' . $label . '</a></td>';
413 } else {
414 // Fallback label
415 $label = $GLOBALS['LANG']->getLL('bookmark_global', TRUE) . ': ' . ($label ? $label : abs($sc_group));
416 $this->lines[] = '<td>&nbsp;</td><td class="bgColor5">' . $label . '</td>';
417 }
418 unset($label);
419 }
420 }
421 $bgColorClass = $row['uid'] == $this->editSC ? 'bgColor5' : ($row['sc_group'] < 0 ? 'bgColor6' : 'bgColor4');
422 if ($row['description'] && $row['uid'] != $this->editSC) {
423 $label = $row['description'];
424 } else {
425 $label = GeneralUtility::fixed_lgd_cs(rawurldecode($qParts['query']), 150);
426 }
427 $titleA = $this->itemLabel($label, $row['module_name'], $row['M_module_name']);
428 $editSH = $row['sc_group'] >= 0 || $GLOBALS['BE_USER']->isAdmin() ? 'editSh(' . intval($row['uid']) . ');' : 'alert(\'' . $GLOBALS['LANG']->getLL('bookmark_onlyAdmin') . '\')';
429 $jumpSC = 'jump(unescape(\'' . rawurlencode($row['url']) . '\'),\'' . implode('_', $mParts) . '\',\'' . $mParts[0] . '\');';
430 $onC = 'if (document.shForm.editShortcut_check && document.shForm.editShortcut_check.checked){' . $editSH . '}else{' . $jumpSC . '}return false;';
431 // user defined groups show up first
432 if ($sc_group >= 0) {
433 $this->linesPre[] = '<td class="' . $bgColorClass . '"><a href="#" onclick="' . htmlspecialchars($onC) . '"><img src="' . $this->getIcon($row['module_name']) . '" title="' . htmlspecialchars($titleA) . '" alt="" /></a></td>';
434 } else {
435 $this->lines[] = '<td class="' . $bgColorClass . '"><a href="#" onclick="' . htmlspecialchars($onC) . '"><img src="' . $this->getIcon($row['module_name']) . '" title="' . htmlspecialchars($titleA) . '" alt="" /></a></td>';
436 }
437 if (trim($row['description'])) {
438 $kkey = strtolower(substr($row['description'], 0, 20)) . '_' . $row['uid'];
439 $this->selOpt[$kkey] = '<option value="' . htmlspecialchars($jumpSC) . '">' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($row['description'], 50)) . '</option>';
440 }
441 $formerGr = $row['sc_group'];
442 }
443 ksort($this->selOpt);
444 array_unshift($this->selOpt, '<option>[' . $GLOBALS['LANG']->getLL('bookmark_selSC', TRUE) . ']</option>');
445 $this->editLoadedFunc();
446 $this->editPageIdFunc();
447 if (!$this->editLoaded && ExtensionManagementUtility::isLoaded('cms')) {
448 $editIdCode = '<td nowrap="nowrap">' . $GLOBALS['LANG']->getLL('bookmark_editID', TRUE) . ': <input type="text" value="' . ($this->editError ? htmlspecialchars($this->editPage) : '') . '" name="editPage"' . $this->doc->formWidth(15) . ' onchange="submitEditPage(this.value);" />' . ($this->editError ? '&nbsp;<strong><span class="typo3-red">' . htmlspecialchars($this->editError) . '</span></strong>' : '') . (is_array($this->theEditRec) ? '&nbsp;<strong>' . $GLOBALS['LANG']->getLL('bookmark_loadEdit', TRUE) . ' \'' . BackendUtility::getRecordTitle('pages', $this->theEditRec, TRUE) . '\'</strong> (' . htmlspecialchars($this->editPath) . ')' : '') . ($this->searchFor ? '&nbsp;' . $GLOBALS['LANG']->getLL('bookmark_searchFor', TRUE) . ' <strong>\'' . htmlspecialchars($this->searchFor) . '\'</strong>' : '') . '</td>';
449 } else {
450 $editIdCode = '';
451 }
452 // Adding CSH:
453 $editIdCode .= '<td>&nbsp;' . BackendUtility::cshItem('xMOD_csh_corebe', 'bookmarks', $GLOBALS['BACK_PATH'], '', TRUE) . '</td>';
454 // Compile it all:
455 $this->content .= '
456
457 <table border="0" cellpadding="0" cellspacing="0" width="99%">
458 <tr>
459 <td>
460 <!--
461 Shortcut Display Table:
462 -->
463 <table border="0" cellpadding="0" cellspacing="2" id="typo3-shortcuts">
464 <tr>
465 ';
466 if ($GLOBALS['BE_USER']->getTSConfigVal('options.enableBookmarks')) {
467 $this->content .= implode('
468 ', $this->lines);
469 }
470 $this->content .= $editIdCode . '
471 </tr>
472 </table>
473 </td>
474 <td align="right">';
475 if ($this->hasWorkspaceAccess()) {
476 $this->content .= $this->workspaceSelector() . BackendUtility::cshItem('xMOD_csh_corebe', 'workspaceSelector', $GLOBALS['BACK_PATH'], '', TRUE);
477 }
478 $this->content .= '
479 </td>
480 </tr>
481 </table>
482 ';
483 // Launch Edit page:
484 if ($this->theEditRec['uid']) {
485 $this->content .= $this->doc->wrapScriptTags('top.loadEditId(' . $this->theEditRec['uid'] . ');');
486 }
487 // Load alternative table/uid into editing form.
488 if (count($this->alternativeTableUid) == 2 && isset($GLOBALS['TCA'][$this->alternativeTableUid[0]]) && MathUtility::canBeInterpretedAsInteger($this->alternativeTableUid[1])) {
489 $JSaction = BackendUtility::editOnClick('&edit[' . $this->alternativeTableUid[0] . '][' . $this->alternativeTableUid[1] . ']=edit', '', 'dummy.php');
490 $this->content .= $this->doc->wrapScriptTags('function editArbitraryElement() { top.content.' . $JSaction . '; } editArbitraryElement();');
491 }
492 // Load search for something.
493 if ($this->searchFor) {
494 $urlParameters = array();
495 $urlParameters['id'] = intval($GLOBALS['WEBMOUNTS'][0]);
496 $urlParameters['search_field'] = $this->searchFor;
497 $urlParameters['search_levels'] = 4;
498 $this->content .= $this->doc->wrapScriptTags('jump(unescape("' . rawurlencode(BackendUtility::getModuleUrl('web_list', $urlParameters, '')) . '"), "web_list", "web");');
499 }
500 }
501
502 /**
503 * Creates lines for the editing form.
504 *
505 * @return void
506 * @todo Define visibility
507 */
508 public function editLoadedFunc() {
509 $this->editLoaded = 0;
510 // sc_group numbers below 0 requires admin to edit those. sc_group
511 // numbers above zero must always be owned by the user himself.
512 if (is_array($this->editSC_rec) && ($this->editSC_rec['sc_group'] >= 0 || $GLOBALS['BE_USER']->isAdmin())) {
513 $this->editLoaded = 1;
514 $opt = array();
515 $opt[] = '<option value="0"></option>';
516 foreach ($this->groupLabels as $k => $v) {
517 if ($v && strcmp('1', $v)) {
518 $label = $v;
519 } else {
520 $label = $GLOBALS['LANG']->getLL('bookmark_group_' . $k, TRUE);
521 // Fallback label
522 if (!$label) {
523 $label = $GLOBALS['LANG']->getLL('bookmark_group', TRUE) . ' ' . $k;
524 }
525 }
526 $opt[] = '<option value="' . $k . '"' . (!strcmp($this->editSC_rec['sc_group'], $k) ? ' selected="selected"' : '') . '>' . $label . '</option>';
527 }
528 if ($GLOBALS['BE_USER']->isAdmin()) {
529 foreach ($this->groupLabels as $k => $v) {
530 if ($v && strcmp('1', $v)) {
531 $label = $v;
532 } else {
533 $label = $GLOBALS['LANG']->getLL('bookmark_group_' . $k, TRUE);
534 // Fallback label
535 if (!$label) {
536 $label = $GLOBALS['LANG']->getLL('bookmark_group', TRUE) . ' ' . $k;
537 }
538 }
539 // Add a prefix for global groups
540 $label = $GLOBALS['LANG']->getLL('bookmark_global', TRUE) . ': ' . $label;
541 $opt[] = '<option value="-' . $k . '"' . (!strcmp($this->editSC_rec['sc_group'], ('-' . $k)) ? ' selected="selected"' : '') . '>' . $label . '</option>';
542 }
543 $opt[] = '<option value="-100"' . (!strcmp($this->editSC_rec['sc_group'], '-100') ? ' selected="selected"' : '') . '>' . $GLOBALS['LANG']->getLL('bookmark_global', TRUE) . ': ' . $GLOBALS['LANG']->getLL('bookmark_all', TRUE) . '</option>';
544 }
545 // border="0" hspace="2" width="21" height="16" - not XHTML compliant in <input type="image" ...>
546 $manageForm = '
547
548 <!--
549 Shortcut Editing Form:
550 -->
551 <table border="0" cellpadding="0" cellspacing="0" id="typo3-shortcuts-editing">
552 <tr>
553 <td>&nbsp;&nbsp;</td>
554 <td><input type="image" class="c-inputButton" name="_savedok"' . IconUtility::skinImg($this->doc->backPath, 'gfx/savedok.gif', '') . ' title="' . $GLOBALS['LANG']->getLL('shortcut_save', TRUE) . '" /></td>
555 <td><input type="image" class="c-inputButton" name="_saveclosedok"' . IconUtility::skinImg($this->doc->backPath, 'gfx/saveandclosedok.gif', '') . ' title="' . $GLOBALS['LANG']->getLL('bookmark_saveClose', TRUE) . '" /></td>
556 <td><input type="image" class="c-inputButton" name="_closedok"' . IconUtility::skinImg($this->doc->backPath, 'gfx/closedok.gif', '') . ' title="' . $GLOBALS['LANG']->getLL('bookmark_close', TRUE) . '" /></td>
557 <td><input type="image" class="c-inputButton" name="_deletedok"' . IconUtility::skinImg($this->doc->backPath, 'gfx/deletedok.gif', '') . ' title="' . $GLOBALS['LANG']->getLL('bookmark_delete', TRUE) . '" /></td>
558 <td><input name="editName" type="text" value="' . htmlspecialchars($this->editSC_rec['description']) . '"' . $this->doc->formWidth(15) . ' /></td>
559 <td><select name="editGroup">' . implode('', $opt) . '</select></td>
560 </tr>
561 </table>
562 <input type="hidden" name="whichItem" value="' . $this->editSC_rec['uid'] . '" />
563
564 ';
565 } else {
566 $manageForm = '';
567 }
568 if (!$this->editLoaded && count($this->selOpt) > 1) {
569 $this->lines[] = '<td>&nbsp;</td>';
570 $this->lines[] = '<td><select name="_selSC" onchange="eval(this.options[this.selectedIndex].value);this.selectedIndex=0;">' . implode('', $this->selOpt) . '</select></td>';
571 }
572 // $this->linesPre contains elements with sc_group>=0
573 $this->lines = array_merge($this->linesPre, $this->lines);
574 if (count($this->lines)) {
575 if (!$GLOBALS['BE_USER']->getTSConfigVal('options.mayNotCreateEditBookmarks')) {
576 $this->lines = array_merge(array(
577 '<td><input type="checkbox" id="editShortcut_check" name="editShortcut_check" value="1"' . ($this->editSC ? ' checked="checked"' : '') . ' />' . ' <label for="editShortcut_check">' . $GLOBALS['LANG']->getLL('bookmark_edit', TRUE) . '</label>&nbsp;</td>'
578 ), $this->lines);
579 $this->lines[] = '<td>' . $manageForm . '</td>';
580 }
581 $this->lines[] = '<td><img src="clear.gif" width="10" height="1" alt="" /></td>';
582 }
583 }
584
585 /**
586 * If "editPage" value is sent to script and it points to an accessible page, the internal var $this->theEditRec is set to the page record which should be loaded.
587 * Returns void
588 *
589 * @return void
590 * @todo Define visibility
591 */
592 public function editPageIdFunc() {
593 if (!ExtensionManagementUtility::isLoaded('cms')) {
594 return;
595 }
596 // EDIT page:
597 $this->editPage = trim($GLOBALS['LANG']->csConvObj->conv_case($GLOBALS['LANG']->charSet, $this->editPage, 'toLower'));
598 $this->editError = '';
599 $this->theEditRec = '';
600 $this->searchFor = '';
601 if ($this->editPage) {
602 // First, test alternative value consisting of [table]:[uid] and if not found, proceed with traditional page ID resolve:
603 $this->alternativeTableUid = explode(':', $this->editPage);
604 // We restrict it to admins only just because I'm not really sure if alt_doc.php properly
605 // checks permissions of passed records for editing. If alt_doc.php does that, then we can remove this.
606 if (!(count($this->alternativeTableUid) == 2 && $GLOBALS['BE_USER']->isAdmin())) {
607 $where = ' AND (' . $GLOBALS['BE_USER']->getPagePermsClause(2) . ' OR ' . $GLOBALS['BE_USER']->getPagePermsClause(16) . ')';
608 if (MathUtility::canBeInterpretedAsInteger($this->editPage)) {
609 $this->theEditRec = BackendUtility::getRecordWSOL('pages', $this->editPage, '*', $where);
610 } else {
611 $records = BackendUtility::getRecordsByField('pages', 'alias', $this->editPage, $where);
612 if (is_array($records)) {
613 $this->theEditRec = reset($records);
614 BackendUtility::workspaceOL('pages', $this->theEditRec);
615 }
616 }
617 if (!is_array($this->theEditRec)) {
618 unset($this->theEditRec);
619 $this->searchFor = $this->editPage;
620 } elseif (!$GLOBALS['BE_USER']->isInWebMount($this->theEditRec['uid'])) {
621 unset($this->theEditRec);
622 $this->editError = $GLOBALS['LANG']->getLL('bookmark_notEditable');
623 } else {
624 // Visual path set:
625 $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
626 $this->editPath = BackendUtility::getRecordPath($this->theEditRec['pid'], $perms_clause, 30);
627 if (!$GLOBALS['BE_USER']->getTSConfigVal('options.bookmark_onEditId_dontSetPageTree')) {
628 $bookmarkKeepExpanded = $GLOBALS['BE_USER']->getTSConfigVal('options.bookmark_onEditId_keepExistingExpanded');
629 // Expanding page tree:
630 BackendUtility::openPageTree($this->theEditRec['pid'], !$bookmarkKeepExpanded);
631 }
632 }
633 }
634 }
635 }
636
637 /**
638 * Outputting the accumulated content to screen
639 *
640 * @return void
641 */
642 public function printContent() {
643 $content = '';
644 $this->content .= $this->doc->endPage();
645 $this->content = $this->doc->insertStylesAndJS($this->content);
646 if ($this->editPage && $this->isAjaxCall) {
647 $data = array();
648 // edit page
649 if ($this->theEditRec['uid']) {
650 $data['type'] = 'page';
651 $data['editRecord'] = $this->theEditRec['uid'];
652 }
653 // edit alternative table/uid
654 if (count($this->alternativeTableUid) == 2 && isset($GLOBALS['TCA'][$this->alternativeTableUid[0]]) && MathUtility::canBeInterpretedAsInteger($this->alternativeTableUid[1])) {
655 $data['type'] = 'alternative';
656 $data['alternativeTable'] = $this->alternativeTableUid[0];
657 $data['alternativeUid'] = $this->alternativeTableUid[1];
658 }
659 // search for something else
660 if ($this->searchFor) {
661 $data['type'] = 'search';
662 $data['firstMountPoint'] = intval($GLOBALS['WEBMOUNTS'][0]);
663 $data['searchFor'] = $this->searchFor;
664 }
665 $content = json_encode($data);
666 header('Content-type: application/json; charset=utf-8');
667 header('X-JSON: ' . $content);
668 } else {
669 $content = $this->content;
670 }
671 echo $content;
672 }
673
674 /***************************
675 *
676 * WORKSPACE FUNCTIONS:
677 *
678 ***************************/
679 /**
680 * Create selector for workspaces and change workspace if command is given to do that.
681 *
682 * @return string HTML
683 * @todo Define visibility
684 */
685 public function workspaceSelector() {
686 // Changing workspace and if so, reloading entire backend:
687 if (strlen($this->changeWorkspace)) {
688 $GLOBALS['BE_USER']->setWorkspace($this->changeWorkspace);
689 return $this->doc->wrapScriptTags('top.location.href="' . BackendUtility::getBackendScript() . '";');
690 }
691 // Changing workspace and if so, reloading entire backend:
692 if (strlen($this->changeWorkspacePreview)) {
693 $GLOBALS['BE_USER']->setWorkspacePreview($this->changeWorkspacePreview);
694 }
695 // Create options array:
696 $options = array();
697 if ($GLOBALS['BE_USER']->checkWorkspace(array('uid' => 0))) {
698 $options[0] = '[' . $GLOBALS['LANG']->getLL('bookmark_onlineWS') . ']';
699 }
700 if ($GLOBALS['BE_USER']->checkWorkspace(array('uid' => -1))) {
701 $options[-1] = '[' . $GLOBALS['LANG']->getLL('bookmark_offlineWS') . ']';
702 }
703 // Add custom workspaces (selecting all, filtering by BE_USER check):
704 if (ExtensionManagementUtility::isLoaded('workspaces')) {
705 $workspaces = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,title,adminusers,members,reviewers', 'sys_workspace', 'pid=0' . BackendUtility::deleteClause('sys_workspace'), '', 'title');
706 if (count($workspaces)) {
707 foreach ($workspaces as $rec) {
708 if ($GLOBALS['BE_USER']->checkWorkspace($rec)) {
709 $options[$rec['uid']] = $rec['uid'] . ': ' . $rec['title'];
710 }
711 }
712 }
713 }
714 // Build selector box:
715 if (count($options)) {
716 foreach ($options as $value => $label) {
717 $selected = (int) $GLOBALS['BE_USER']->workspace === $value ? ' selected="selected"' : '';
718 $options[$value] = '<option value="' . htmlspecialchars($value) . '"' . $selected . '>' . htmlspecialchars($label) . '</option>';
719 }
720 } else {
721 $options[] = '<option value="-99">' . $GLOBALS['LANG']->getLL('bookmark_noWSfound', TRUE) . '</option>';
722 }
723 $selector = '';
724 // Preview:
725 if ($GLOBALS['BE_USER']->workspace !== 0) {
726 $selector .= '<label for="workspacePreview">Frontend Preview:</label> <input type="checkbox" name="workspacePreview" id="workspacePreview" onclick="changeWorkspacePreview(' . ($GLOBALS['BE_USER']->user['workspace_preview'] ? 0 : 1) . ')"; ' . ($GLOBALS['BE_USER']->user['workspace_preview'] ? 'checked="checked"' : '') . '/>&nbsp;';
727 }
728 $selector .= '<a href="mod/user/ws/index.php" target="content">' . IconUtility::getSpriteIconForRecord('sys_workspace', array()) . '</a>';
729 if (count($options) > 1) {
730 $selector .= '<select name="_workspaceSelector" onchange="changeWorkspace(this.options[this.selectedIndex].value);">' . implode('', $options) . '</select>';
731 }
732 return $selector;
733 }
734
735 /***************************
736 *
737 * OTHER FUNCTIONS:
738 *
739 ***************************/
740 /**
741 * Returns relative filename for icon.
742 *
743 * @param string $Ifilename Absolute filename of the icon
744 * @param string $backPath Backpath string to prepend the icon after made relative
745 * @return void
746 * @todo Define visibility
747 */
748 public function mIconFilename($Ifilename, $backPath) {
749 // Change icon of fileadmin references - otherwise it doesn't differ with Web->List
750 $Ifilename = str_replace('mod/file/list/list.gif', 'mod/file/file.gif', $Ifilename);
751 if (GeneralUtility::isAbsPath($Ifilename)) {
752 $Ifilename = '../' . \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix($Ifilename);
753 }
754 return $backPath . $Ifilename;
755 }
756
757 /**
758 * Returns icon for shortcut display
759 *
760 * @param string $modName Backend module name
761 * @return string Icon file name
762 * @todo Define visibility
763 */
764 public function getIcon($modName) {
765 if ($GLOBALS['LANG']->moduleLabels['tabs_images'][$modName . '_tab']) {
766 $icon = $this->mIconFilename($GLOBALS['LANG']->moduleLabels['tabs_images'][$modName . '_tab'], '');
767 } elseif ($modName == 'xMOD_alt_doc.php') {
768 $icon = 'gfx/edit2.gif';
769 } elseif ($modName == 'xMOD_file_edit.php') {
770 $icon = 'gfx/edit_file.gif';
771 } elseif ($modName == 'xMOD_wizard_rte.php') {
772 $icon = 'gfx/edit_rtewiz.gif';
773 } else {
774 $icon = 'gfx/dummy_module.gif';
775 }
776 return $icon;
777 }
778
779 /**
780 * Returns title-label for icon
781 *
782 * @param string $inlabel In-label
783 * @param string $modName Backend module name (key)
784 * @param string $M_modName Backend module label (user defined?)
785 * @return string Label for the shortcut item
786 * @todo Define visibility
787 */
788 public function itemLabel($inlabel, $modName, $M_modName = '') {
789 if (substr($modName, 0, 5) == 'xMOD_') {
790 $label = substr($modName, 5);
791 } else {
792 $split = explode('_', $modName);
793 $label = $GLOBALS['LANG']->moduleLabels['tabs'][$split[0] . '_tab'];
794 if (count($split) > 1) {
795 $label .= '>' . $GLOBALS['LANG']->moduleLabels['tabs'][($modName . '_tab')];
796 }
797 }
798 if ($M_modName) {
799 $label .= ' (' . $M_modName . ')';
800 }
801 $label .= ': ' . $inlabel;
802 return $label;
803 }
804
805 /**
806 * Return the ID of the page in the URL if found.
807 *
808 * @param string $url The URL of the current shortcut link
809 * @return string If a page ID was found, it is returned. Otherwise: 0
810 * @todo Define visibility
811 */
812 public function getLinkedPageId($url) {
813 return preg_replace('/.*[\\?&]id=([^&]+).*/', '$1', $url);
814 }
815
816 /**
817 * Checks if user has access to Workspace module.
818 *
819 * @return boolean Returns TRUE if user has access to workspace module.
820 * @todo Define visibility
821 */
822 public function hasWorkspaceAccess() {
823 $MCONF = array();
824 include 'mod/user/ws/conf.php';
825 return $GLOBALS['BE_USER']->modAccess(array('name' => 'user', 'access' => 'user,group'), FALSE) && $GLOBALS['BE_USER']->modAccess($MCONF, FALSE);
826 }
827
828 }