[FEATURE] Make use of File Abstraction Layer in Backend
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_clipboard.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Contains class for TYPO3 clipboard for records and files
29 *
30 * Revised for TYPO3 3.6 July/2003 by Kasper Skårhøj
31 * XHTML compliant
32 *
33 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
34 */
35
36
37 /**
38 * TYPO3 clipboard for records and files
39 *
40 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
41 * @package TYPO3
42 * @subpackage t3lib
43 */
44 class t3lib_clipboard {
45 var $numberTabs = 3;
46
47 /**
48 * Clipboard data kept here
49 *
50 * Keys:
51 * 'normal'
52 * 'tab_[x]' where x is >=1 and denotes the pad-number
53 * \ 'mode' : 'copy' means copy-mode, default = moving ('cut')
54 * \ 'el' : Array of elements:
55 * DB: keys = '[tablename]|[uid]' eg. 'tt_content:123'
56 * DB: values = 1 (basically insignificant)
57 * FILE: keys = '_FILE|[shortmd5 of path]' eg. '_FILE|9ebc7e5c74'
58 * FILE: values = The full filepath, eg. '/www/htdocs/typo3/32/dummy/fileadmin/sem1_3_examples/alternative_index.php' or 'C:/www/htdocs/typo3/32/dummy/fileadmin/sem1_3_examples/alternative_index.php'
59 *
60 * 'current' pointer to current tab (among the above...)
61 * '_setThumb' boolean: If set, file thumbnails are shown.
62 *
63 * The virtual tablename '_FILE' will always indicate files/folders. When checking for elements from eg. 'all tables' (by using an empty string) '_FILE' entries are excluded (so in effect only DB elements are counted)
64 *
65 */
66 var $clipData = array();
67
68 var $changed = 0;
69 var $current = '';
70 var $backPath = '';
71 var $lockToNormal = 0;
72 var $fileMode = 0; // If set, clipboard is displaying files.
73
74
75 /*****************************************
76 *
77 * Initialize
78 *
79 ****************************************/
80
81 /**
82 * Initialize the clipboard from the be_user session
83 *
84 * @return void
85 */
86 function initializeClipboard() {
87 $this->backPath = $GLOBALS['BACK_PATH'];
88
89 // Get data
90 $clipData = $GLOBALS['BE_USER']->getModuleData('clipboard', $GLOBALS['BE_USER']->getTSConfigVal('options.saveClipboard') ? '' : 'ses');
91
92 // NumberTabs
93 $clNP = $GLOBALS['BE_USER']->getTSConfigVal('options.clipboardNumberPads');
94 if (t3lib_utility_Math::canBeInterpretedAsInteger($clNP) && $clNP >= 0) {
95 $this->numberTabs = t3lib_utility_Math::forceIntegerInRange($clNP, 0, 20);
96 }
97
98 // Resets/reinstates the clipboard pads
99 $this->clipData['normal'] = is_array($clipData['normal']) ? $clipData['normal'] : array();
100 for ($a = 1; $a <= $this->numberTabs; $a++) {
101 $this->clipData['tab_' . $a] = is_array($clipData['tab_' . $a]) ? $clipData['tab_' . $a] : array();
102 }
103
104 // Setting the current pad pointer ($this->current) and _setThumb (which determines whether or not do show file thumbnails)
105 $this->clipData['current'] = $this->current = isset($this->clipData[$clipData['current']]) ? $clipData['current'] : 'normal';
106 $this->clipData['_setThumb'] = $clipData['_setThumb'];
107 }
108
109 /**
110 * Call this method after initialization if you want to lock the clipboard to operate on the normal pad only. Trying to switch pad through ->setCmd will not work
111 * This is used by the clickmenu since it only allows operation on single elements at a time (that is the "normal" pad)
112 *
113 * @return void
114 */
115 function lockToNormal() {
116 $this->lockToNormal = 1;
117 $this->current = 'normal';
118 }
119
120 /**
121 * The array $cmd may hold various keys which notes some action to take.
122 * Normally perform only one action at a time.
123 * In scripts like db_list.php / file_list.php the GET-var CB is used to control the clipboard.
124 *
125 * Selecting / Deselecting elements
126 * Array $cmd['el'] has keys = element-ident, value = element value (see description of clipData array in header)
127 * Selecting elements for 'copy' should be done by simultaneously setting setCopyMode.
128 *
129 * @param array Array of actions, see function description
130 * @return void
131 */
132 function setCmd($cmd) {
133 if (is_array($cmd['el'])) {
134 foreach ($cmd['el'] as $k => $v) {
135 if ($this->current == 'normal') {
136 unset($this->clipData['normal']);
137 }
138 if ($v) {
139 $this->clipData[$this->current]['el'][$k] = $v;
140 } else {
141 $this->removeElement($k);
142 }
143 $this->changed = 1;
144 }
145 }
146 // Change clipboard pad (if not locked to normal)
147 if ($cmd['setP']) {
148 $this->setCurrentPad($cmd['setP']);
149 }
150 // Remove element (value = item ident: DB; '[tablename]|[uid]' FILE: '_FILE|[shortmd5 hash of path]'
151 if ($cmd['remove']) {
152 $this->removeElement($cmd['remove']);
153 $this->changed = 1;
154 }
155 // Remove all on current pad (value = pad-ident)
156 if ($cmd['removeAll']) {
157 $this->clipData[$cmd['removeAll']] = array();
158 $this->changed = 1;
159 }
160 // Set copy mode of the tab
161 if (isset($cmd['setCopyMode'])) {
162 $this->clipData[$this->current]['mode'] = $this->isElements() ? ($cmd['setCopyMode'] ? 'copy' : '') : '';
163 $this->changed = 1;
164 }
165 // Toggle thumbnail display for files on/off
166 if (isset($cmd['setThumb'])) {
167 $this->clipData['_setThumb'] = $cmd['setThumb'];
168 $this->changed = 1;
169 }
170 }
171
172 /**
173 * Setting the current pad on clipboard
174 *
175 * @param string Key in the array $this->clipData
176 * @return void
177 */
178 function setCurrentPad($padIdent) {
179 // Change clipboard pad (if not locked to normal)
180 if (!$this->lockToNormal && $this->current != $padIdent) {
181 if (isset($this->clipData[$padIdent])) {
182 $this->clipData['current'] = $this->current = $padIdent;
183 }
184 if ($this->current != 'normal' || !$this->isElements()) {
185 $this->clipData[$this->current]['mode'] = '';
186 } // Setting mode to default (move) if no items on it or if not 'normal'
187 $this->changed = 1;
188 }
189 }
190
191 /**
192 * Call this after initialization and setCmd in order to save the clipboard to the user session.
193 * The function will check if the internal flag ->changed has been set and if so, save the clipboard. Else not.
194 *
195 * @return void
196 */
197 function endClipboard() {
198 if ($this->changed) {
199 $this->saveClipboard();
200 }
201 $this->changed = 0;
202 }
203
204 /**
205 * Cleans up an incoming element array $CBarr (Array selecting/deselecting elements)
206 *
207 * @param array Element array from outside ("key" => "selected/deselected")
208 * @param string $table is the 'table which is allowed'. Must be set.
209 * @param boolean $removeDeselected can be set in order to remove entries which are marked for deselection.
210 * @return array Processed input $CBarr
211 */
212 function cleanUpCBC($CBarr, $table, $removeDeselected = 0) {
213 if (is_array($CBarr)) {
214 foreach ($CBarr as $k => $v) {
215 $p = explode('|', $k);
216 if ((string) $p[0] != (string) $table || ($removeDeselected && !$v)) {
217 unset($CBarr[$k]);
218 }
219 }
220 }
221 return $CBarr;
222 }
223
224
225 /*****************************************
226 *
227 * Clipboard HTML renderings
228 *
229 ****************************************/
230
231 /**
232 * Prints the clipboard
233 *
234 * @return string HTML output
235 */
236 function printClipboard() {
237 $out = array();
238 $elCount = count($this->elFromTable($this->fileMode ? '_FILE' : ''));
239
240 // Upper header
241 $out[] = '
242 <tr class="t3-row-header">
243 <td colspan="3">' . t3lib_BEfunc::wrapInHelp('xMOD_csh_corebe', 'list_clipboard', $this->clLabel('clipboard', 'buttons')) . '</td>
244 </tr>';
245
246 // Button/menu header:
247 $thumb_url = t3lib_div::linkThisScript(array('CB' => array('setThumb' => $this->clipData['_setThumb'] ? 0 : 1)));
248 $rmall_url = t3lib_div::linkThisScript(array('CB' => array('removeAll' => $this->current)));
249
250 // Copymode Selector menu
251 $copymode_url = t3lib_div::linkThisScript();
252 $moveLabel = htmlspecialchars($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.php:moveElements'));
253 $copyLabel = htmlspecialchars($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.php:copyElements'));
254 $opt = array();
255 $opt[] = '<option style="padding-left: 20px; background-image: url(\'' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/clip_cut.gif', '', 1) . '\'); background-repeat: no-repeat;" value="" ' . (($this->currentMode() == 'copy') ? '' : 'selected="selected"') . '>' . $moveLabel . '</option>';
256 $opt[] = '<option style="padding-left: 20px; background-image: url(\'' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/clip_copy.gif', '', 1) . '\'); background-repeat: no-repeat;" value="1" ' . (($this->currentMode() == 'copy') ? 'selected="selected"' : '') . '>' . $copyLabel . '</option>';
257
258 $copymode_selector = ' <select name="CB[setCopyMode]" onchange="this.form.method=\'POST\'; this.form.action=\'' . htmlspecialchars($copymode_url . '&CB[setCopyMode]=') . '\'+(this.options[this.selectedIndex].value); this.form.submit(); return true;" >' . implode('', $opt) . '</select>';
259
260 // Selector menu + clear button
261 $opt = array();
262 $opt[] = '<option value="" selected="selected">' . $this->clLabel('menu', 'rm') . '</option>';
263 // Import / Export link:
264 if ($elCount && t3lib_extMgm::isLoaded('impexp')) {
265 $opt[] = '<option value="' . htmlspecialchars("window.location.href='" . $this->backPath . t3lib_extMgm::extRelPath('impexp') . 'app/index.php' . $this->exportClipElementParameters() . '\';') . '">' . $this->clLabel('export', 'rm') . '</option>';
266 }
267 // Edit:
268 if (!$this->fileMode && $elCount) {
269 $opt[] = '<option value="' . htmlspecialchars("window.location.href='" . $this->editUrl() . "&returnUrl='+top.rawurlencode(window.location.href);") . '">' . $this->clLabel('edit', 'rm') . '</option>';
270 }
271 // Delete:
272 if ($elCount) {
273 if ($GLOBALS['BE_USER']->jsConfirmation(4)) {
274 $js = "
275 if(confirm(" . $GLOBALS['LANG']->JScharCode(sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:mess.deleteClip'), $elCount)) . ")){
276 window.location.href='" . $this->deleteUrl(0, $this->fileMode ? 1 : 0) . "&redirect='+top.rawurlencode(window.location.href);
277 }
278 ";
279 } else {
280 $js = " window.location.href='" . $this->deleteUrl(0, $this->fileMode ? 1 : 0) . "&redirect='+top.rawurlencode(window.location.href); ";
281 }
282 $opt[] = '<option value="' . htmlspecialchars($js) . '">' . $this->clLabel('delete', 'rm') . '</option>';
283 }
284 $selector_menu = '<select name="_clipMenu" onchange="eval(this.options[this.selectedIndex].value);this.selectedIndex=0;">' . implode('', $opt) . '</select>';
285
286 $out[] = '
287 <tr class="typo3-clipboard-head">
288 <td nowrap="nowrap">' .
289 '<a href="' . htmlspecialchars($thumb_url) . '#clip_head">' .
290 '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/thumb_' . ($this->clipData['_setThumb'] ? 's' : 'n') . '.gif', 'width="21" height="16"') . ' vspace="2" border="0" title="' . $this->clLabel('thumbmode_clip') . '" alt="" />' .
291 '</a>' .
292 '</td>
293 <td width="95%" nowrap="nowrap">' .
294 $copymode_selector . ' ' .
295 $selector_menu .
296 '</td>
297 <td>' .
298 '<a href="' . htmlspecialchars($rmall_url) . '#clip_head">' .
299 t3lib_iconWorks::getSpriteIcon('actions-document-close', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:buttons.clear', TRUE))) .
300 '</a></td>
301 </tr>';
302
303
304 // Print header and content for the NORMAL tab:
305 $out[] = '
306 <tr class="bgColor5">
307 <td colspan="3"><a href="' . htmlspecialchars(t3lib_div::linkThisScript(array('CB' => array('setP' => 'normal')))) . '#clip_head">' .
308 t3lib_iconWorks::getSpriteIcon('actions-view-table-' . (($this->current == 'normal') ? 'collapse' : 'expand')) .
309 $this->padTitleWrap('Normal', 'normal') .
310 '</a></td>
311 </tr>';
312 if ($this->current == 'normal') {
313 $out = array_merge($out, $this->printContentFromTab('normal'));
314 }
315
316 // Print header and content for the NUMERIC tabs:
317 for ($a = 1; $a <= $this->numberTabs; $a++) {
318 $out[] = '
319 <tr class="bgColor5">
320 <td colspan="3"><a href="' . htmlspecialchars(t3lib_div::linkThisScript(array('CB' => array('setP' => 'tab_' . $a)))) . '#clip_head">' .
321 t3lib_iconWorks::getSpriteIcon('actions-view-table-' . (($this->current == 'tab_' . $a) ? 'collapse' : 'expand')) .
322 $this->padTitleWrap($this->clLabel('cliptabs') . $a, 'tab_' . $a) .
323 '</a></td>
324 </tr>';
325 if ($this->current == 'tab_' . $a) {
326 $out = array_merge($out, $this->printContentFromTab('tab_' . $a));
327 }
328 }
329
330 // Wrap accumulated rows in a table:
331 $output = '<a name="clip_head"></a>
332
333 <!--
334 TYPO3 Clipboard:
335 -->
336 <table cellpadding="0" cellspacing="1" border="0" width="290" id="typo3-clipboard">
337 ' . implode('', $out) . '
338 </table>';
339
340 // Wrap in form tag:
341 $output = '<form action="">' . $output . '</form>';
342
343 // Return the accumulated content:
344 return $output;
345 }
346
347 /**
348 * Print the content on a pad. Called from ->printClipboard()
349 *
350 * @param string Pad reference
351 * @return array Array with table rows for the clipboard.
352 * @access private
353 */
354 function printContentFromTab($pad) {
355 $lines = array();
356 if (is_array($this->clipData[$pad]['el'])) {
357 foreach ($this->clipData[$pad]['el'] as $k => $v) {
358 if ($v) {
359 list($table, $uid) = explode('|', $k);
360 $bgColClass = ($table == '_FILE' && $this->fileMode) || ($table != '_FILE' && !$this->fileMode) ? 'bgColor4-20' : 'bgColor4';
361
362 if ($table == '_FILE') { // Rendering files/directories on the clipboard:
363 $fileObject = t3lib_file_Factory::getInstance()->retrieveFileOrFolderObject($v);
364 if ($fileObject) {
365 $thumb = '';
366 $folder = $fileObject instanceof t3lib_file_Folder;
367 $size = ($folder ? '' : '(' . t3lib_div::formatSize($fileObject->getSize()) . 'bytes)');
368 $icon = t3lib_iconWorks::getSpriteIconForFile(
369 $folder ? 'folder' : strtolower($fileObject->getExtension()),
370 array('style' => 'margin: 0 20px;', 'title' => $fileObject->getName() . ' ' . $size)
371 );
372
373 if ($this->clipData['_setThumb'] && t3lib_div::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileObject->getExtension())) {
374 $thumb = '<br />' . t3lib_BEfunc::getThumbNail($this->backPath . 'thumbs.php', $v, ' vspace="4"');
375 }
376
377
378 $lines[] = '
379 <tr>
380 <td class="' . $bgColClass . '">' . $icon . '</td>
381 <td class="' . $bgColClass . '" nowrap="nowrap" width="95%">&nbsp;' . $this->linkItemText(htmlspecialchars(t3lib_div::fixed_lgd_cs($fileObject->getName(), $GLOBALS['BE_USER']->uc['titleLen'])), $fileObject->getName()) .
382 ($pad == 'normal' ? (' <strong>(' . ($this->clipData['normal']['mode'] == 'copy' ? $this->clLabel('copy', 'cm') : $this->clLabel('cut', 'cm')) . ')</strong>') : '') . '&nbsp;' . $thumb . '</td>
383 <td class="' . $bgColClass . '" align="center" nowrap="nowrap">' .
384 '<a href="#" onclick="' . htmlspecialchars('top.launchView(\'' . $table . '\', \'' . $v . '\'); return false;') . '">' . t3lib_iconWorks::getSpriteIcon('actions-document-info', array('title' => $this->clLabel('info', 'cm'))) . '</a>' .
385 '<a href="' . htmlspecialchars($this->removeUrl('_FILE', t3lib_div::shortmd5($v))) . '#clip_head">' . t3lib_iconWorks::getSpriteIcon('actions-selection-delete', array('title' => $this->clLabel('removeItem'))) . '</a>' .
386 '</td>
387 </tr>';
388 } else {
389 // If the file did not exist (or is illegal) then it is removed from the clipboard immediately:
390 unset($this->clipData[$pad]['el'][$k]);
391 $this->changed = 1;
392 }
393 } else { // Rendering records:
394 $rec = t3lib_BEfunc::getRecordWSOL($table, $uid);
395 if (is_array($rec)) {
396 $lines[] = '
397 <tr>
398 <td class="' . $bgColClass . '">' . $this->linkItemText(t3lib_iconWorks::getSpriteIconForRecord($table, $rec, array('style' => 'margin: 0 20px;', 'title' => htmlspecialchars(t3lib_BEfunc::getRecordIconAltText($rec, $table)))), $rec, $table) . '</td>
399 <td class="' . $bgColClass . '" nowrap="nowrap" width="95%">&nbsp;' . $this->linkItemText(htmlspecialchars(t3lib_div::fixed_lgd_cs(t3lib_BEfunc::getRecordTitle($table, $rec), $GLOBALS['BE_USER']->uc['titleLen'])), $rec, $table) .
400 ($pad == 'normal' ? (' <strong>(' . ($this->clipData['normal']['mode'] == 'copy' ? $this->clLabel('copy', 'cm') : $this->clLabel('cut', 'cm')) . ')</strong>') : '') . '&nbsp;</td>
401 <td class="' . $bgColClass . '" align="center" nowrap="nowrap">' .
402 '<a href="#" onclick="' . htmlspecialchars('top.launchView(\'' . $table . '\', \'' . intval($uid) . '\'); return false;') . '">' . t3lib_iconWorks::getSpriteIcon('actions-document-info', array('title' => $this->clLabel('info', 'cm'))) . '</a>' .
403 '<a href="' . htmlspecialchars($this->removeUrl($table, $uid)) . '#clip_head">' . t3lib_iconWorks::getSpriteIcon('actions-selection-delete', array('title' => $this->clLabel('removeItem'))) . '</a>' .
404 '</td>
405 </tr>';
406
407 $localizationData = $this->getLocalizations($table, $rec, $bgColClass, $pad);
408 if ($localizationData) {
409 $lines[] = $localizationData;
410 }
411
412 } else {
413 unset($this->clipData[$pad]['el'][$k]);
414 $this->changed = 1;
415 }
416 }
417 }
418 }
419 }
420 if (!count($lines)) {
421 $lines[] = '
422 <tr>
423 <td class="bgColor4"><img src="clear.gif" width="56" height="1" alt="" /></td>
424 <td colspan="2" class="bgColor4" nowrap="nowrap" width="95%">&nbsp;<em>(' . $this->clLabel('clipNoEl') . ')</em>&nbsp;</td>
425 </tr>';
426 }
427
428 $this->endClipboard();
429 return $lines;
430 }
431
432
433 /**
434 * Gets all localizations of the current record.
435 *
436 * @param string the table
437 * @param array the current record
438 * @return string HTML table rows
439 */
440 function getLocalizations($table, $parentRec, $bgColClass, $pad) {
441 $lines = array();
442 $tcaCtrl = $GLOBALS['TCA'][$table]['ctrl'];
443
444 if ($table != 'pages' && t3lib_BEfunc::isTableLocalizable($table) && !$tcaCtrl['transOrigPointerTable']) {
445 $where = array();
446 $where[] = $tcaCtrl['transOrigPointerField'] . '=' . intval($parentRec['uid']);
447 $where[] = $tcaCtrl['languageField'] . '<>0';
448
449 if (isset($tcaCtrl['delete']) && $tcaCtrl['delete']) {
450 $where[] = $tcaCtrl['delete'] . '=0';
451 }
452
453 if (isset($tcaCtrl['versioningWS']) && $tcaCtrl['versioningWS']) {
454 $where[] = 't3ver_wsid=' . $parentRec['t3ver_wsid'];
455 }
456
457 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', $table, implode(' AND ', $where));
458
459 if (is_array($rows)) {
460 $modeData = '';
461 if ($pad == 'normal') {
462 $mode = ($this->clipData['normal']['mode'] == 'copy' ? 'copy' : 'cut');
463 $modeData = ' <strong>(' . $this->clLabel($mode, 'cm') . ')</strong>';
464 }
465
466 foreach ($rows as $rec) {
467 $lines[] = '
468 <tr>
469 <td class="' . $bgColClass . '">' .
470 t3lib_iconWorks::getSpriteIconForRecord($table, $rec, array('style' => "margin-left: 38px;")) . '</td>
471 <td class="' . $bgColClass . '" nowrap="nowrap" width="95%">&nbsp;' . htmlspecialchars(
472 t3lib_div::fixed_lgd_cs(t3lib_BEfunc::getRecordTitle($table, $rec), $GLOBALS['BE_USER']->uc['titleLen'])) .
473 $modeData . '&nbsp;</td>
474 <td class="' . $bgColClass . '" align="center" nowrap="nowrap">&nbsp;</td>
475 </tr>';
476 }
477 }
478 }
479 return implode('', $lines);
480 }
481
482
483 /**
484 * Wraps title of pad in bold-tags and maybe the number of elements if any.
485 *
486 * @param string String (already htmlspecialchars()'ed)
487 * @param string Pad reference
488 * @return string HTML output (htmlspecialchar'ed content inside of tags.)
489 */
490 function padTitleWrap($str, $pad) {
491 $el = count($this->elFromTable($this->fileMode ? '_FILE' : '', $pad));
492 if ($el) {
493 return '<strong>' . $str . '</strong> (' . ($pad == 'normal' ? ($this->clipData['normal']['mode'] == 'copy' ? $this->clLabel('copy', 'cm') : $this->clLabel('cut', 'cm')) : htmlspecialchars($el)) . ')';
494 } else {
495 return $GLOBALS['TBE_TEMPLATE']->dfw($str);
496 }
497 }
498
499 /**
500 * Wraps the title of the items listed in link-tags. The items will link to the page/folder where they originate from
501 *
502 * @param string Title of element - must be htmlspecialchar'ed on beforehand.
503 * @param mixed If array, a record is expected. If string, its a path
504 * @param string Table name
505 * @return string
506 */
507 function linkItemText($str, $rec, $table = '') {
508 if (is_array($rec) && $table) {
509 if ($this->fileMode) {
510 $str = $GLOBALS['TBE_TEMPLATE']->dfw($str);
511 } else {
512 if (t3lib_extMgm::isLoaded('recordlist')) {
513 $str = '<a href="' . htmlspecialchars(
514 t3lib_BEfunc::getModuleUrl(
515 'web_list',
516 array('id' => $rec['pid']),
517 $this->backPath)
518 ) . '">' . $str . '</a>';
519 }
520 }
521 } elseif (file_exists($rec)) {
522 if (!$this->fileMode) {
523 $str = $GLOBALS['TBE_TEMPLATE']->dfw($str);
524 } else {
525 if (t3lib_extMgm::isLoaded('filelist')) {
526 $str = '<a href="' . htmlspecialchars(
527 $this->backPath . t3lib_extMgm::extRelPath('filelist') . 'mod1/file_list.php?id=' . dirname($rec)
528 ) . '">' . $str . '</a>';
529 }
530 }
531 }
532 return $str;
533 }
534
535 /**
536 * Returns the select-url for database elements
537 *
538 * @param string Table name
539 * @param integer Uid of record
540 * @param boolean If set, copymode will be enabled
541 * @param boolean If set, the link will deselect, otherwise select.
542 * @param array The base array of GET vars to be sent in addition. Notice that current GET vars WILL automatically be included.
543 * @return string URL linking to the current script but with the CB array set to select the element with table/uid
544 */
545 function selUrlDB($table, $uid, $copy = 0, $deselect = 0, $baseArray = array()) {
546 $CB = array('el' => array(rawurlencode($table . '|' . $uid) => $deselect ? 0 : 1));
547 if ($copy) {
548 $CB['setCopyMode'] = 1;
549 }
550 $baseArray['CB'] = $CB;
551 return t3lib_div::linkThisScript($baseArray);
552 }
553
554 /**
555 * Returns the select-url for files
556 *
557 * @param string Filepath
558 * @param boolean If set, copymode will be enabled
559 * @param boolean If set, the link will deselect, otherwise select.
560 * @param array The base array of GET vars to be sent in addition. Notice that current GET vars WILL automatically be included.
561 * @return string URL linking to the current script but with the CB array set to select the path
562 */
563 function selUrlFile($path, $copy = 0, $deselect = 0, $baseArray = array()) {
564 $CB = array('el' => array(rawurlencode('_FILE|' . t3lib_div::shortmd5($path)) => $deselect ? '' : $path));
565 if ($copy) {
566 $CB['setCopyMode'] = 1;
567 }
568 $baseArray['CB'] = $CB;
569 return t3lib_div::linkThisScript($baseArray);
570 }
571
572 /**
573 * pasteUrl of the element (database and file)
574 * For the meaning of $table and $uid, please read from ->makePasteCmdArray!!!
575 * The URL will point to tce_file or tce_db depending in $table
576 *
577 * @param string Tablename (_FILE for files)
578 * @param mixed "destination": can be positive or negative indicating how the paste is done (paste into / paste after)
579 * @param boolean If set, then the redirect URL will point back to the current script, but with CB reset.
580 * @return string
581 */
582 function pasteUrl($table, $uid, $setRedirect = 1) {
583 $rU = $this->backPath . ($table == '_FILE' ? 'tce_file.php' : 'tce_db.php') . '?' .
584 ($setRedirect ? 'redirect=' . rawurlencode(t3lib_div::linkThisScript(array('CB' => ''))) : '') .
585 '&vC=' . $GLOBALS['BE_USER']->veriCode() .
586 '&prErr=1&uPT=1' .
587 '&CB[paste]=' . rawurlencode($table . '|' . $uid) .
588 '&CB[pad]=' . $this->current .
589 t3lib_BEfunc::getUrlToken('tceAction');
590 return $rU;
591 }
592
593 /**
594 * deleteUrl for current pad
595 *
596 * @param boolean If set, then the redirect URL will point back to the current script, but with CB reset.
597 * @param boolean If set, then the URL will link to the tce_file.php script in the typo3/ dir.
598 * @return string
599 */
600 function deleteUrl($setRedirect = 1, $file = 0) {
601 $rU = $this->backPath . ($file ? 'tce_file.php' : 'tce_db.php') . '?' .
602 ($setRedirect ? 'redirect=' . rawurlencode(t3lib_div::linkThisScript(array('CB' => ''))) : '') .
603 '&vC=' . $GLOBALS['BE_USER']->veriCode() .
604 '&prErr=1&uPT=1' .
605 '&CB[delete]=1' .
606 '&CB[pad]=' . $this->current .
607 t3lib_BEfunc::getUrlToken('tceAction');
608 return $rU;
609 }
610
611 /**
612 * editUrl of all current elements
613 * ONLY database
614 * Links to alt_doc.php
615 *
616 * @return string The URL to alt_doc.php with parameters.
617 */
618 function editUrl() {
619 $elements = $this->elFromTable(''); // all records
620 $editCMDArray = array();
621 foreach ($elements as $tP => $value) {
622 list($table, $uid) = explode('|', $tP);
623 $editCMDArray[] = '&edit[' . $table . '][' . $uid . ']=edit';
624 }
625
626 $rU = $this->backPath . 'alt_doc.php?' . implode('', $editCMDArray);
627 return $rU;
628 }
629
630 /**
631 * Returns the remove-url (file and db)
632 * for file $table='_FILE' and $uid = shortmd5 hash of path
633 *
634 * @param string Tablename
635 * @param string uid integer/shortmd5 hash
636 * @return string URL
637 */
638 function removeUrl($table, $uid) {
639 return t3lib_div::linkThisScript(array('CB' => array('remove' => $table . '|' . $uid)));
640 }
641
642 /**
643 * Returns confirm JavaScript message
644 *
645 * @param string Table name
646 * @param mixed For records its an array, for files its a string (path)
647 * @param string Type-code
648 * @param array Array of selected elements
649 * @return string JavaScript "confirm" message
650 */
651 function confirmMsg($table, $rec, $type, $clElements) {
652 if ($GLOBALS['BE_USER']->jsConfirmation(2)) {
653 $labelKey = 'LLL:EXT:lang/locallang_core.php:mess.' . ($this->currentMode() == 'copy' ? 'copy' : 'move') . ($this->current == 'normal' ? '' : 'cb') . '_' . $type;
654 $msg = $GLOBALS['LANG']->sL($labelKey);
655
656 if ($table == '_FILE') {
657 $thisRecTitle = basename($rec);
658 if ($this->current == 'normal') {
659 $selItem = reset($clElements);
660 $selRecTitle = basename($selItem);
661 } else {
662 $selRecTitle = count($clElements);
663 }
664 } else {
665 $thisRecTitle = (
666 $table == 'pages' && !is_array($rec) ?
667 $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] :
668 t3lib_BEfunc::getRecordTitle($table, $rec)
669 );
670
671 if ($this->current == 'normal') {
672 $selItem = $this->getSelectedRecord();
673 $selRecTitle = $selItem['_RECORD_TITLE'];
674 } else {
675 $selRecTitle = count($clElements);
676 }
677 }
678
679 // Message:
680 $conf = 'confirm(' . $GLOBALS['LANG']->JScharCode(sprintf(
681 $msg,
682 t3lib_div::fixed_lgd_cs($selRecTitle, 30),
683 t3lib_div::fixed_lgd_cs($thisRecTitle, 30)
684 )) . ')';
685 } else {
686 $conf = '';
687 }
688 return $conf;
689 }
690
691 /**
692 * Clipboard label - getting from "EXT:lang/locallang_core.php:"
693 *
694 * @param string Label Key
695 * @param string Alternative key to "labels"
696 * @return string
697 */
698 function clLabel($key, $Akey = 'labels') {
699 return htmlspecialchars($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:' . $Akey . '.' . $key));
700 }
701
702 /**
703 * Creates GET parameters for linking to the export module.
704 *
705 * @return string GET parameters for current clipboard content to be exported.
706 */
707 function exportClipElementParameters() {
708
709 // Init:
710 $pad = $this->current;
711 $params = array();
712 $params[] = 'tx_impexp[action]=export';
713
714 // Traverse items:
715 if (is_array($this->clipData[$pad]['el'])) {
716 foreach ($this->clipData[$pad]['el'] as $k => $v) {
717 if ($v) {
718 list($table, $uid) = explode('|', $k);
719
720 if ($table == '_FILE') { // Rendering files/directories on the clipboard:
721 if (file_exists($v) && t3lib_div::isAllowedAbsPath($v)) {
722 $params[] = 'tx_impexp[' . (is_dir($v) ? 'dir' : 'file') . '][]=' . rawurlencode($v);
723 }
724 } else { // Rendering records:
725 $rec = t3lib_BEfunc::getRecord($table, $uid);
726 if (is_array($rec)) {
727 $params[] = 'tx_impexp[record][]=' . rawurlencode($table . ':' . $uid);
728 }
729 }
730 }
731 }
732 }
733
734 return '?' . implode('&', $params);
735 }
736
737
738 /*****************************************
739 *
740 * Helper functions
741 *
742 ****************************************/
743
744 /**
745 * Removes element on clipboard
746 *
747 * @param string Key of element in ->clipData array
748 * @return void
749 */
750 function removeElement($el) {
751 unset($this->clipData[$this->current]['el'][$el]);
752 $this->changed = 1;
753 }
754
755 /**
756 * Saves the clipboard, no questions asked.
757 * Use ->endClipboard normally (as it checks if changes has been done so saving is necessary)
758 *
759 * @return void
760 * @access private
761 */
762 function saveClipboard() {
763 $GLOBALS['BE_USER']->pushModuleData('clipboard', $this->clipData);
764 }
765
766 /**
767 * Returns the current mode, 'copy' or 'cut'
768 *
769 * @return string "copy" or "cut"
770 */
771 function currentMode() {
772 return $this->clipData[$this->current]['mode'] == 'copy' ? 'copy' : 'cut';
773 }
774
775 /**
776 * This traverses the elements on the current clipboard pane
777 * and unsets elements which does not exist anymore or are disabled.
778 *
779 * @return void
780 */
781 function cleanCurrent() {
782 if (is_array($this->clipData[$this->current]['el'])) {
783 foreach ($this->clipData[$this->current]['el'] as $k => $v) {
784 list($table, $uid) = explode('|', $k);
785 if ($table != '_FILE') {
786 if (!$v || !is_array(t3lib_BEfunc::getRecord($table, $uid, 'uid'))) {
787 unset($this->clipData[$this->current]['el'][$k]);
788 $this->changed = 1;
789 }
790 } else {
791 if (!$v || t3lib_file_Factory::getInstance()->retrieveFileOrFolderObject($v) === NULL) {
792 unset($this->clipData[$this->current]['el'][$k]);
793 $this->changed = 1;
794 }
795 }
796 }
797 }
798 }
799
800 /**
801 * Counts the number of elements from the table $matchTable. If $matchTable is blank, all tables (except '_FILE' of course) is counted.
802 *
803 * @param string Table to match/count for.
804 * @param string $pad can optionally be used to set another pad than the current.
805 * @return array Array with keys from the CB.
806 */
807 function elFromTable($matchTable = '', $pad = '') {
808 $pad = $pad ? $pad : $this->current;
809 $list = array();
810 if (is_array($this->clipData[$pad]['el'])) {
811 foreach ($this->clipData[$pad]['el'] as $k => $v) {
812 if ($v) {
813 list($table, $uid) = explode('|', $k);
814 if ($table != '_FILE') {
815 if ((!$matchTable || (string) $table == (string) $matchTable) && $GLOBALS['TCA'][$table]) {
816 $list[$k] = ($pad == 'normal' ? $v : $uid);
817 }
818 } else {
819 if ((string) $table == (string) $matchTable) {
820 $list[$k] = $v;
821 }
822 }
823 }
824 }
825 }
826 return $list;
827 }
828
829 /**
830 * Verifies if the item $table/$uid is on the current pad.
831 * If the pad is "normal", the mode value is returned if the element existed. Thus you'll know if the item was copy or cut moded...
832 *
833 * @param string Table name, (_FILE for files...)
834 * @param integer Element uid (path for files)
835 * @return string
836 */
837 function isSelected($table, $uid) {
838 $k = $table . '|' . $uid;
839 return $this->clipData[$this->current]['el'][$k] ? ($this->current == 'normal' ? $this->currentMode() : 1) : '';
840 }
841
842 /**
843 * Returns item record $table,$uid if selected on current clipboard
844 * If table and uid is blank, the first element is returned.
845 * Makes sense only for DB records - not files!
846 *
847 * @param string Table name
848 * @param integer Element uid
849 * @return array Element record with extra field _RECORD_TITLE set to the title of the record...
850 */
851 function getSelectedRecord($table = '', $uid = '') {
852 if (!$table && !$uid) {
853 $elArr = $this->elFromTable('');
854 reset($elArr);
855 list($table, $uid) = explode('|', key($elArr));
856 }
857 if ($this->isSelected($table, $uid)) {
858 $selRec = t3lib_BEfunc::getRecordWSOL($table, $uid);
859 $selRec['_RECORD_TITLE'] = t3lib_BEfunc::getRecordTitle($table, $selRec);
860 return $selRec;
861 }
862 }
863
864 /**
865 * Reports if the current pad has elements (does not check file/DB type OR if file/DBrecord exists or not. Only counting array)
866 *
867 * @return boolean TRUE if elements exist.
868 */
869 function isElements() {
870 return is_array($this->clipData[$this->current]['el']) && count($this->clipData[$this->current]['el']);
871 }
872
873
874 /*****************************************
875 *
876 * FOR USE IN tce_db.php:
877 *
878 ****************************************/
879
880 /**
881 * Applies the proper paste configuration in the $cmd array send to tce_db.php.
882 * $ref is the target, see description below.
883 * The current pad is pasted
884 *
885 * $ref: [tablename]:[paste-uid].
886 * tablename is the name of the table from which elements *on the current clipboard* is pasted with the 'pid' paste-uid.
887 * No tablename means that all items on the clipboard (non-files) are pasted. This requires paste-uid to be positive though.
888 * so 'tt_content:-3' means 'paste tt_content elements on the clipboard to AFTER tt_content:3 record
889 * 'tt_content:30' means 'paste tt_content elements on the clipboard into page with id 30
890 * ':30' means 'paste ALL database elements on the clipboard into page with id 30
891 * ':-30' not valid.
892 *
893 * @param string [tablename]:[paste-uid], see description
894 * @param array Command-array
895 * @return array Modified Command-array
896 */
897 function makePasteCmdArray($ref, $CMD) {
898 list($pTable, $pUid) = explode('|', $ref);
899 $pUid = intval($pUid);
900
901 if ($pTable || $pUid >= 0) { // pUid must be set and if pTable is not set (that means paste ALL elements) the uid MUST be positive/zero (pointing to page id)
902 $elements = $this->elFromTable($pTable);
903
904 $elements = array_reverse($elements); // So the order is preserved.
905 $mode = $this->currentMode() == 'copy' ? 'copy' : 'move';
906
907 // Traverse elements and make CMD array
908 foreach ($elements as $tP => $value) {
909 list($table, $uid) = explode('|', $tP);
910 if (!is_array($CMD[$table])) {
911 $CMD[$table] = array();
912 }
913 $CMD[$table][$uid][$mode] = $pUid;
914 if ($mode == 'move') {
915 $this->removeElement($tP);
916 }
917 }
918 $this->endClipboard();
919 }
920 return $CMD;
921 }
922
923 /**
924 * Delete record entries in CMD array
925 *
926 * @param array Command-array
927 * @return array Modified Command-array
928 */
929 function makeDeleteCmdArray($CMD) {
930 $elements = $this->elFromTable(''); // all records
931 foreach ($elements as $tP => $value) {
932 list($table, $uid) = explode('|', $tP);
933 if (!is_array($CMD[$table])) {
934 $CMD[$table] = array();
935 }
936 $CMD[$table][$uid]['delete'] = 1;
937 $this->removeElement($tP);
938 }
939 $this->endClipboard();
940 return $CMD;
941 }
942
943
944 /*****************************************
945 *
946 * FOR USE IN tce_file.php:
947 *
948 ****************************************/
949
950 /**
951 * Applies the proper paste configuration in the $file array send to tce_file.php.
952 * The current pad is pasted
953 *
954 * @param string Reference to element (splitted by "|")
955 * @param array Command-array
956 * @return array Modified Command-array
957 */
958 function makePasteCmdArray_file($ref, $FILE) {
959 list($pTable, $pUid) = explode('|', $ref);
960 $elements = $this->elFromTable('_FILE');
961 $mode = $this->currentMode() == 'copy' ? 'copy' : 'move';
962
963 // Traverse elements and make CMD array
964 foreach ($elements as $tP => $path) {
965 $FILE[$mode][] = array('data' => $path, 'target' => $pUid, 'altName' => 1);
966 if ($mode == 'move') {
967 $this->removeElement($tP);
968 }
969 }
970 $this->endClipboard();
971
972 return $FILE;
973 }
974
975 /**
976 * Delete files in CMD array
977 *
978 * @param array Command-array
979 * @return array Modified Command-array
980 */
981 function makeDeleteCmdArray_file($FILE) {
982 $elements = $this->elFromTable('_FILE');
983 // Traverse elements and make CMD array
984 foreach ($elements as $tP => $path) {
985 $FILE['delete'][] = array('data' => $path);
986 $this->removeElement($tP);
987 }
988 $this->endClipboard();
989
990 return $FILE;
991 }
992 }
993
994
995 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_clipboard.php'])) {
996 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_clipboard.php']);
997 }
998
999 ?>